03-面向对象编程高级
1. 内部类
1.1. 成员内部类
类中的普通成员,拥有者是对象,(对象的内部类)。
和实例方法一样,成员内部类的实例方法,可以访问外部类的实例成员,静态成员。
语法:外部类名.内部类名 名字 = new 外部类名().new 内部类名();
public class OuterClass {
public class InnerClass {
//JDK 16 之前,不能用静态成员。
//OuterClass.this 当前外部类的对象
}
}
1.2. 静态内部类
类的内部类。有 static 修饰的内部类。不能直接访问外部类的实例成员。
语法:外部类名.内部类名 名字 = 外部类名.内部类名();
1.3. 局部内部类
定义在执行体 { } 里的类。
鸡肋语法,不咋用。
1.4. 匿名内部类
本质是一个子类,使用的地方,会返回一个实例对象。
匿名内部类默认类名是 当前类名&编号
通常作为一个实参传给方法,例如:动态代理创建代理对象。
语法:
// 方便创建子类对象的语法。 联想到类lambda式
new 类或接口(参数) {
// 方法的重写
@Override
...
}
2. 枚举
2.1. 是什么?
枚举是一个特殊的类。
- 第一行只能是名字用逗号
,隔开,分割号;结束。 - 名字的本质是常量,类型是引用数据类型(该枚举类)。
语法
修饰符 enum 枚举类 {
名字1,名字2,名字3等;
其他成员
}
2.2. 特点
通过反编译,看到枚举的特点:
public enum A{
X , Y , Z;
}
//Compiled from “A.java"
public final class A extends java.lang.Enum<A> {
public static final A X = new A();
public static final A Y = new A();
public static final A Z = new A();
public static A[] values();
public static A valueOf(java.lang.String);
}
- 枚举是最终类,不能被继承。
- 枚举类继承了 java. lang. Enum
- 枚举类的第一行只能写名字,这些名字都是常量(常量必须初始化)。从第二行开始可以写其他的成员。
- 枚举类的构造器是私有的。枚举类对外不能创建对象。
2.3. 用枚举实现单例设计模式
2.4. 使用场景
常量和枚举都表示一组信息,作为参数传递。
- 使用常量
- 不能约束参数值
- 用枚举,
- 能约束参数值
- 代码可读性更好
- 缺点:占用堆内存。
例子
3. 泛型和通配符
泛型让类、接口、方法更通用。
3.1. 泛型类、泛型接口
语法
修饰符 class 名字<类型变量,类型变量...> {
}
修饰符 interface 名字<类型变量,类型变量...> {
}
类型变量建议(约定大于强制)大写英文字母:
- T Type 最常用的泛型参数,表示任意类型。
public class Box<T> { ... } - E Element 常用于集合类中表示元素的类
public class List<E> { ... } - K key 映射(如
Map)中的键类型- public class Map<K, V> { ... } - V value 映射(如
Map)中的值类型,通常与K配对使用 - N Number 表示方法返回值的类型(常见于函数式接口)
public interface Function<T, R> { R apply(T t); } - R Return
- 当需要多个类型变量时,按字母顺序扩展(如
T,U,V)
3.2. 泛型方法和通配符
语法
// 类型变量 使用在声明上,方法体内不能。
修饰符 <类型变量,...> 返回值类型 方法名(形参列表) {
...
}
父子,上下。
- 通配符是
?在泛型中表示一切类型。 - 泛型上限
? extends Car,该泛型的上限是 Car,表示汽车类,或子类。 - 泛型下限
? super Car该泛型的下限是 Car,表示汽车类,或父类。
3.3. 泛型擦除
泛型的本质:把具体的数据类型作为参数,传递给类型变量。
泛型工作在编译阶段,用于类型检查,可以避免强制类型转化。
编译完成后,class 文件中没有泛型了,这就是泛型的擦除。
泛型只支持引用数据类型,不支持基本数据类型。
4. 常用 API
4.1. Object
祖宗类,常用方法
toString() // 被子类重写,用来返回内容。
equal() // 被子类重写,指定对象得比较规则。默认比较对象得地址值。
4.2. Objects
工具类
equal(o1,o2) // 更安全,相对Object得,增加了两个判断,地址和非空判断。
notNull()
isNull()
4.3. 包装类
4.3.1. 为什么要设计包装类
万物皆对象。
泛型和集合,不支持基本数据类型,支持引用数据类型。
包装类把基本数据类型,包装成引用数据类型。例如 Integer num = Integer. valueOf (10);
int->Integer char->Character;其他首字母大写
自动装箱,自动拆箱,是说基本数据类型和它们对应的引用数据类型之间可以自动转化。
包装类得常量池技术 #TODO
4.3.2. 常见操作
toString(2)
toString()基本类型转字符串。
parseXXX()
valueOf()
4.4. StringBuilder
| String | StringBuilder |
|---|---|
| 不可变字符串 | 可变字符串 |
| 频繁操作字符串,会产生很多没用得对象,性能差 | 拼接字符列性能好,代码优雅 |
StringBuilder()
StringBuilder(str)
append(任意类型)
length()
toString()
reverse()
StringBuffer 和 StringBuilder 用法一样。
StringBuffer 是线程安全的。
demo 整数数组,返回格式 [1,2,3] 字符串
4.5. StringJoiner
JDK 8 有的,
高效操作字符串,同时它使用它的 API 代码会更简洁。
StringJoiner(间隔符)
StringJoiner(间隔符,开始符,结束符)
add() //添加对象,返回对象自身。 联想到设计模式,装饰器。
length()
toString()