Java面向对象编程(高级)二

在软件开发领域,面向对象编程(Object-Oriented Programming)是一种强大且广泛应用的编程范式,它将数据和操作封装在对象中,通过对象之间的交互来实现程序的逻辑。面向对象编程让我们能够以更加模块化、灵活和可维护的方式构建软件系统。

本文将链接上一篇文章,继续深入探讨面向对象编程的核心概念、优势以及如何在实际项目中应用这种编程范式

目录

6、抽象类与抽象方法(或abstract关键字)

6.1 由来

6.2 语法格式

6.3 使用说明

6.4 注意事项

6.5 模板方法设计模式 

7、接口(interface) 

7.1 概述

7.2 定义格式 

7.2.1 接口的生命格式 

7.2.2 接口的成员变量说明 

7.3 接口的使用规则 

7.3.1 类实现接口(implements)

7.3.2 接口的多实现

7.3.3 接口的多继承 

7.3.4 接口与实现类对象构成多态

7.3.5 使用接口的静态成员 

7.3.6 使用接口的非静态方法 

 7.4 JDK8中相关冲突问题

7.4.1 默认方法冲突问题

7.4.2 常量冲突问题

7.5 接口的总结 

8、内部类

8.1 概述

8.1.1 什么是内部类

 8.1.2 为什么要声明内部类

8.2 成员内部类

8.2.1 概述

8.2.2 创建成员内部类

8.2.3 代码示例

8.3 局部内部类 

8.3.1 非匿名局部内部类

8.3.2 匿名内部类 


 

6、抽象类与抽象方法(或abstract关键字)

6.1 由来

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。

我们声明一些几何图形类:圆、矩形、三角形类等,发现这些类都有共同特征:求面积、求周长。那么这些共同特征应该抽取到一个共同父类:几何图形类中。但是这些方法在父类中又无法给出具体的实现,而是应该交给子类各自具体实现。那么父类在声明这些方法时,就只有方法签名,没有方法体我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类必须是抽象类

6.2 语法格式

  • 抽象类:被abstract修饰的类。
  • 抽象方法:被abstract修饰没有方法体的方法。

抽象类的语法格式:

[权限修饰符] abstract class 类名{
    
}
[权限修饰符] abstract class 类名 extends 父类{
    
}

抽象方法的语法格式:

[其他修饰符] abstract 返回值类型 方法名([形参列表]);

注意:抽象方法没有方法体。 

示例:

public abstract class Animal {
    public abstract void eat();
}
public class Cat extends Animal {
    public void eat (){
      	System.out.println("小猫吃鱼和猫粮"); 
    }
}
public class CatTest {
 	 public static void main(String[] args) {
        // 创建子类对象
        Cat c = new Cat(); 
       
        // 调用eat方法
        c.eat();
  	}
}

 此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法

6.3 使用说明

1、抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。

 2、抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。

理解:子类的构造方法中,有默认的super()或手动的super(实参列表),需要访问父类构造方法。

 3、抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

 4、抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

6.4 注意事项

  • 不能用abstract修饰变量、代码块、构造器;
  • 不能用abstract修饰私有方法、静态方法、final的方法、final的类。

6.5 模板方法设计模式 

抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

解决的问题:

  • 当功能内部一部分实现是确定的,另一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。

  • 换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。

 示例:

abstract class Template {
    public final void getTime() {
        long start = System.currentTimeMillis();
        code();
        long end = System.currentTimeMillis();
        System.out.println("执行时间是:" + (end - start));
    }

    public abstract void code();
}

class SubTemplate extends Template {
    public void code() {
        for (int i = 0; i < 10000; i++) {
            System.out.println(i);
        }
    }
}

模板方法设计模式是编程中经常用得到的模式。各个框架、类库中都有他的影子,比如常见的有:

  • 数据库访问的封装

  • Junit单元测试

  • JavaWeb的Servlet中关于doGet/doPost方法调用

  • Hibernate中模板程序

  • Spring中JDBCTemlate、HibernateTemplate等


7、接口(interface) 

7.1 概述

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要...则必须能...”的思想。继承是一个"是不是"的is-a关系,而接口实现则是 "能不能"的has-a关系。

例如:电脑都预留了可以插入USB设备的USB接口,USB接口具备基本的数据传输的开启功能和关闭功能。你能不能用USB进行连接,或是否具备USB通信功能,就看你能否遵循USB接口规范

接口的本质是契约、标准、规范,就像我们的法律一样。制定好后大家都要遵守。

7.2 定义格式 

接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。

