这几天在学习关于jdk8的一些知识,在看到讲解lambda表达式的引入原因时,举了一个匿名类的例子,并进一步引入lambda表达式,因为lambda表达式比匿名类更简洁明了易懂。
匿名类写法如下:
inventory.sort(new Comparator<Apple>() {
public int compare(Apple a1, Apple a2){
return a1.getWeight().compareTo(a2.getWeight());
}
});
inventory是一个List<Apple>。
这时候大家思考一个问题,Comparator接口有两个抽象方法,一个是compare,另一个是equals方法,而写这个匿名内部类时,怎么没有重写equals方法呢,也没有报错。
我在网上查了相关解释如下:写匿名类别类,系统给我们自动创建了实现类(这个大家都知道),这个实现类里自动重写了所有抽象方法,只是方法体是空的。我虽然只重写了部分方法,但是其他方法已经被临时类重写了只不过是空方法而已!
听这个解释还是比较信服的,但是我想一探究竟,到底是不是这么回事,后来我自己写了测试一下。竟然发现和上面的解释有所不同。因为我利用反编译工具打开系统生成那个接口的实现类,发现里面并没有重写equals方法。这就奇怪了,为什么没有重写equals方法还不报错呢?后来想了想明白了,原因是所有类都继承Object类,而Object类里有实现equals方法,那么那个系统生成的实现类肯定也有这个equals方法啊,所以也就是重写了Comparator接口的equals方法。这么一来,网上那个解释是不对的啊。
反编译工具打开系统创建的实现类没有equals方法的截图如下:
为了验证网上的说法是否正确,我有自己建了一个接口,内有两个抽象方法,然后匿名类类实现一个抽象方法,结果编译时报错,说是没有重写另一个方法。这就验证了网上的说法是错误的。
错误贴图如下:
写在后面的话,首先我是在jdk1.8写测试的,不知道在jdk1.6写的是否网上的说法成立?各位有测试的可以留言告知。
在jdk1.8下,匿名内部类的写法必须重写接口所有抽象方法,系统创建的实现类不会自动创建所有抽象方法。
现在把所有代码贴在下面,供大家测试
import java.util.*;
public class MyTest{
public static void main (String[] args){
List<Student> list = new ArrayList<Student>();
list.add(new Student(1,"aa"));
list.add(new Student(2,"bb"));
list.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {return o1.getNum().compareTo(o2.getNum());
}
});
//匿名内部类写法,只重写test1,未重写test2,报错
method1(new MyInterface(){
@Override
public int test1(){
System.out.println("aaaaaa");
return 2;
}
});
}
public static void method1(MyInterface myInterface){
System.out.println("1231231321");
}
}//自定义的接口,有两个抽象方法
interface MyInterface{
int test1();
void test2();
}class Student{
private Integer num;
private String name;
Student(){}
Student(Integer num,String name){
this.num = num;
this.name = name;
}
public void setNum( Integer num){
this.num = num;
}
public Integer getNum(){
return this.num;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}