为什么匿名内部类实现接口,不需要重写所有抽象方法

本文探讨了Java 8中匿名内部类与lambda表达式的区别,指出匿名内部类虽未显式重写Comparator接口的equals方法,但因继承自Object自动拥有该方法。通过反编译和实际测试,揭示了接口实现类生成的细节。

这几天在学习关于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;
    }
}


————————————————

原文链接:https://blog.youkuaiyun.com/dhklsl/article/details/84532719

<think>嗯,用户的问题很具体:Java的匿名类是否需要重写所有抽象父类的方法。这个问题涉及到Java语法的核心机制,结合提供的引用材料来看,有几个关键点需要厘清。用户引用的材料里提到匿名内部类会自动重写所有抽象方法(引用[1]),但同也看到接口实现必须重写方法的示例(引用[3])。表面上看似乎矛盾,其实需要区分两种情况——当匿名类实现的是单一抽象方法接口,可以显式重写;但实现包含多个抽象方法接口或抽象类,就必须全部重写。从用户提问方式看,ta应该已经查阅过资料但存在困惑,特别是引用[1]所说的“自动重写空方法”可能让ta误解为任何候都重写。需要明确说明这是Java编译器对多抽象方法接口的妥协方案,而非免除重写义务。用户的核心困惑点可能在“为什么候可以省略重写”,这需要解释Lambda表达式和函数接口的关联特性。考虑到用户引用材料中多次出现具体代码案例(引用[3][5]),说明ta有实践基础。回答应当:第一明确语法规则:普通接口或抽象类必须全重写(除非是abstract类本身)第二解释例外情况:函数接口允许显式重写第三澄清原理:编译器实际生成空方法体(引用[1][4])最后用代码示例对比两种情况,用户就能理解匿名类表面省略重写的幕后机制。特别要注意纠正用户可能存在的误解:以为匿名类在任何情况下都可以选择性重写方法。这涉及到Java多态的基础,引用[4]提到向下转型子类方法优先的机制也与此相关,应该联动说明。</think> 在Java中,**匿名类必须重写其抽象父类(或接口)中的所有抽象方法**。以下是详细分析: --- ### **核心规则** 1. **实现接口** 当匿名类实现接口,**必须重写接口中的所有抽象方法**。例如: ```java interface MyInterface { void methodA(); void methodB(); } public class Main { public static void main(String[] args) { MyInterface obj = new MyInterface() { @Override public void methodA() { System.out.println("A"); } @Override public void methodB() { System.out.println("B"); } // 必须重写所有抽象方法 }; } } ``` **编译错误示例**:若未重写全部方法,编译器会直接报错:`Class must implement all abstract methods` 2. **继承抽象类** 若匿名类继承抽象类,**必须重写抽象类中的全部抽象方法**,但可忽略已实现的具体方法。 --- ### **例外情况:函数接口** 若父类是**函数接口(仅含一个抽象方法)**,可通过Lambda表达式简化,无需显式重写。例如: ```java @FunctionalInterface interface SimpleInterface { void run(); // 唯一抽象方法 } public class Main { public static void main(String[] args) { // Lambda简化(本质是匿名类) SimpleInterface obj = () -> System.out.println("Running..."); } } ``` 此编译器自动生成匿名类并重写唯一抽象方法,无需手动编写重写逻辑[^1][^3]。 --- ### **底层机制** - **编译器自动生成类**:匿名类的本质是编译器生成一个临子类(例如`Main$1.class`),该类会**强制重写所有抽象方法**(若未显式重写,则生成空方法体)[^1]。 - **语法硬性要求**:Java语法规定匿名类必须提供所有抽象方法的具体实现,否则代码无法通过编译。 --- ### **代码验证** ```java abstract class AbstractClass { abstract void abstractMethod(); } public class Test { public static void main(String[] args) { AbstractClass obj = new AbstractClass() { @Override void abstractMethod() { // 必须重写 System.out.println("Implemented"); } }; } } ``` **结论**:匿名类必须显式重写所有抽象方法函数接口可通过Lambda隐式处理),否则无法编译通过。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值