内部类可以直接访问外部类成员吗_一文了解Java的内部类

81837953d4639a9ecb3e1eed03bc1557.png

在Java中,类通常都是独立存在的,但是我们可以在类中再定义类,这样的类被称为内部类。内部类定义位置的不同可以分为成员内部类、静态内部类、方法内部类、匿名内部类。相对于内部类,包含内部类的类被称为外部类。

1 内部类的意义

内部类从字面上是非常容易理解的,无非就是在类的内部定义的类。那么为什么要在类的内部再定义类呢?

1.私有变量访问:我们可以把内部类当成外部类的一个成员,内部类对于外部类的其它私有成员变量来说是不受访问控制权限所影响的。那么内部类就实现了跨域访问的特性。

2.隐藏式的多继承。这个多继承不同于接口的"多继承",而是实实在在的多继承。内部类也是一个单独类,既然是类就有面向对象的特性,它就可以进行继承操作,并且内部类的继承操作对于外部类是否发生过继承是没有影响的。这样内部类和外部类就共同实现了多继承操作(如果内部类中还有内部类,继承的个数会被扩大下去)。

3.可以作为抽象类、接口的匿名实现。一些接口和抽象类中的抽象方法非常少,单独的创建实现子类非常的麻烦,我们就可以通过匿名内部类的方式直接实现接口或者抽象类,这样能够简化类的设计过程。例如Swing中的事件处理、函数式接口都可以直接通过内部类来实现。

2 内部类种类及定义

在定义内部类时,内部类定义的位置不同其意义也不相同。内部类大体上可以分为四种类型:成员内部类,静态内部类,局部内部类、匿名内部类。其中成员内部类和静态内部类都是直接定义在外部类中,它们可以作为单独的类被外部其它类所访问(受限于访问修饰符)。局域内部类和匿名内部类定义在方法中,它们并不会被外部的类所访问,只是一种临时类。

2.1 成员内部类

成员内部类,直接定义在类的内部,与类的成员变量和方法属于同一层级。下面代码是成员内部类的定义示例。

ffee7d1c338c9d56f3870f83d7205e17.png

在上述代码示例中,Inner就是一个内部类,包含Inner类的Outer类我们称之为外部类。Inner类就是典型的成员内部类。成员内部类可以用常用的四种访问控制修饰符进行修饰,其访问控制与成员变量的访问控制修饰一致。

在其它外围类中,创建内部类与普通类是相似的,可以直接进行实例化操作。如果在其它外围类中要完成对内部类Inner的实例创建,必须在外围类中建立Outer对象,再由Outer对象来创建内部类Inner(如下面代码所示)。

d0d453f521e8fe266e6d48a5fd7f54fe.png

由于Inner内部类定义时采用了默认的访问修饰,所以务必保证上述代码所属的类与Outer类在同一包中。在外围类中使用内部类时,要注意内部类的访问修饰,如果内部类是private修饰的,只能在外部类中使用,其它类是无法声明内部类的。

2.2 静态内部类

内部成员类被static修饰就变成了静态内部类,静态内部类可以直接进行声明并实例化(如下面代码所示)。

e984a7cccd9a8b0c2b645b35ca86af0f.png

在上述代码中,Inner类就是一个静态内部类,静态内部类同样也可以用四种类型的访问控制符进行修饰。访问规则与成员变量访问控制修饰规则一样。

外部类对静态内部类的访问与成员内部类的访问方式一样,直接实例化即可。静态内部类和成员内部类在使用上的区别主要是在创建过程中存在着差异。

2.3 局部内部类

具备内部类是定义在外部类中的方法中(或流程控制语句中)。局部内部类不能被外部类和外围类访问,它只能在定义的局部位置使用(参考局部变量的使用,定义和使用见下面代码示例)。

db22e09c5338cb050ae8c15ea2fc4c16.png

在上述代码示例中,showInner()方法中定义的Inner就是一个方法局部内部类,方法局部内部类只能在方法中使用,出了方法就不能被使用。在showInner2()方法中,Inner2是一个流程控制局部类,它只能在流程内使用。

局部类与局部变量拥有一样的生命周期,与局部变量一样,不能被访问控制修饰符进行修饰。

2.4 匿名内部类

匿名内部类是局部内部类最常用的一种表现形式。匿名内部类只有类的实现体,而没有类的方法。

我们知道接口(抽象类)是不能直接实例化的,我们必须通过实例化它们的子类来间接的完成接口(抽象类)的实例化。而匿名内部类 相当于我们在使用接口(抽象类)时,临时创造了一个子类,但是这个子类我们没有给它命名,我们称之为匿名类。通常这样的类是在方法调用过程中创建并使用的(下面代码演示了匿名内部类的使用)。

de6ab41c0927efcb09db44d2d2613ca8.png

在上述示例中,我们在main方法中直接实例化抽象类Animal,在实例化的过程中我们实现了一个匿名的内部类,并将Animal中的抽象方法eat实现。实际上dog对象引用的就是我们创建的匿名内部类。

3 内部类的外部访问

内部类对外部类可以进行无缝的访问,无视外部类的访问修饰。在类的实例方法中,如果类的成员变量和局部变量发生重名冲突时,使用this关键字可以表示当前对象。

在内部类中使用"this.变量名"方式表示内部类的成员变量,而外部类的成员变量则用"外部类名.this.变量名"的方式表示外部类的成员变量(如下面代码所示)。

7b48b798b5b4f2eb288b40ae01d08ca8.png

在上述代码示例中,内部类getInnerName方法中,我们用this关键字对内部类的成员变量进行返回操作,在getOuterName方法中,我们使用Outer.this对外部类的成员变量进行操作。

对于静态内部类,它的外部访问比较特殊,静态内部类只能访问外部类的静态变量。而且在非静态的内部类中,是不能创建静态的类变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值