引用数据类型:数组,类,枚举,接口,注解。

7.2.1 接口的生命格式 

[修饰符] interface 接口名{
    //接口的成员列表:
    // 公共的静态常量
    // 公共的抽象方法
    
    // 公共的默认方法(JDK1.8以上)
    // 公共的静态方法(JDK1.8以上)
    // 私有方法(JDK1.9以上)
}

示例代码:

public interface USB3{
    //静态常量
    long MAX_SPEED = 500*1024*1024;//500MB/s

    //抽象方法
    void in();
    void out();

    //默认方法
    default void start(){
        System.out.println("开始");
    }
    default void stop(){
        System.out.println("结束");
    }

    //静态方法
    static void show(){
        System.out.println("USB 3.0可以同步全速地进行读写操作");
    }
}

7.2.2 接口的成员变量说明 

在JDK8.0 之前,接口中只允许出现:

(1)公共的静态的常量:其中public static final可以省略

(2)公共的抽象的方法:其中public abstract可以省略

理解:接口是从多个相似类中抽象出来的规范,不需要提供具体实现

 在JDK8.0 时,接口中允许声明默认方法静态方法

(3)公共的默认的方法:其中public 可以省略,建议保留,但是default不能省略

(4)公共的静态的方法:其中public 可以省略,建议保留,但是static不能省略

在JDK9.0 时,接口又增加了:
(5)私有方法

除此之外,接口中没有构造器,没有初始化块,因为接口中没有成员变量需要动态初始化。

7.3 接口的使用规则 

7.3.1 类实现接口(implements)

接口不能创建对象,但是可以被类实现(implements ,类似于被继承)。

类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。

[修饰符] class 实现类  implements 接口{
	// 重写接口中抽象方法[必须],当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法[可选]
}

[修饰符] class 实现类 extends 父类 implements 接口{
    // 重写接口中抽象方法[必须],当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法[可选]
}

注意:

  1. 如果接口的实现类是非抽象类,那么必须重写接口中所有抽象方法

  2. 默认方法可以选择保留,也可以重写。

重写时,default单词就不要再写了,它只用于在接口中表示默认方法,到类中就没有默认方法的概念了  

      3. 接口中的静态方法不能被继承也不能被重写

示例:

interface USB{		// 
	public void start() ;
	public void stop() ;	
}
class Computer{
	public static void show(USB usb){	
		usb.start() ;
		System.out.println("=========== USB 设备工作 ========") ;
		usb.stop() ;
	}
};
class Flash implements USB{
	public void start(){	// 重写方法
		System.out.println("U盘开始工作。") ;
	}
	public void stop(){		// 重写方法
		System.out.println("U盘停止工作。") ;
	}
};
class Print implements USB{
	public void start(){	// 重写方法
		System.out.println("打印机开始工作。") ;
	}
	public void stop(){		// 重写方法
		System.out.println("打印机停止工作。") ;
	}
};
public class InterfaceDemo{
	public static void main(String args[]){
		Computer.show(new Flash()) ;
		Computer.show(new Print()) ;

		c.show(new USB(){
			public void start(){
				System.out.println("移动硬盘开始运行");
			}
			public void stop(){
				System.out.println("移动硬盘停止运行");
			}
		});
	}
};

7.3.2 接口的多实现

在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。

实现格式:

[修饰符] class 实现类  implements 接口1,接口2,接口3。。。{
	// 重写接口中所有抽象方法[必须],当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法[可选]
}

[修饰符] class 实现类 extends 父类 implements 接口1,接口2,接口3。。。{
    // 重写接口中所有抽象方法[必须],当然如果实现类是抽象类,那么可以不重写
  	// 重写接口中默认方法[可选]
}

 接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次

定义多个接口:

public interface A {
    void showA();
}

public interface B {
    void showB();
}

定义实现类:

public class C implements A,B {
    @Override
    public void showA() {
        System.out.println("showA");
    }

    @Override
    public void showB() {
        System.out.println("showB");
    }
}

测试类:

public class TestC {
    public static void main(String[] args) {
        C c = new C();
        c.showA();
        c.showB();
    }
}

7.3.3 接口的多继承 

一个接口能继承另一个或者多个接口,接口的继承也使用 extends 关键字,子接口继承父接口的方法。

定义父接口:

public interface Chargeable {
    void charge();
    void in();
    void out();
}

定义子接口:

public interface UsbC extends Chargeable,USB3 {
    void reverse();
}

定义子接口的实现类:

public class TypeCConverter implements UsbC {
    @Override
    public void reverse() {
        System.out.println("正反面都支持");
    }

