java_常见的四种内部类详解

目录

内部类的分类

局部位置

成员位置

1)局部内部类

2)匿名内部类(是一个类同时是一个对象)

(1)基于接口

传统

简化开发

(2)基于类(普通类,抽象类....)

匿名内部类当实参传递(本质也是一个对象)

3)成员内部类

外部其他类想访问成员内部类的方法

第一个方法:

第二个方法:

4)静态内部类


内部类的分类

局部位置

调用:如果要调用,创建类对象,对象调用方法即可(方法内有内部类)

作用域:方法或者代码块内

定义在外部类局部位置上(比如方法内,和局部变量一个层级):

1)局部内部类(有类名)

2)匿名内部类(没有类名,重点)(JDK底层还是有名字的)

成员位置

作用域:整个类体

定义在外部类的成员位置上(和属性,方法一个层级):

1)成员内部类(没用static修饰)

2)静态内部类(使用static修饰)


1)局部内部类

  1. 可以直接访问外部类所有成员,包括私有。
  2. 局部变量是不能添加访问修饰符的,只能添加final。
  3. 外部类想访问内部类需要创建一个外部类对象来创建内部类对象,再由内部类对象来访问。
  4. 外部类和局部内部类的成员重名,默认就近原则,内部类想访问外部类重名成员,则用外部类名.this.成员,因为不是静态所以要加this(哪个对象调用方法,this则指向哪个对象)(所有内部类共享这条规则,除了静态内部类

2)匿名内部类(是一个类同时是一个对象)

底层创建一个只能使用一次的类继承该类

格式:new类/接口(参数列表){类体}

(1)基于接口

传统

一般是写一个类,实现该接口,并向上转型为接口创建对象,调用接口方法。

,就会动态绑定子类的方法。

因为接口类型可以指向实现了该接口的类的对象实例。

简化开发

编译类型是接口类型,而运行类型是匿名内部类(底层系统会分配,用外部类的名称加上$1)

如果实在想看,变量名.getClass()就看到了。

接口名 变量名=new 接口名(){

        @Override

        接口方法();

};

变量名.重写后的接口方法();。

并且创建了一个实例,并把实例地址赋给变量名。

匿名内部类创建一次就不能使用了销毁了,但是那个变量地址还是可以反复使用。

(2)基于类(普通类,抽象类....)

创建对象:Person p=new Person();

编译类型:Person

运行类型:Person


创建匿名内部类:Person p=new Person(){};

编译类型:Person

运行类型:(外部类名)$(创建匿名内部类的次数)

                就是一个匿名类继承Person,所以运行类型是那个匿名类


第一种调用方式(要多次调用匿名类方法,用一个p变量接收):

Person p=new Person(){

        @Override

        类的方法(){

        }

};

p.类的方法();

第二种调用方式(只调用一次匿名内部类方法,则不需要变量接收):

new Person(){

        @Override

        类的方法(){

        super.xxx();(调用父类方法)

        }

}.类的方法();

如果一个类的构造器里面有参数,那当你基于这个类使用匿名内部类并传入参数时,会调用此类的构造器。

匿名内部类当实参传递(本质也是一个对象)

//接口
interface PP{
    //动态绑定机制
    void show();
}
//有个方法用接口类型作为参数
public static void LL(PP p){
    p.show();
}

//(1)在主方法中,用匿名内部类做一个对象,这个对象重写了show方法并传入参数
LL(new PP(){
    @Override
    //在这里改动show(),不影响其他实例
    public void show(){
        System.out.println("999999999");
    }
});

//(2)传统方法(硬编码)
LL(new Car());
//在这里改动方法show(),会影响所有Car实例
class Car implements PP{
    @Override
    public void show(){
        System.out.println("999999999");
    }
}

3)成员内部类

没有写在方法中,也不在代码块中,且没有static修饰。

和上面两个相同的是,可以访问外部类的所有成员,包含私有的,

和上面两个不同的是,它可以添加任意的访问修饰符,因为地位不再是一个局部变量,而是成员变量。

外部其他类想访问成员内部类的方法

第一个方法:

则先创建一个外部类对象,再用这个对象创建一个内部类对象,再用这个内部类对象去调用方法。

第二个方法:

在外部类中定义一个方法,该方法返回一个内部类对象实例。则直接在外部类对象调用此方法即可得到一个内部类对象。。

4)静态内部类

类被声明为静态类时,必须为内部类!
反之:静态类一定是内部类!

定义在成员变量的位置,且有static修饰。

可以直接访问外部类所有静态成员(包括私有),但是不可以访问非静态成员。

可以添加任意的访问修饰符,因为地位是成员变量。

重点!!!

静态类不可以实例化!但是静态内部类可以实例化!!

外部类和局部内部类的成员重名,默认就近原则,内部类想访问外部类重名成员,则用外部类名.成员(因为你只能访问外部类静态成员,静态成员是属于类的,不需要加this)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七qi_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值