目录
接口
1.接口用来描述类应该做什么,而不指定它们如何去做;一个类可以实现一个或多个接口。
2.接口中所有的方法都自动是public方法,所有字段总是public static final。
3.接口绝不会有静态代码块、构造方法或实例字段。
4.接口的定义格式:
public interface 接口名称 {
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
}
5.四种方法的解释:
- 抽象方法:使用abstract关键字修饰,可以省略,没有方法体。该方法供子类实现使用。
- 默认方法:使用default修饰,不可省略,供子类调用或者子类重写。
- 静态方法:使用static修饰,供接口直接调用。
- 私有方法:使用private修饰,供接口中的默认方法或者静态方法调用。
6.可以将接口看做没有实例对象的抽象类。
7.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
否则,非抽象子类实现接口必须重写接口中所有抽象方法。
而继承了接口的默认方法,既可以直接调用,也可以重写。
静态方法与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用。
私有方法只有默认方法可以调用。
而私有静态方法只有默认方法和静态方法可以调用。
8.让类实现接口的步骤:
- 在类名后使用implements关键字将类声明为实现给定的接口。
- 对接口的所有方法提供定义。
9.尽管在声明接口中的方法时可以省略public,但实现接口时public不可省略。
10.接口不是类,不可以使用new运算符实例化一个接口,但可以声明接口的变量,其必须引用实现了这个接口的类对象。
Comparable x; // Comparable is an interface.
x = new A(...);
11.可以使用instanceof检查一个对象是否实现了某个特定的接口。
if ( anObject instanceof anInterface ) {
// ...
}
12. 默认方法必须使用default修饰符标记,实现时不强制要求覆盖该方法,保证了源代码兼容。
13.如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。
14.抽象类利于代码的复用,接口类利于代码的维护。
15.默认方法冲突的解决方法:
- 超类优先:超类和接口存在同名方法,只会调用超类的方法,接口中的同名方法全部被忽略,这是“类优先”原则。
- 接口冲突:接口中的同名默认方法必须在实现类中重写一次,同名抽象方法只需重写一次,静态方法不冲突。
- 子接口重写默认方法时,default关键字可以保留;子类重写默认方法时,default关键字不可以保留。
16.一个类不可以继承多个父类,但可以实现多个接口,并且可以在继承一个父类的同时实现多个接口。
Lambda表达式
1.将一个代码块传递到某个对象时使用Lambda表达式。
2.Lambda表达式形式:参数,箭头以及一个表达式,若该表达式无法用一条语句写完,则使用大括号将这些语句括起。
3.即使Lambda表达式没有参数,仍然要提供小括号。
4.如果Lambda表达式的参数类型可推导,则可以忽略其类型;而若仅一个参数且参数类型可推导,则可以省略小括号。
5.无需指定Lambda表达式的返回类型,其可以通过上下文推导得出。
Lambda表达式在某个分支返回一个值而在另一些分支不返回值是非法的!
6.对于一个只有抽象方法的接口,可以提供一个Lambda表达式。这种接口称为函数式接口。
内部类
成员内部类
1.描述:定义在类中方法外的类。
2.访问特点:
- 内部类可以直接访问外部类的成员,包括私有成员。
- 外部类要访问内部类的成员,必须要建立内部类的对象。
3.创建成员内部类的格式:
外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
4.内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名 和$符号 。
比如,A$B.class
匿名内部类
1.描述:是内部类的简化写法。它的本质是一个带具体实现的、父类或者父接口的、匿名的子类对象。
2.前提:匿名内部类必须继承一个父类或者实现一个父接口。
3.匿名内部类,是在创建对象的时候,只能使用唯一一次。
若希望多次创建对象,则需要单独定义一个实现类。
4.匿名对象,是在调用方法的时候,只能使用唯一一次。
若希望同一个对象多次调用该方法,那么必须为这个对象命名。
5.匿名内部类是省略了实现类/子类的名称,但匿名对象是省略了对象的名称。
// 使用匿名内部类,但不是匿名对象,对象名称就叫objA
MyInterface objA = new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!111-A");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-A");
}
};
objA.method1();
objA.method2();
System.out.println("=================");
// 使用了匿名内部类,而且省略了对象名称,也是匿名对象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!111-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-B");
}
}.method1();
// 因为匿名对象无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!111-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-B");
}
}.method2();