    @Override
    public void charge() {
        System.out.println("可充电");
    }

    @Override
    public void in() {
        System.out.println("接收数据");
    }

    @Override
    public void out() {
        System.out.println("输出数据");
    }
}

所有父接口的抽象方法都有重写。
方法签名相同的抽象方法只需要实现一次。

7.3.4 接口与实现类对象构成多态

实现类实现接口,类似于子类继承父类,因此,接口类型的变量与实现类的对象之间,也可以构成多态引用。通过接口类型的变量调用方法,最终执行的是你new的实现类对象实现的方法体。

接口的不同实现类:

public class Mouse implements USB3 {
    @Override
    public void out() {
        System.out.println("发送脉冲信号");
    }

    @Override
    public void in() {
        System.out.println("不接收信号");
    }
}
public class KeyBoard implements USB3{
    @Override
    public void in() {
        System.out.println("不接收信号");
    }

    @Override
    public void out() {
        System.out.println("发送按键信号");
    }
}

测试类:

public class TestComputer {
    public static void main(String[] args) {
        Computer computer = new Computer();
        USB3 usb = new Mouse();
        computer.setUsb(usb);
        usb.start();
        usb.out();
        usb.in();
        usb.stop();
        System.out.println("--------------------------");

        usb = new KeyBoard();
        computer.setUsb(usb);
        usb.start();
        usb.out();
        usb.in();
        usb.stop();
        System.out.println("--------------------------");

        usb = new MobileHDD();
        computer.setUsb(usb);
        usb.start();
        usb.out();
        usb.in();
        usb.stop();
    }
}

7.3.5 使用接口的静态成员 

接口不能直接创建对象,但是可以通过接口名直接调用接口的静态方法和静态常量。

public class TestUSB3 {
    public static void main(String[] args) {
        //通过“接口名.”调用接口的静态方法 (JDK8.0才能开始使用)
        USB3.show();
        //通过“接口名.”直接使用接口的静态常量
        System.out.println(USB3.MAX_SPEED);
    }
}

7.3.6 使用接口的非静态方法 

  • 对于接口的静态方法,直接使用“接口名.”进行调用即可
            也只能使用“接口名."进行调用,不能通过实现类的对象进行调用

  • 对于接口的抽象方法、默认方法,只能通过实现类对象才可以调用
            接口不能直接创建对象,只能创建实现类的对象

public class TestMobileHDD {
    public static void main(String[] args) {
        //创建实现类对象
        MobileHDD b = new MobileHDD();

        //通过实现类对象调用重写的抽象方法,以及接口的默认方法,如果实现类重写了就执行重写的默认方法,如果没有重写,就执行接口中的默认方法
        b.start();
        b.in();
        b.stop();

        //通过接口名调用接口的静态方法
//        MobileHDD.show();
//        b.show();
        Usb3.show();
    }
}

 7.4 JDK8中相关冲突问题

7.4.1 默认方法冲突问题

(1)类优先原则

当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法。代码如下:

定义接口:

public interface Friend {
    default void date(){//约会
        System.out.println("吃喝玩乐");
    }
}

定义父类:

public class Father {
    public void date(){//约会
        System.out.println("爸爸约吃饭");
    }
}

定义子类:

public class Son extends Father implements Friend {
    @Override
    public void date() {
        //(1)不重写默认保留父类的
        //(2)调用父类被重写的
//        super.date();
        //(3)保留父接口的
//        Friend.super.date();
        //(4)完全重写
        System.out.println("跟康师傅学Java");
    }
}

定义测试类:

public class TestSon {
    public static void main(String[] args) {
        Son s = new Son();
        s.date();
    }
}

 

(2)接口冲突

  • 当一个类同时实现了多个父接口,而多个父接口中包含方法签名相同的默认方法时

声明接口:

public interface BoyFriend {
    default void date(){//约会
        System.out.println("神秘约会");
    }
}

 选择保留其中一个,通过“接口名.super.方法名"的方法选择保留哪个接口的默认方法。

public class Girl implements Friend,BoyFriend{

    @Override
    public void date() {
        //(1)保留其中一个父接口的
//        Friend.super.date();
//        BoyFriend.super.date();
        //(2)完全重写
        System.out.println("跟康师傅学Java");
    }

}

测试类:

public class TestGirl {
    public static void main(String[] args) {
        Girl girl = new Girl();
        girl.date();
    }
}

  • 当一个子接口同时继承了多个接口,而多个父接口中包含方法签名相同的默认方法时  

 另一个父类接口:

