Java内部类

一、局部内部类

定义在外部类的局部位置,比如方法体中,并且有类名。

本质依旧是类。

1、可以访问外部类的所有成员,包括私有成员。

2、不能添加修饰符。

因为它等价于一个局部变量,局部变量不能使用修饰符。

可以使用final修饰,局部变量可以使用final修饰。

3、作用域:

仅在定义它的方法体或代码块中。

4、局部内部类访问外部类成员:

直接访问

5、外部类访问局部内部类成员:

先创建对象,再访问。(注意,必须在作用域内)

6、外部其他类无法访问内部类,因为内部类只是一个局部变量。

7、如果外部类和局部内部类的成员重名,遵循就近原则。

若想访问外部类成员,使用 外部类名.this.成员 去访问。

原因:

外部类名.this 本质就是外部类的对象,该对象就是目前调用自己的外部类对象。

二、匿名内部类

匿名內部类定义在外部类的 局部位置,比如方法体中,并且 没有类名。
本质也是类。
①本质是类;②内部类;③没有名字(其实有,系统分配);④同时是一个对象。
语法:

java 复制代码
    new 类名或接口名(参数列表){
        类体
    }

经典使用场景:
当作实参传递,简洁高效。
一、基于接口:
需求:
需要使用一个接口,但是只使用一次。
正常情况:
(1)定义子类、(2) 重写接口中的方法、(3) 创建子类对象、(4) 调用重写后的方法
因为只使用一次,且定义后就使用,因此专门定义该类没有意义。
解决:
使用匿名内部类:

a1和a2的编译类型为A,运行类型为Outer$1 和Outer$2
在底层:

java 复制代码
    class Outer$1 implement A{
        public void fun() {
            System.out.println("匿名内部类");
        }
    }

①先如上代码定义一个实现了接口A的类。
②立刻创建一个该类的对象,并赋值给变量a1。
③之后无法使用Outer$1创建新的对象了。
④由上可见,匿名内部类命名规则是外部类名 + $ +阿拉伯数字(是第几个匿名内部类,就是几)。
二、基于类:
需求:
需要使用一个接口,但是只使用一次。
正常情况:
(1)定义子类、(2) 重写父类中的方法、(3) 创建子类对象、(4) 调用重写后的方法
因为只使用一次,且定义后就使用,因此专门定义该类没有意义。

在底层:

java 复制代码
class Outer03$1 extend Fater{
    @Override
    void fun() {
        System.out.println("重写fun()方法");
        newFun();
    }
    void newFun(){
        System.out.println("新方法");
    }
}

①先如上代码定义一个实现了继承了Father的类。
②立刻创建一个该类的对象,并赋值给变量father。
③new Father("tom"){};中的字符串"tom"将传递给Father这个父类的构造器。
如果父类是抽象类,那么对于抽象类中的抽象方法就必须实现。
细节:
1、可以直接访问外部类的所有成员,包括私有的。
2、不能添加访问修饰符,因为它的地位就是一个局部变量。
3、作用域:在定义它的方法内或代码块内。
4、匿名内部类没有构造方法,因为匿名内部类是没有类名的。
5、匿名内部类不能定义任何静态成员、方法。
匿名内部类是晚于外部类加载的。
匿名内部类和其对象几乎是同时加载的(但是还是早于对象加载)。
而静态内容是属于类的,当类加载的时候就开始加载。
所以当匿名内部类中有静态内容,就会随着类加载,而这时和对象创建冲突。

三、成员内部类

就是一个定义在外部类成员位置的类。

细节:

1、可以直接访问外部类的所有成员。

2、可以有任何修饰符,它本身就是一个成员。

3、外部其他类使用成员内部类:

由于内部类使用的目的就是它自身不会有多个对象,没必要专门在外面定义,

所以外部其他类使用成员内部类情况很少,如果使用一般会在外面定义。

①外部类.成员内部类 类名 = 外部类对象.new 成员内部类();

内部成员类首先是一个成员,通过外部类对象.形式调用

它又是一个类,所以要new。

②在外部类中写一个方法,返回成员内部类的对象。

四、静态内部类

定义在外部类的成员位置上,且有static修饰。

细节:

1、可以访问外部类的所有静态成员,包括私有的,但不能访问非静态的。

原因:由于是静态的,在外部类加载时就已经创建,但是外部类其他非静态成员

还未创建,类似静态方法。

2、可以添加任何修饰符。

3、外部其他类访问静态内部类:

①new 外部类名.静态内部类名();

因为是静态的,所以直接通过外部类名可以访问,不需要外部类的对象。

②写一个方法,返回内部类的实例。

相关推荐
AskHarries4 分钟前
利用反射实现动态代理
java·后端·reflect
@月落5 分钟前
alibaba获得店铺的所有商品 API接口
java·大数据·数据库·人工智能·学习
liuyang-neu10 分钟前
力扣 42.接雨水
java·算法·leetcode
z千鑫14 分钟前
【人工智能】如何利用AI轻松将java,c++等代码转换为Python语言?程序员必读
java·c++·人工智能·gpt·agent·ai编程·ai工具
Flying_Fish_roe28 分钟前
Spring Boot-Session管理问题
java·spring boot·后端
赚钱给孩子买茅台喝29 分钟前
智能BI项目第四期
java·spring boot·spring cloud·aigc
陈大爷(有低保)2 小时前
UDP Socket聊天室(Java)
java·网络协议·udp
kinlon.liu2 小时前
零信任安全架构--持续验证
java·安全·安全架构·mfa·持续验证
王哲晓2 小时前
Linux通过yum安装Docker
java·linux·docker
java6666688882 小时前
如何在Java中实现高效的对象映射:Dozer与MapStruct的比较与优化
java·开发语言