JAVA快速入门(1)

引言

为了应付大作业,特地速成一哈JVAV

省略了一堆东西

估计过几天会继续写后篇,到时候再看吧。

内容包括

  • 语法快速入门(这玩意和cpp大部分很像所以没咋写)
  • 面向对象基础
  • 杂项
  • 一些核心类

声明

和cpp不同的部分

1
2
int[] a = new int[5];	//数组
var a = new int[5]; //自动类型推导

ps.

任何数组都是引用类型!

string也是!

实例化的对象也是!

这时候要判断是不是相等要用

a.equals(b)的方法

这个时候赋值是引用类型参数绑定

感觉有点像指针。。还有那个python的原理


方法

可变参数

类似函数传入数组,用类型...定义

1
2
3
4
5
6
7
class Group {
private String[] names;

public void setNames(String... names) {
this.names = names;
}
}

传入可以直接传入多个string

构造方法

类构造时调用的方法 构造函数

可以重载

1
2
3
class Group {
public Group{}
}

实例化

1
A a = new A();

类的一些东西

继承

java是单继承的,用extends关键字

1
2
class B extends A{
}

经典protected类型,令子类可以访问父类的内容

很显然,子类不应该定义和父类重名的字段,private也不行

super

super代表了父类,super();即父类的构造方法

实例化类的时候,会默认调用一个无参的super();

如果此时父类没有无参构造方法会报错

解决方法是手动在类构造函数上加一句父类对应的super(xxxx);

子类不会继承任何父类的构造方法

阻止继承

感觉暂时用不上

1
2
public sealed class A permits B, C {
}

sealedpermits可以让只有指定的类才能继承该类

上/下转型

继承树object>a>b

向上:

直接用引用变量指向子类实例就行

1
A a = new B();

向下:

父类类型强转到子类类型

1
2
3
A a = new B();
B b = new B();
b = (B)a;

instanceof为操作符,判断一个东西是不是指定类型

1
2
3
4
5
6
7
8
9
Object obj = "hello";
if (obj instanceof String) {
String s = (String) obj;
}
//或者可以直接一起转型
Object obj = "hello";
if (obj instanceof String s) {// 可以直接使用变量s
System.out.println(s.toUpperCase());
}

这种转型有时候我们在方法中传递形参为父类,又想调用子类的方法时,在确定了传入实参为子类后可以进行一个强转。

多态

override

首先说明方法签名:

  • 方法名
  • 参数列表

如果子类的一个方法方法签名和父类的完全一致,则子类会覆写父类的方法

使用@Override修饰,编译器还会帮助检查是否为覆写而非重载

@Override并非必须

java调用方法时根据的是对象真正的类型而不是引用的类型进行调用

多态

多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法

如果调用父类被覆写了的方法

可以使用super.方法名()来调用

final 感觉类似const

final修饰的类无法继承,final修饰的方法不会被覆写,final修饰的变量初始化之后无法更改

抽象类

类似cpp里边的虚函数,其实就是父类单纯提供方法签名而不实现任何功能,即抽象方法的时候用的。

这样就能构成多态。

使用abstract修饰就完了,定义了抽象方法的类也要一样地修饰,这就是抽象类

和cpp一样抽象类无法实例化

1
2
3
abstract class Person {
public abstract void run();
}

所有这些东西的主要思想其实就是呃(抄的)

  • 上层代码只定义规范(例如:abstract class Person);
  • 不需要子类就可以实现业务逻辑(正常编译);
  • 具体的业务逻辑由不同的子类实现,调用者并不关心。

接口

接口本质是更抽象的抽象类

如果一个抽象类没有字段,所有方法全部都是抽象方法,就可以用接口改写。

使用interface声明,这里边的东西直接默认是public abstract

1
2
3
4
interface A {
void run();
String asdf();
}

那么我们该如何使用这玩意呢

使用implements实现,

而且一个类可以实现多个接口

1
2
3
class Student implements Person, Hello { // 实现了两个interface
...
}

有关接口继承

这玩意看着好复杂…