public interface USB2 {
    //静态常量
    long MAX_SPEED = 60*1024*1024;//60MB/s

    //抽象方法
    void in();
    void out();

    //默认方法
    public default void start(){
        System.out.println("开始");
    }
    public default void stop(){
        System.out.println("结束");
    }

    //静态方法
    public static void show(){
        System.out.println("USB 2.0可以高速地进行读写操作");
    }
}

 子接口:

public interface USB extends USB2,USB3 {
    @Override
    default void start() {
        System.out.println("Usb.start");
    }

    @Override
    default void stop() {
        System.out.println("Usb.stop");
    }
}

子接口重写默认方法时,default关键字可以保留。
子类重写默认方法时,default关键字不可以保留。

7.4.2 常量冲突问题

  • 当子类继承父类又实现父接口,而父类中存在与父接口常量同名的成员变量,并且该成员变量名在子类中仍然可见。

  • 当子类同时实现多个接口,而多个接口存在相同同名常量。

 此时在子类中想要引用父类或父接口的同名的常量或成员变量时,就会有冲突问题。

父类和父接口:

public class SuperClass {
    int x = 1;
}
public interface SuperInterface {
    int x = 2;
    int y = 2;
}
public interface MotherInterface {
    int x = 3;
}

子类:

public class SubClass extends SuperClass implements SuperInterface,MotherInterface {
    public void method(){
//        System.out.println("x = " + x);//模糊不清
        System.out.println("super.x = " + super.x);
        System.out.println("SuperInterface.x = " + SuperInterface.x);
        System.out.println("MotherInterface.x = " + MotherInterface.x);
        System.out.println("y = " + y);//没有重名问题,可以直接访问
    }
}

7.5 接口的总结 

  • 接口本身不能创建对象,只能创建接口的实现类对象,接口类型的变量可以与实现类对象构成多态引用。

  • 声明接口用interface,接口的成员声明有限制:

    • (1)公共的静态常量

    • (2)公共的抽象方法

    • (3)公共的默认方法(JDK8.0 及以上)

    • (4)公共的静态方法(JDK8.0 及以上)

    • (5)私有方法(JDK9.0 及以上)

  • 类可以实现接口,关键字是implements,而且支持多实现。如果实现类不是抽象类,就必须实现接口中所有的抽象方法。如果实现类既要继承父类又要实现父接口,那么继承(extends)在前,实现(implements)在后。

  • 接口可以继承接口,关键字是extends,而且支持多继承。

  • 接口的默认方法可以选择重写或不重写。如果有冲突问题,另行处理。子类重写父接口的默认方法,要去掉default,子接口重写父接口的默认方法,不要去掉default。

  • 接口的静态方法不能被继承,也不能被重写。接口的静态方法只能通过“接口名.静态方法名”进行调用。


8、内部类

8.1 概述

8.1.1 什么是内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类(InnerClass),类B则称为外部类(OuterClass)

 8.1.2 为什么要声明内部类

具体来说,当一个事物A的内部,还有一个部分需要一个完整的结构B进行描述,而这个内部的完整的结构B又只为外部事物A提供服务,不在其他地方单独使用,那么整个内部的完整结构B最好使用内部类。
总的来说,遵循高内聚、低耦合的面向对象开发原则。

8.2 成员内部类

8.2.1 概述

如果成员内部类中不使用外部类的非静态成员,那么通常将内部类声明为静态内部类,否则声明为非静态内部类。

语法格式:

[修饰符] class 外部类{
    [其他修饰符] [static] class 内部类{
    }
}

 成员内部类的使用特征,概括来讲有如下两种角色:

  • 成员内部类作为类的成员的角色

    • 和外部类不同,Inner class还可以声明为private或protected;

    • 可以调用外部类的结构。(注意:在静态内部类中不能使用外部类的非静态成员)

    • Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员变量;

  • 成员内部类作为类的角色

    • 可以在内部定义属性、方法、构造器等结构

    • 可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关

    • 可以声明为abstract类 ,因此可以被其它的内部类继承

    • 可以声明为final的,表示不能被继承

    • 编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)

注意点:

  1. 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式

  2. 成员内部类可以直接使用外部类的所有成员,包括私有的数据

  3. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的

8.2.2 创建成员内部类

实例化静态内部类

外部类名.静态内部类名 变量 = 外部类名.静态内部类名();
变量.非静态方法();

实例化非静态内部类

外部类名 变量1 = new 外部类();
外部类名.非静态内部类名 变量2 = 变量1.new 非静态内部类名();
变量2.非静态方法();

