CS109 考前复习
回顾
-
基本数据类型
- 个,String 不是哦!
-
变量名命名规则
- 只能包含字母、数字、下划线、美元符号,且不能以数字开头。
-
编译
-
Java 源代码(.java 文件)-> 字节码(.class 文件)。字节码(bytecode)是一种中间代码,与平台(操作系统)无关,能被 Java 虚拟机(JVM)执行。
-
编译并运行:
java Main.java arg0 arg1 arg2 ...
,其中arg0 arg1 arg2 ...
是main
方法的参数,也就是public static void main(String[] args)
中的args
数组。 -
编译:
javac Main.java
。 -
运行:
java Main arg0 arg1 arg2 ...
。
-
-
printf 方法
-
switch-case
-
case 后的值必须是编译期已知的常量,不能使用变量或表达式。
-
如果省略 break,代码会继续执行下一个 case,称为贯穿(fall through)。而 default 可以没有 break,因为碰到大括号也会退出。
-
default 可以没有——如果没有匹配的 case 且没有 default 分支,则 switch 块会直接结束。
-
switch 表达式的类型有限制。Java 7 以前,仅支持 byte、short、char 和 int;从 Java 7 开始,还支持 String 和 enum。
-
-
表达式执行顺序
- 按照优先级从高到低的顺序进行计算,同优先级从左到右依次运算。
-
隐式类型转换
-
跨类型赋值或计算时,小范围类型会自动转换为大范围类型。(从大到小则需要强制类型转换,可能损失精度)
-
boolean 和其他任何类型都不能相互转换。
-
在方法调用中,实参类型可以自动提升为形参类型。
1
2
3
4
5
6
7
8
9public class Main {
public static void main(String[] args) {
printNumber(10); // int 自动转换为 double
}
static void printNumber(double num) {
System.out.println("数字: " + num);
}
}
-
-
多态
-
分为编译时多态性(Static Polymorphism)和运行时多态性(Dynamic Polymorphism)。
-
简要地说,能在编译时知道调用哪个方法的,都会在编译时被绑定(bind);反之,编译时看不出来该调用哪个方法的,都会在运行时被绑定。
-
-
重载(Overload)与运行时多态性(Dynamic Polymorphism)
- 名字相同的两个方法,只要参数不完全相同,就可以共存。
-
重写(Override)与编译时多态性(Static Polymorphism)
-
不一定要写
@Override
。 -
子类重写构造器时,需要在第一句调用父类构造器;如果不写,则自动调用父类的无参构造器。(btw,一个类里面如果什么构造器都没写,会自动有一个空构造器,没有参数、方法体也是空的。但如果写了至少一个构造器,那个空构造器就不存在了)
-
static、final 方法和构造器不能被重写。abstract 方法不能被子类 abstract 方法重写。
-
对于重写方法,参数列表必须完全一致;返回值类型必须一致,或是原类型的子类;而访问权限(access level)上子类须与父类一致或更宽松,即:
父类方法访问权限 子类方法允许的访问权限 public
public
protected
protected
,public
包访问权限 包访问权限, protected
,public
private
无法重写
-
-
接口(Interface)
- 不能(直接)被实例化(instanciate)。
-
static
-
static 方法内不能有 this(本对象),也不能有 super(父对象),只能调用其他 static 变量和方法。
-
static 的所有东西都跟类走,所以都只有唯一的一份。
-
static 方法不能被重写(override)。
-
-
final
-
final 基本类型变量:值不能变。
1
2final int MAX_VALUE = 100;
MAX_VALUE = 200; // 编译错误:final 变量不能重新赋值 -
final 引用类型变量:引用的哪个对象不能变,但该对象的内容可以变。
1
2
3final List<String> list = new ArrayList<>();
list.add("Hello"); // 正确,可以修改引用对象的内容
list = new ArrayList<>(); // 编译错误:引用的哪个对象不能修改 -
final 方法:在子类中不能被重写(override)。
-
final 类:不能被继承。
-
-
abstract
-
abstract 方法:没有方法体(以分号结尾),子类必须实现该方法。如果一个类包含抽象方法,该类必须声明为抽象类。
-
abstract 类:不能直接被实例化,只能通过继承来使用。抽象类也可以包含具体方法。如果子类没有实现父类的所有抽象方法,那么该子类也应当是抽象类。
-
-
泛型
1
2
3
4
5
6
7
8
9
10
11public class Main {
public static <T extends Number> double sum(T a, T b) {
return a.doubleValue() + b.doubleValue();
}
public static void main(String[] args) {
System.out.println(sum(10, 20)); // Outputs: 30.0
System.out.println(sum(5.5, 2.2)); // Outputs: 7.7
// sum("10", "20"); // Compile-time error: String is not a subtype of Number
}
}-
尖括号中可以用逗号隔开多个类型参数(type parameter),如
<T1 extends Number, T2, T3>
。 -
这里的 extends 关键字限定了类型参数的上界,即该类型必须是
Number
的子类。
-
-
Comparable 接口与 compareTo 方法
- 实现了 Comparable 接口的类可以直接与同类对象进行比较。例如
a.compareTo(b)
,返回一个 int:为负数,则 ;为 ,则 ;为正数,则 。
- 实现了 Comparable 接口的类可以直接与同类对象进行比较。例如
-
valueOf 方法
-
包装类的 valueOf:将基本类型或字符串转换为相应的包装类对象。
1
2
3
4Character a = Character.valueOf('A'); // 返回 Character 对象
String b = String.valueOf(42); // 将基本类型转换为 String 对象 "42"
Integer c = Integer.valueOf(42); // 将基本类型转换为 Integer 对象
Integer d = Integer.valueOf("42"); // 将字符串转换为 Integer 对象 -
枚举类的 valueOf:用于将字符串转换为对应的枚举常量。
1
2
3
4
5
6
7
8
9
10enum Color {
RED, GREEN, BLUE;
}
public class Main {
public static void main(String[] args) {
Color color = Color.valueOf("RED"); // 转换为枚举常量 Color.RED
System.out.println(color); // 输出:RED
}
} -
可以认为 valueOf 与 toString 互逆。
-
-
instanceof
- 基本语法:
objectName instanceof ClassName
,返回一个布尔值,表示objectName
是否是ClassName
类或其子类的对象。这里ClassName
也可以是接口。
1
2
3
4
5
6
7
8
9
10
11
12
13class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
public class Main {
public static void main(String[] args) {
Animal animal = new Cat();
System.out.println(animal instanceof Cat); // true
System.out.println(animal instanceof Dog); // false
System.out.println(animal instanceof Animal); // true
System.out.println(animal instanceof String); // 报错
}
} - 基本语法:
思考
-
一般使用哪两个关键字来一同修饰编译期常量?
-
一个方法或类,可以同时被 abstract 和 final 修饰吗?
-
预测输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class Animal {
public void speak() {
System.out.println("This is an animal!");
}
}
class Dog extends Animal {
public void speak() {
System.out.println("This is a dog!");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog();
myAnimal.speak();
}
} -
预测输出:
1
2
3
4
5
6
7
8
9
10
11
12class Animal {
public static void speak() {
System.out.println("This is an animal!");
}
}
class Dog extends Animal {}
public class Main {
public static void main(String[] args) {
Dog.speak();
}
} -
预测输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class Animal {
public static void speak() {
System.out.println("This is an animal!");
}
}
class Dog extends Animal {
public static void speak() {
System.out.println("This is a dog!");
}
}
public class Main {
public static void main(String[] args) {
Animal.speak();
Dog.speak();
Animal myAnimal = new Dog();
myAnimal.speak();
((Dog) myAnimal).speak();
}
} -
预测输出:
1
2
3
4
5
6
7
8public class Main {
public static void main(String[] args) {
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);
System.out.println(a.equals(b));
}
} -
预测输出:
1
2
3
4
5
6
7
8
9public class Main {
public static void main(String[] args) {
String a = new String("Hello");
String b = a;
a += " World";
System.out.println(a == b);
System.out.println(a.equals(b));
}
} -
预测输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class Dog extends Animal {
public Dog(int age) {
System.out.println("This is a dog!");
}
public static void main(String[] args) {
Animal myAnimal = new Dog(10);
}
}
class Animal {
protected int age;
public Animal(int age) {
this.age = age;
System.out.println("This is an animal!");
}
}
答案
-
static 和 final。static 使该变量会在编译期就被确定,final 使该变量不能被修改。
-
不可以。abstract 表示子类必须实现,final 表示子类不能重写(override),二者相矛盾。
-
答案:
1
This is a dog!
-
答案:
1
This is an animal!
如果子类中找不到某 static 方法,会在其父类中寻找。
-
答案:
1
2
3
4This is an animal!
This is a dog!
This is an animal!
This is a dog!使用
objectName.methodName
来调用静态方法,取决于objectName
被声明为哪个类,与它实际是谁的对象无关。 -
答案:
1
2false
true对于引用类型,
==
只判断二者是否指向同一个地址;String 类型使用 equals 方法实现真正的判等。 -
答案:
1
2false
falsea
被修改过后是Hello World
,这是一个新的对象;而b
仍然是Hello
。所以二者无论如何都不相等。 -
答案:
1
Complication Error
子类构造器第一行没有调用父类构造器,且父类也没有无参构造器。