抽象类 abstract
注意项
- 父类方法需要声明,但是有不确定性,考虑将该方法设计为抽象方法
- 抽象方法=没有实现的方法=没有方法体(跟接口的区别?)
- 抽象方法的类必须设置为抽象类,实现方法由其子类实现
abstract class animal(){
public abstract void eat();
}
- 抽象类还是类,可以不包括抽象方法,也可以包括有实现方法,静态属性,构造器等等;但抽象方法一定属于抽象类
- 抽象类不可被实例化
- abstract 只能修饰类和方法,不能修饰属性和其他
- 抽象方法不能有主体 {}
- 抽象方法不能使用private、final和static来修饰;与子类重写父类方法冲突
模板设计模式
多个类完成不同的任务,要求统计不同任务执行的时间
- 父类写成模板,将job()写为抽象方法
- 多个工作类都继承父类,重写job即可,都实现了计算时间的功能
abstract public class Template{
public abstract void job(); //抽象方法
public void calculateTime(){
long start = System.currentTimeMillis();
job();
long end= System.currentTimeMillis();
System.out.println("执行时间" + { end - start });
}
}
接口 interface
一些没有实现的方法,封装到一起就是接口。
使用细节
-
普通类要用的时候,根据情况implements接口去实现方法,需要实现接口所有方法;一个类可以同时实现多个接口
-
接口可以同时继承多个接口,写extends,不用implements
-
抽象类实现接口时,可以不实现方法,但是需要有方法名?
-
jdk8后接口可以有静态和默认实现方法,默认方法需在接口方法中用default修饰 (此default含义不一样)
-
接口管理多个实现类,传入向上转型?自动识别是哪个具体类,统一
-
接口不能被实例化
====================================================================== -
接口的修饰符只能时public和默认
-
接口中的方法都是public and abstract,但是可以省略abstract关键字
-
接口中的属性都是public static final;可以省略关键字,但是默认必须是;访问:接口名.属性名
实现接口 vs 继承类
- 实现机制是对单继承的补充,加强子类功能;java只能单继承但可多实现
- 子类继承父类,自动拥有父类功能,如果需要其他功能,可通过实现接口来实现。
- 解决的问题:继承解决代码复用性和可维护性;接口设计好各种规范(方法)
- 接口比继承更灵活,继承is-a,接口只需满足like-a or hava-a
- 接口在一定程度上实现代码解耦 [接口规范性+动态绑定]
接口的多态
- 多态参数,UsbInterface usbInterface 即可接收手机也可接收相机(手机、相机都实现于UsbInterface)
IF if01 = new Monster(); // 跟继承类似,接口指针(继承:父类对象指针)可指向其他实现接口的实例对象
if01 = new Cat();
- 多态数组,UsbInterface[] usbInterface 数组既可以有手机对象也可有相机对象
- 接口存在多态传递现象
内部类
类的五大成员之一[属性,构造器,方法,代码块,内部类]
一个类的内部嵌套了另一个类接口
局部内部类(有类名) and 匿名内部类(无类名)
局部内部类
- 位置:在外部类 outer 的方法 f1() 的内部,可访问外部类所有成员
- 不能加访问修饰符,但是可以加final修饰,本质是局部的类,地位是局部变量
- 作用域:在定义的方法和代码块内
- 外部类和局部内部类成员重名时,遵循就近原则,若要访问外部内成员,则用 外部类名.this.成员名
匿名内部类!!!重要
- 定义在外部类的局部位置,没有类名,底层返回一个对象,命名为$xxx
new 类或接口(参数列表){ 类体 };
- 基于接口:内部实现接口,但只用一次,用匿名内部类可简化代码;代码内部给匿名内部类会分配名称$xxx;编译类型是IA,运行类型是$xxx
- -
IA tiger = new IA(){ }; //IA是一个外部类外面写的接口
- 基于类:编译类型是Father,运行类型是$xxx
- -
Father father = new Father("Jack"){ }
使用细节
- 可直接调用方法
-
new 类或接口(参数列表){ 类体 }**.方法()**;
- 不能添加访问修饰符,地位是局部变量
- 外部其他类不能访问匿名内部类
- 外部类和匿名内部类成员重名时,遵循就近原则,若要访问外部内成员,则用 外部类名.this.成员名
- 当作实参传递,简洁高效 p498
成员内部类 and 静态内部类
成员内部类
- 位置:在外部类的成员位置上【区别局部内部类】
- 没有static修饰
- 可添加访问修饰符【public,protected,default,private】
- 可直接访问外部类所有成员,包括私有的
- 外部其他类使用成员内部类
Outer outer = new Outer(); //外部类对象
// 1
Outer.Inner inner = outer.new Inner()
// 2 在外部类实现一个方法getInstance() return new Inner()
Outer.Inner inner outer.getInstance();
- 外部类和成员内部类成员重名时,遵循就近原则,若要访问外部内成员,则用 外部类名.this.成员名
静态内部类
- 位置:在外部类的成员位置上【区别局部内部类】
- static修饰
- 可添加访问修饰符【public,protected,default,private】
- 可直接访问外部类静态成员,包括私有的;但不能访问非静态成员
- 外部其他类使用成员内部类
Outer outer = new Outer(); //外部类对象
// 1 因为是静态内部类,可通过类名直接访问(满足访问权限的前提)
Outer.Inner inner = new outer.Inner()
// 2 在外部类实现一个方法getInstance() return new Inner()
Outer.Inner inner outer.getInstance();
// 3 不创建外部对象,在外部类实现一个静态方法etInstance() return new Inner(),用类名直接访问创建 g
Outer.Inner inner = new Outer.getInner();
- 外部类和静态内部类成员重名时,遵循就近原则,若要访问外部内成员,则用 外部类名.this.成员名