第七章
第七章 面向对象高级特性
- 单词的意思
- 可以修饰什么
- 修饰后有什么变化
7.1 final
final: 最终的
用法
- 修饰类
使类无法被继承, 没有子类 - 修饰方法
这个类无法被重写 - 修饰变量
使变量值无法修改
内部变量用final后一定要赋值, 否则会报错
7.2 native
native: 本地的, 原生的
用法
- 只能修饰方法
表示这个方法体代码不是用java语言实现的
可以正常调用或者重写这部分代码
7.3 static
native: 本地的, 原生的
用法
- 方法
不能被重写
其他类中可以直接类名.方法名调用
静态方法不允许出现this, super, 非静态修饰的成员 - 变量
值是该类对象共享的
静态变量的get/set也是静态的
与局部变量变量名相同可以用 类名.静态变 量区分 - 内部类
- 代码块
7.4 静态代码块
[修饰符] class 类名{
static{
静态代码块;
}
}
作用
协助完成类初始化, 可以为类变量赋值
类初始化
类初始化有
- 静态变量的显式赋值代码
- 静态代码块中的代码
- 按顺序执行
类初始化执行特点
- 每个类的<clinit>()只执行一次
- 父类没初始化会先初始化父类
- 先类初始化才能实例初始化
7.5 变量的分类和区别
- 按数据类型划分
- 基本数据类型
- 引用数据类型
- 按声明类型的不同
- 成员变量
- 局部变量
成员变量和局部变量的区别
- 声明位置不同
- 成员变量: 类中方法外
- 局部变量: 形参列表, 方法内, 代码块中
- 修饰符不同
- 成员变量: 4种权限修饰符, static, final...
- 局部变量: 只有final
- 生命周期
- 成员变量
- 静态变量和类生命周期相同
- 费静态变量(实例变量)和所属的对象相同
- 局部变量: 每次都是新的
- 成员变量
- 作用域
- 成员变量
- 静态变量可以在本类中随意使用, 在其他类可以用 类名.变量 名使用
- 非静态变量在本类只能被非静态成员中使用, 在其他类中用对象名.变量名使用
- 局部变量
- 有作用域
- 成员变量
7.6 根父类
java.lang.Object类是所有类的父类, 包括数组对象
- Object方法是所有类的父类, 所有的方法都会被继承到子类中
- 每一个对象创建, 都会调用到Object的实例初始化方法<init>()
- Object类型的变量, 形参, 数组都可以存储任意类型的对象
Object类的常用方法
- public String toString();
- 返回对象的字符串表示形式
- 建议所有子类重写此方法。
- Object 类的 toString 方法返回一个字符串, 该字符串由类名, @, 和此对象哈希码的无符号十六进制表示组成
- getClass().getName() + '@' + Integer.toHexString(hashCode())
- public final Class<?> getClass()
- 获取对象运行时的类型
- protected void finalize()
- 当对象被GC确定要被回收的垃圾, 在回收之前GC会调用这个方法. 而且这个方法只会被调用一次, 子类可以选择重写
- public int hashCode()
- 此方法是为了提高哈希表的性能.
- hashCode 的常规协定
- hashCode值不相等, 两个对象不会相等
- hashCode相等, 两个对象有可能相等
- public boolean equals(Object obj)
- 指示其他某个对象是否与此对象“相等”.
- 默认情况下, 此方法等价于"==", 比较的是对象的地址值
- 可以重写
- 当此方法被重写时, 通常有必要重写 hashCode 方法, 以维护 hashCode 方法的常规协定, 该协定声明相等对象必须具有相等的哈希码。
- equals 方法在非空对象引用上实现相等关系
- 自反性: 对于任何非空引用值 x, x.equals(x) 都应返回 true。
- 对称性: 对于任何非空引用值 x 和 y, 当且仅当 y.equals(x) 返回 true 时, x.equals(y) 才应返回 true。
- 传递性: 对于任何非空引用值 x、y 和 z, 如果 x.equals(y) 返回 true, 并且 y.equals(z) 返回 true, 那么 x.equals(z) 应返回 true。
- 一致性: 对于任何非空引用值 x 和 y, 多次调用 x.equals(y) 始终返回 true 或始终返回 false, 前提是对象上 equals 比较中所用的信息没有被修改。
- 对于任何非空引用值 x, x.equals(null) 都应返回 false。
7.7 abstract
抽象方法类
当不能确定方法体如何实现, 也要体现子类的共同特征, 就要用抽象方法
如果一个类有抽象方法, 那么这个类是抽象方法类
[权限修饰符] abstract class 类名 [extends 父类]{
[权限修饰符] abstract 返回值 方法名();
//抽象方法没有方法体
}
抽象类的特点
- 不能直接实例化, 即new对象
- 抽象类就是用来继承的, 子类如果不重写所有的抽象方法, 那么这个子类也是抽象类
- 抽象类有构造器, 用于子类实例化过程调用
- 抽象类也可以没有抽象方法, 目的是无法创建对象而是创建子类对象
- 可以多态引用
不能和abstract一起使用的修饰符
- final 不能一起修饰方法和类
- static 不能一起修饰方法
- native 不能一起修饰方法
- private 不能一起修饰方法和类
7.8 接口
一种标准, 注意关注行为标准(即方法)
开发原则有一条, 面向接口编程
声明
[修饰符] interface 接口名{
接口的成员列表;
}
实现
[修饰符] class 实现类 implements 父接口们{
}
[修饰符] class 实现类 extends 父类 implements 父接口们{
}
接口继承
[修饰符] interface 接口名 extends 父接口们{
接口的成员列表;
}
接口特点
- 接口不能直接实例化, 即不能直接new对象
- 可以与子类多态引用
- 实现类在实现接口时必须重写所有抽象方法, 除非这个类是抽象类
- Java规定单继承, 但接口可以多继承
- 接口与接口也可以多继承
接口成员
- JDK1.8前
- 全局静态常量: public static final, 这些修饰符可以省略
- 公共抽象方法: public abstract 也可以省略
- JDK1,8后
- 公共静态方法: public static 不能省略
public interface Flyable{
long MAX_SPEED = 7900000;
void fly();
}
public class bird implements Flyable{
void fly(){
//......
}
}
7.9 内部类
声明在另外一个类里面就是内部类
内部类的形式
- 静态内部类
- 非静态成员内部类
- 有名字的局部内部类
- 匿名内部类
匿名内部类
//匿名内部类中调用父类的构造器
new 父类(){
内部类成员列表
}
new 父类(实参列表){
内部类成员列表
}
// 接口没有构造器, 这里是匿名内部类自己的无参构造, 默认调用根父类Object的无参构造
new 父接口名(){
内部类成员列表
}
匿名内部类, 匿名对象的区别?
System.out.println(new Student("张三"));//匿名对象
Student stu = new Student("张三");//这个对象有名字, stu
//既有匿名内部类, 又是一个匿名的对象
new Object(){
public void test(){
//.....
}
}
//这个匿名内部类的对象, 使用obj这个名字引用, 对象有名字但是这个类没有名字
Object obj = new Object(){
public void test(){
//.....
}
}
使用
-
继承
abstract class Father{ public abstract void test(); } public class Test { public static void main(String[] args) { //多态引用 Father f = new Father() { @Override public void test() { System.out.println("用匿名内部类继承了Father这个抽象类, 重写了test方法"); } }; } }
-
实现
interface Flyable{ void fly(); } public class Test { public static void main(String[] args) { //用父接口与匿名内部类的对象构成了多态引用 Flyable f = new Flyable() { @Override public void fly() { System.out.println("用匿名内部类继承了Flyable这个抽象类, 重写了抽象方法"); } }; f.fly(); } }
示例代码
-
用匿名内部类对象直接调用方法
new Object(){ public void test(){ System.out.println("用匿名内部类的匿名对象直接调用方法"); } }.test();
-
用匿名内部类对象直接作为实参
Value[] all = new Value[3]; all[0] = new Value(20); all[1] = new Value(23); all[2] = new Value(21); Arrays.sort(all, new Comparator(){ public int compare(Object o1, Object o 2){ Value v1 = (Value)o1; Value v2 = (Value)o2; return v1.getValue() - v2.getValue(); } })
常用接口
-
java.lang.Comparable: 自然排序
抽象方法: int compareTo(Object obe) -
java.util.Comparator: 定制排序
抽象方法: int compare(Object obj1, Object obj2)public class Value implements Comparable{ private int value; @Override public int compareTo(Object arg0) { Value v1 = (Value)arg0; return this.value - v1.value; } public Value(int value) { super(); this.value = value; } public Value() { super(); } public int getValue() { return value; } public void setValue(int value) { this.value = value; } @Override public String toString() { return "Value [value=" + value + "]"; } }
-
如果后面又发现新的需求, 选择定制排序, 实现Comparable接口
静态内部类
[修饰符] class 外部类名 [extends 父类] [implements 父类接口们]{
[其他修饰符] static class 静态内部类 [extends 父类] [implements 父类接口们]{
\\静态内部类的成员列表..
}
\\外部类的其他成员列表..
}
- 包含的成员
- 可以包含类的所有成员
- 修饰符要求
- 四种权限修饰符
- 其他修饰符: abstract, final
- 使用外部类的成员上是否有要求
- 只能使用外部类的静态成员
- 在外部类使用静态内部类是否有要求
- 否
- 在外部类的外面使用静态内部类是否有要求
- 如果使用静态内部类的静态成员
- 外部类名.静态内部类名.静态成员
- 如果是用的是静态内部类的非静态成员
- 先创建静态内部类的对象
- 内部类名.静态内部类 对象名 = 外部类名.静态内部类名([实参列表]);
- 通过对象调用非静态成员
- 对象名.XXX
- 如果使用静态内部类的静态成员
- 字节码文件形式: 外部类名$静态内部类名.class
非静态内部类
[修饰符] class 外部类名 [extends 父类] [implements 父类接口们]{
[其他修饰符] class 非静态内部类 [extends 父类] [implements 父类接口们]{
\\非静态内部类的成员列表..
}
\\外部类的其他成员列表..
}
- 包含的成员
- 不允许出现静态成员
- 修饰符要求
- 四种权限修饰符
- 其他修饰符: abstract, final
- 使用外部类的成员上是否有要求
- 都可以使用
- 在外部类使用非静态内部类是否有要求
- 在外部类的静态成员中不能使用非静态内部类
- 在外部类的外面使用静态内部类是否有要求
- 使用非静态内部类的非静态成员
- 外部类名 外部类对象名 = new 外部类名([实参列表]);
- 外部类名.非静态内部类名 对象名 = 外部类对象名.new 非静态内部类名([实参列表]);
外部类名.非静态内部类名 对象名 = 外部类对象名.get非静态内部类对象的方法([实参列表]); - 对象名.XXX
- 使用非静态内部类的非静态成员
- 字节码文件形式: 外部类名$非静态内部类名.class
局部内部类
[修饰符] class 外部类名 [extends 父类] [implements 父类接口们]{
[修饰符] 返回值类型 方法名([实参列表]){
[其他修饰符] class 局部内部类 [extends 父类] [implements 父类接口们]{
\\局部内部类的成员列表..
}
}
\\外部类的其他成员列表..
}
- 包含的成员
- 不允许静态成员
- 修饰符要求
- 权限修饰符: 不可用
- 其他修饰符: abstract, final
- 使用外部类的成员上是否有要求
- 使用外部类的静态成员: 都可以用
- 使用外部类的非静态成员: 所在的方法是不是静态的
- 使用所在方法的局部变量: 必须是final修饰
- 在外部类使用局部内部类是否有要求
- 有作用域
- 在外部类的外面使用局部内部类是否有要求
- 无法使用
- 字节码文件形式: 外部类名$编号局部内部类名.class