java遗珠之嵌套类
Posted 吴冬冬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java遗珠之嵌套类相关的知识,希望对你有一定的参考价值。
使用内部类的原因
1.合乎只在一个地方备用的逻辑: 如果一个类仅仅被一个别的类使用,那么把这个类嵌入到使用它的类中非常符合逻辑,嵌套这样的帮助类
是的package变得简洁。
2.有益于封装:
如果两个类A和B,如果B需要访问A定义为private的成员,那么B嵌套到A类中,即使A的成员是private的B也可以访问,另外B类也可以被隐藏起来,不被外部访问。
3.可读性好且易于维护
在顶级类中在使用它们的地方嵌套很多小的类利于可读和维护
静态内部类
像类变量和类方法一样,静态内部类通过它的封闭类来调用。并且像类方法一样,静态内部类不能直接访问定义在外部类的实例变量和实例方法,只能通过外部类的对象引用才可以使用它们。
静态内部类使用外部类或者其他类的实例成员,需要像其他顶级类一样使用它们。静态内部类的行为看起来像是一个顶级类一样,只是仅仅因为包装便利的关系,才将它嵌套到另一个顶级类内部。
静态内部类需要使用它的包装类来访问。
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
内部类
像实例变量和实例方法一样,内部类需要通过它的封闭类的实例来调用,并且它可以直接访问对象的方法和字段,因为内部类是通过外部类的实例关联,因此它不能定义静态的成员。
内部类的实例要依托于它的外包类的实例存在
class OuterClass
...
class InnerClass
...
要实例化内部类必须实例化外部类,然后在外部类实例的基础上创建内部类:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
隐匿
如果定义一个类型(比如成员变量或者参数名称)在一个特定的区域(比如内部类或者方法参数)和封闭区域内的另一个定义重名,那么这个定义会隐匿掉封闭区域的定义,你无法仅仅通过名字来使用被隐匿掉的定义,可以看如下代码
public class ShadowTest
public int x = 0;
class FirstLevel
public int x = 1;
void methodInFirstLevel(int x)
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
public static void main(String... args)
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
输出如下:
x = 23
this.x = 1
ShadowTest.this.x = 0
这个例子定义了三个名字为x
的变量,ShadowTest类的成员变量x,内部类FirstLevel类的成员变量x,和methodInFirstLevel方法的参数x。methodInFirstLevel方法的参数x隐匿了内部类FirstLevel类的成员变量x,因此你在methodInFirstLevel方法中使用x时使用的是方法参数的x,为了使用内部类FirstLevel的成员变量x,你需要this关键字来指明是内部类FirstLevel类的成员变量x:
System.out.println("this.x = " + this.x);
为了使用更大范围的成员变量,你需要通过指定类名的方式,在此例子中,你在methodInFirstLevel中使用ShadowTest类的成员变量你需要如下做:
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
序列化
强烈建议不需要序列化内部类,包括本地类和匿名类。因为编译器编译某些构造器是比如内部类,会创建合成构造,由类,方法,字段和其他与源码不对应的构造器组成。合成构造可以在不更改jvm的前提下实现新的java特性,但是合成构造在不同的编译器下的实现也不通,也就是说生成的.class文件都是不同,因此序列化内部类后,由不同的JRE反序列化时就会出现问题。
以上是关于java遗珠之嵌套类的主要内容,如果未能解决你的问题,请参考以下文章