一个interface可以继承自另一个interfaceinterface继承自interface使用extends,它相当于扩展了接口的方法。

我们还可以定义default方法,

这个相当于抽象类中有具体实现的那些方法。

这样继承这个接口的所有子类也可以直接用这个方法。

1
2
3
4
5
6
7
8
9
10
interface A {
void run();
default String asdf();
}

class B implements A{
void run(){
asdf();
}
}

一些杂项

静态字段

静态字段啥的跟cpp类里边的差不多,静态方法是可以直接用方法名调用,类似正常的函数,但是他显然不能访问实例的非静态字段

使用static修饰,懂得都懂(

类似命名空间

Java定义了一种名字空间,称之为包:package。一个类总是属于某个包,类名(比如Person)只是一个简写,真正的完整类名是包名.类名

位于同一个包的类,可以访问包作用域的字段和方法。不用publicprotectedprivate修饰的字段和方法就是包作用域。

import

使用import语句,导入包中的类或者子包

在写import的时候,可以使用*,表示把这个包下面的所有class都导入进来(但不包括子包的class

还有一种import static的语法,它可以导入可以导入一个类的静态字段和静态方法。

作用域

感觉不用写。

一个是java支持嵌套类,内部的类也可以访问``private`

内部类

嵌套类,可以声明可以匿名

在方法内部定义一个匿名类,这玩意其实就是一个东西继承自某个父类,然后重写一下里边的方法?

1
2
3
Runnable r = new 父类类名() {
// 实现必要的抽象方法...
};

classpath和jar

不会

jar包相当于zip包,其实就是把编译好的一堆.class文件打包到一起便于管理

模块

应该是依赖管理之类的,懒得看了


JAVA的一些核心类

怎么都nm4点了,写完这段歇了(

String

1
String s = "eee";

首字母大写(

String不可变

由于是引用类型,我们要用s1.equals(s2)这种来判断是否相同

equalsIgnoreCase()方法忽略大小写比较

一堆方法啊。。

直接抄了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 是否包含子串:
"Hello".contains("ll"); // true

"Hello".indexOf("l"); // 2
"Hello".lastIndexOf("l"); // 3
"Hello".startsWith("He"); // true
"Hello".endsWith("lo"); // true

"Hello".substring(2); // "llo"
"Hello".substring(2, 4); //"ll"
// 使用trim()方法可以移除字符串首尾空白字符。空白字符包括空格,\t,\r,\n:
" \tHello\r\n ".trim(); // "Hello"

"".isEmpty(); // true,因为字符串长度为0
" ".isEmpty(); // false,因为字符串长度不为0
" \n".isBlank(); // true,因为只包含空白字符
" Hello ".isBlank(); // false,因为包含非空白字符

String s = "hello";
s.replace('l', 'w'); // "hewwo",所有字符'l'被替换为'w'
s.replace("ll", "~~"); // "he~~o",所有子串"ll"被替换为"~~"

replace还支持正则,没学过


String[] arr = {"A", "B", "C"};
String s = String.join("***", arr); // "A***B***C"


String.valueOf(123); // "123"
String.valueOf(45.67); // "45.67"
String.valueOf(true); // "true"
String.valueOf(new Object()); // 类似java.lang.Object@636be97c

char[] cs = "Hello".toCharArray(); // String -> char[]
String s = new String(cs); // char[] -> String

还要byte字符串编码啥的,这玩意我感觉需要就火速百度就完了。

StringBuilder

String可以直接用+拼接,但是效率不高。

如果要一直添加字符的话可以用这个玩意

1
2
3
4
5
6
StringBuilder sb = new StringBuilder(1024);
for (int i = 0; i < 1000; i++) {
sb.append(',');
sb.append(i);
}
String s = sb.toString();

支持链式操作,就是说可以一直.append().append()...之类的

还有个insert方法,要给插入的index和内容

不过链式操作只要函数结束之后返回对象引用就行了吧(

谁叫这玩意啥都是引用

包装类型

意思就是类似int这种基本类型用类进行了包装,可以使用引用和一些奇奇怪怪的方法。

进行一个抄

基本类型 对应的引用类型
boolean java.lang.Boolean
byte java.lang.Byte
short java.lang.Short
int java.lang.Integer
long java.lang.Long
float java.lang.Float
double java.lang.Double
char java.lang.Character

int的转换示例

1
2
3
4
5
6
int i = 100;
Integer n = Integer.valueOf(i);
int x = n.intValue();
你甚至可以这么写
Integer n = 100; // 编译器自动使用Integer.valueOf(int)
int x = n; // 编译器自动使用Integer.intValue()

很显然这个Integer.valueOf(i)是静态方法,而且这玩意实现有优化,比new Integer(i)效率更高,因为他返回给引用的可能是以前就已经存在的实例

当然,这些B东西都是不可更改的。。

静态方法parseInt()可以把字符串解析成一个整数

枚举类

例如我要定义周一到周日这7天,而且我不想让这7天以外的符号和他进行操作,就可以用enum关键字声明

1
2
3
4
5
6
7
8
9
10
11
12
13
enum Weekday {
SUN, MON, TUE, WED, THU, FRI, SAT;
}

本质来说感觉是这样,别问为啥例子变了,我也不知道
public final class Color extends Enum { // 继承自Enum,标记为final class
// 每个实例均为全局唯一:
public static final Color RED = new Color();
public static final Color GREEN = new Color();
public static final Color BLUE = new Color();
// private构造方法,确保外部无法调用new操作符:
private Color() {}
}

我个人感觉这些其实就是抽象符号,而且拥有static final的属性

这样就不会有类型外的值和非枚举类内的值相互比较了

因为有static的属性,我们显然可以用==进行比较

有方法name()返回常量名

1
String s = Weekday.SUN.name(); // "SUN"

ordinal()返回定义的常量的顺序,从0开始计数

1
int n = Weekday.MON.ordinal(); // 1

既然这玩意本质是类,我们也可以在里边改写构造方法,给它加上一些值

1
2
3
4
5
6
7
8
9
enum Weekday {
MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6), SUN(0);

public final int dayValue;

private Weekday(int dayValue) {
this.dayValue = dayValue;
}
}

这样我们可以访问引用的daValue值获得信息。。

记录类

用来记录数据的不变类,写的更方便

1
public record A(int x, int y){}

可以改写构造方法加上判断

BigInteger

高精度,用它给你的方法就完了。

实例化的时候要用字符串

BigDecimal

和上边那个差不多呃

通过BigDecimalstripTrailingZeros()方法,可以将一个BigDecimal格式化为一个相等的,但去掉了末尾0的BigDecimal

工具类

  • Math:数学计算
  • Random:生成伪随机数
  • SecureRandom:生成安全的随机数

呃这个感觉没啥好说的

Math

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Math.abs(-100); // 100
Math.abs(-7.8); // 7.8

Math.max(100, 99); // 100
Math.min(1.2, 2.3); // 1.2

Math.pow(2, 10); // 2的10次方=1024
Math.sqrt(2); // 1.414...
Math.exp(2); // 7.389...
Math.log(4); // 1.386...
Math.log10(100); // 2
Math.sin(3.14); // 0.00159...
Math.cos(3.14); // -0.9999...
Math.tan(3.14); // -0.0015...
Math.asin(1.0); // 1.57079...
Math.acos(1.0); // 0.0

double pi = Math.PI; // 3.14159...
double e = Math.E; // 2.7182818...
Math.sin(Math.PI / 6); // sin(π/6) = 0.5
0-1
Math.random(); // 0.53907... 每次都不一样

Random

1
2
3
4
5
6
7
Random r = new Random(种子);
r.nextInt(); // 2071575453,每次都不一样
r.nextInt(10); // 5,生成一个[0,10)之间的int
r.nextLong(); // 8811649292570369305,每次都不一样
r.nextFloat(); // 0.54335...生成一个[0,1)之间的float
r.nextDouble(); // 0.3716...生成一个[0,1)之间的double
r.nextBytes();

SecureRandom

1
SecureRandom sr = new SecureRandom();

然后疯狂的用就完了


DONE!!!!!