final关键字
可以修饰:类、方法、变量。
- 修饰类:不能被继承。
- 修饰方法:方法不能被子类重写。
- 修饰变量:有且仅能被赋值一次。
修饰变量分为:
- 修饰静态成员变量(static修饰)
public static final String NAME_ID = "666";
final修饰静态变量,被称为常量,通常这个值作为系统的配置信息。
- 修饰实例成员变量
private final String name = "666";
一般没有意义。
- 修饰局部变量。一般没有意义。
注意:final修饰引用类型的变量,变量存储的地址不能改,但指向的内容可以改。
单例类(设计模式)
什么是设计模式:一个问题的解法是最优的,这个最优解法被总结出来,称之为设计模式。
设计模式有23种。主要学什么:1)解决什么问题;2)设计模式怎么写。
单例类的作用
作用:确保某个类只能创建一个对象。(比如任务管理器只能开一个窗口,word可以开多个)
单例类的写法
- 饿汉式单例写法:(1)定义一个私有静态变量(即类变量,static修饰)new一个类对象。(2)类的构造器私有。(3)定义一个公开静态类方法(
getInstance()
),返回对象。
//饿汉式单例:拿对象时,对象早就创建好了。
public class A{private static A a = new A();private A(){}public static A getInstance(){return a;}
}
- 懒汉式单例写法:(1)定义一个私有静态变量(即类变量,static修饰),不new。(2)类的构造器私有。(3)定义一个公开静态类方法(
getInstance()
),new对象,并返回对象。
//懒汉式单例类:用对象时,才开始创建对象。
public class A{private static A a;private A(){}public static A getInstance(){if(a == null){a = new A();}return a;}
}
懒汉式的优缺点:第一次拿对象没有饿汉式的快,但如果只用A中的静态方法,就不需要创建对象,到用到对象时调用getInstance()才会创建。
枚举类
枚举类是一种特殊类。是一种多例设计模式。如果名称只有1个,就是单例类。
枚举类的写法
写法:第一行只能罗列枚举对象的名称,这些名称本质是常量。
修饰符 enum 枚举类名{名称1,名称2,名称3 ...;其他成员;
}
枚举类的注意事项
- 枚举类都是最终类,不可以被继承。
- 枚举类第一行只能罗列枚举对象的名称,这些名称本质是常量(static final),并且每个常量都会记住枚举类的一个对象。
- 枚举类的构造器是私有的,因此枚举类对外不能创建对象。
- 编译器为枚举类新增了几个方法。
public enum A{X,Y,Z;
}A a1 = A.X;
a1.name();//X
a1.ordinal();//0
a1.values();//拿到所有的枚举对象
枚举类的经典应用场景
很适合做信息分类和标志。比如东南西北四个方向,用枚举类。
虽然常量也可以做信息分类和标志,但使用常量,参数值不受约束。
抽象类
abstract
可以修饰类、成员方法。修饰类就是抽象类。
抽象类的特点
- 抽象类不一定有抽象方法,但抽象方法一定在抽象类中。
- 抽象类可以有成员变量,方法,构造器。
- 抽象类不能创建对象,仅作为特殊的父类,让子类继承并实现。
- 一个抽象类的子类必须实现父类的所有抽象方法,不然这个子类也要定义为抽象类。
- 抽象类的使命就是被继承。
- 抽象类不是必须的技术,它只是一个最佳实践。
- 更好支持多态。当父类知道每个子类都要做某个行为,子类的这个行为又不一样,就定义抽象方法,子类分别实现。
抽象类的应用-模板方法设计模式
模板方法的作用
提供一个方法作为完成某类功能的模板。模板方法封装了每个实现步骤,但允许子类提供特定步骤的实现。提高代码复用,简化子类设计。
模板方法的写法
- 定义抽象类。定义final模板方法和抽象方法。
public abstract class People{private int age;public final void write(){"111".sout;writeMain();"333".sout;}public abstract void writeMain();
}
- 定义子类。重写抽象方法。
public class Student extends People{@overritepublic void writeMain{"Student1 is Writing".sout;}
}Student s = new Student();
s.write();
接口
关键字:interface
JDK8之前
在JDK8之前,接口只能定义:
- 常量(必须初始化,接口
public static final
可以省略)。 - 抽象方法(
public abstract
可以省略)。
接口是被类实现(implements
),实现类,一个类可以同时实现多个接口,必须重写所有接口的全部抽象方法,否则要定义为抽象类。
JDK8之后
JDK8之后新增的三种方法。
即default
、private
、static
修饰。
default
使用接口的实现类的对象来调用。private
使用接口中其他实例方法调用。static
只能使用当前接口名来调用。
优点:在开发时,已经有很多实现类,如果突然要在接口中新增一个功能,JDK8需要在所有的实现类里重写这个新增抽象方法,JDK8之后直接定义带方法体的方法,工作量少。
接口的作用
- 弥补了单继承的不足,角色可以更多。
- 面向接口编程,更容易解耦合。
接口的注意事项
- 接口和接口可以多继承,一个接口可以同时继承多个接口。
- 一个接口继承多个接口,如果多个接口中存在方法签名冲突,则不支持多继承,也不支持多实现。
方法签名冲突,比如同样的返回值和方法名是可以合并的,但不同的返回值相同的方法名就会冲突。
- 父类和接口中有同名的方法,实现类会优先用父类的。
class Dog extends Animal implements A2{public void go{//想要用接口中的,只能用这样的方法中转show();//父类的super.show();//父类的A2.super.show();//接口的}
}
- 一个类实现的多个接口中有同名方法,可以不冲突,只要重写该方法即可。
抽象类和接口的区别
相同点
- 都是抽象形式,都可以有抽象方法,都不能创建对象。
- 都是派生子类形式,抽象类是被子类继承使用,接口是被实现类实现。
- 继承抽象类或者所有接口,都必须重写所有抽象方法,否则自己要成为抽象类。
- 都能支持多态,都能够实现解耦合。
不同点
- 抽象类中可以定义类的全部普通成员,接口只能定义常量和抽象方法。
- 抽象类只能被类单继承,接口可以被类多实现。
- 抽象类体现模板思想,更利于做父类,实现代码的复用性。接口更适合做功能的解耦合,更灵活(多个实现类作为多个方案一起实现解耦合)。这只是最佳实践,最佳实现,最优雅。