8.2.3 代码示例

public class TestMemberInnerClass {
    public static void main(String[] args) {
        //创建静态内部类实例,并调用方法
        Outer.StaticInner inner = new Outer.StaticInner();
        inner.inFun();
        //调用静态内部类静态方法
        Outer.StaticInner.inMethod();

        System.out.println("*****************************");
        
        //创建非静态内部类实例(方式1),并调用方法
        Outer outer = new Outer();
        Outer.NoStaticInner inner1 = outer.new NoStaticInner();
        inner1.inFun();

        //创建非静态内部类实例(方式2)
        Outer.NoStaticInner inner2 = outer.getNoStaticInner();
        inner1.inFun();
    }
}
class Outer{
    private static String a = "外部类的静态a";
    private static String b  = "外部类的静态b";
    private String c = "外部类对象的非静态c";
    private String d = "外部类对象的非静态d";

    static class StaticInner{
        private static String a ="静态内部类的静态a";
        private String c = "静态内部类对象的非静态c";
        public static void inMethod(){
            System.out.println("Inner.a = " + a);
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("b = " + b);
        }
        public void inFun(){
            System.out.println("Inner.inFun");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("Inner.a = " + a);
            System.out.println("b = " + b);
            System.out.println("c = " + c);
//            System.out.println("d = " + d);//不能访问外部类的非静态成员
        }
    }

    class NoStaticInner{
        private String a = "非静态内部类对象的非静态a";
        private String c = "非静态内部类对象的非静态c";

        public void inFun(){
            System.out.println("NoStaticInner.inFun");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("a = " + a);
            System.out.println("b = " + b);
            System.out.println("Outer.c = " + Outer.this.c);
            System.out.println("c = " + c);
            System.out.println("d = " + d);
        }
    }


    public NoStaticInner getNoStaticInner(){
        return new NoStaticInner();
    }
}

8.3 局部内部类 

8.3.1 非匿名局部内部类

语法格式:

[修饰符] class 外部类{
    [修饰符] 返回值类型  方法名(形参列表){
            [final/abstract] class 内部类{
    	}
    }    
}
  • 编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名、$符号、编号。
            这里有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类

  • 和成员内部类不同的是,它前面不能有权限修饰符等

  • 局部内部类如同局部变量一样,有作用域

  • 局部内部类中是否能访问外部类的非静态的成员,取决于所在的方法

示例:

public class TestLocalInner {
    public static void main(String[] args) {
        Outer.outMethod();
        System.out.println("-------------------");

        Outer out = new Outer();
        out.outTest();
        System.out.println("-------------------");

        Runner runner = Outer.getRunner();
        runner.run();

    }
}
class Outer{

    public static void outMethod(){
        System.out.println("Outer.outMethod");
        final String c = "局部变量c";
        class Inner{
            public void inMethod(){
                System.out.println("Inner.inMethod");
                System.out.println(c);
            }
        }

        Inner in = new Inner();
        in.inMethod();
    }

    public void outTest(){
        class Inner{
            public void inMethod1(){
                System.out.println("Inner.inMethod1");
            }
        }

        Inner in = new Inner();
        in.inMethod1();
    }

    public static Runner getRunner(){
        class LocalRunner implements Runner{
            @Override
            public void run() {
                System.out.println("LocalRunner.run");
            }
        }
        return new LocalRunner();
    }

}
interface Runner{
    void run();
}

8.3.2 匿名内部类 

因为考虑到这个子类或实现类是一次性的,那么我们“费尽心机”的给它取名字,就显得多余。那么我们完全可以使用匿名内部类的方式来实现,避免给类命名的问题。

new 父类([实参列表]){
    重写方法...
}
new 父接口(){
    重写方法...
}

 使用匿名内部类的对象直接调用方法:

interface A{
	void a();
}
public class Test{
    public static void main(String[] args){
    	new A(){
			@Override
			public void a() {
				System.out.println("aaaa");
			}
    	}.a();
    }
}

 通过父类或父接口的变量多态引用匿名内部类的对象

interface A{
	void a();
}
public class Test{
    public static void main(String[] args){
    	A obj = new A(){
			@Override
			public void a() {
				System.out.println("aaaa");
			}
    	};
    	obj.a();
    }
}

 匿名内部类的对象作为实参

interface A{
	void method();
}
public class Test{
    public static void test(A a){
    	a.method();
    }
    
    public static void main(String[] args){
    	test(new A(){

			@Override
			public void method() {
				System.out.println("aaaa");
			}
    	});
    }   
}

  • 43
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值