java 内部类的使用
内部类 就是在类中嵌套的另一个类。 非静态内部类创建内部类的方式就是把类定义在外部类里面。 ?? 内部类对于外部类是特殊的,内部类可以访问到外部类的所有成员,包括私有成员。 String str = "Outer" Inner() {str = "Inner"
当生成一个内部类对象的时候,它自动和它的外部类有联系, 内部类的类型在外部类除外部类静态方法外不能直接使用内部类的名字,应为OuterClassName.InnerClassName。 内部类可以为私有权限,当内部类为私有时,外部类外对内部类是不可见的。内部类不能有static的域,除非是final的。 创建内部类的方法: 1,外部类方法发返回内部类的引用。 2, </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Inner getInner() {
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> Inner();
}
} <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> Test {<span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String args) { Outer out = <span style="color: #0000ff;">new<span style="color: #000000;"> Outer(); Outer.Inner in = out.<span style="color: #0000ff;">new<span style="color: #000000;"> Inner(); Outer.Inner in1 =<span style="color: #000000;"> out.getInner(); } } 在内部类通过OuterClassName.this可以访问外部类对象。 a = 17 a = 3 .a + " " + Outer.<span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> Test {
<span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { Outer out = <span style="color: #0000ff;">new<span style="color: #000000;"> Outer(); Outer.Inner in = out.<span style="color: #0000ff;">new<span style="color: #000000;"> Inner(); in.f(); } } // output:3 17 类也可以定义在代码块,包括方法内部。这样类的作用域也就限制在方法内部。此时内部类不能访问外部类,因为它不是外部类的一部分,但是它可以访问当前代码块的常量。 【名字实在是很糟糕 <span style="color: #0000ff;">class<span style="color: #000000;"> Outer {
<span style="color: #0000ff;">public<span style="color: #000000;"> Inf f() { <span style="color: #0000ff;">class Inner <span style="color: #0000ff;">implements<span style="color: #000000;"> Inf { <span style="color: #0000ff;">public <span style="color: #0000ff;">void<span style="color: #000000;"> f() { System.out.println("Inner"<span style="color: #000000;">); } } <span style="color: #0000ff;">return <span style="color: #0000ff;">new<span style="color: #000000;"> Inner(); } } <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> Test{ 在这个例子中,通过向上转型为接口类型,完全隐藏了具体实现。 匿名内部类匿名内部类就是没有名字的内部类 <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> AnonymousInnerClassTest {
<span style="color: #0000ff;">public<span style="color: #000000;"> Contents contents() { <span style="color: #0000ff;">return <span style="color: #0000ff;">new<span style="color: #000000;"> Contents() { <span style="color: #0000ff;">private <span style="color: #0000ff;">int i = 11<span style="color: #000000;">; <span style="color: #0000ff;">public <span style="color: #0000ff;">int value() { <span style="color: #0000ff;">return<span style="color: #000000;"> i; } }; } <span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { AnonymousInnerClassTest a = <span style="color: #0000ff;">new<span style="color: #000000;"> AnonymousInnerClassTest(); Contents c =<span style="color: #000000;"> a.contents(); System.out.println(c.value()); } } 乍一看很奇怪,但其实很方便的使用方法。在需要使用类的地方直接写一个类的定义。 匿名内部类和在方法中定义类使用功能差不多,区别就是匿名内部类只能产生一个对象。 很容易想到因为匿名类没有名字,而构造器的名字需要和类名一样,所以……它没!有!构!造!器! 如果基类需要有参数的构造器怎么办?只需要在new的时候加上参数就可以了。 i, j) { .i = i; .j =<span style="color: #0000ff;">class<span style="color: #000000;"> B {
<span style="color: #0000ff;">public A f(<span style="color: #0000ff;">int i,<span style="color: #0000ff;">int<span style="color: #000000;"> j) { <span style="color: #0000ff;">return <span style="color: #0000ff;">new<span style="color: #000000;"> A(i,j) { <span style="color: #008000;">//<span style="color: #008000;">... <span style="color: #000000;"> }; } } 那么如果一个匿名内部类需要构造器来初始化的时候怎么办呢? 在学习类的初始化顺序的时候知道,在构建类对象时是先执行非静态代码段再执行构造器。所以这里可以用代码块带到类似构造器的效果。 <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> A {
<span style="color: #0000ff;">public<span style="color: #000000;"> B getB() { <span style="color: #0000ff;">return <span style="color: #0000ff;">new<span style="color: #000000;"> B() { { System.out.println("Inside Instance initialize."<span style="color: #000000;">); } <span style="color: #0000ff;">public <span style="color: #0000ff;">void print() { System.out.println("in anonymous f()"<span style="color: #000000;">); } }; }
} Java8中,可以不是final了,但是默认是final的,在内部类不能改变。原因是在内部类,外部变量相当于形参,也就是在内部类改变对外部类无影响,就会造成数据不同步的问题。 <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> A {
<span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { <span style="color: #0000ff;">int x = 0<span style="color: #000000;">; <span style="color: #0000ff;">new<span style="color: #000000;"> I() { <span style="color: #008000;">//<span style="color: #008000;"> x = 3; error <span style="color: #0000ff;">void<span style="color: #000000;"> f() { System.out.println(x); } }; } } Java8中匿名内部类可以用lambda表达式代替,感觉超简洁。语法糖,写代码方便,不过也增加了阅读代码的难度。 A1 { <span style="color: #0000ff;">class<span style="color: #000000;"> A2 {
<span style="color: #0000ff;">public<span style="color: #000000;"> A1 f() { <span style="color: #0000ff;">return () -> { System.out.println("lambda expression."<span style="color: #000000;">); }; } } <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> Test { 略过略过,以后再学,,, 迭代器实现 <span style="color: #0000ff;">class<span style="color: #000000;"> Sequence {
<span style="color: #0000ff;">private <span style="color: #0000ff;">int<span style="color: #000000;">[] items; <span style="color: #0000ff;">private <span style="color: #0000ff;">int next = 0<span style="color: #000000;">; <span style="color: #0000ff;">public <span style="color: #0000ff;">int<span style="color: #000000;"> size() { <span style="color: #0000ff;">return<span style="color: #000000;"> items.length; } <span style="color: #0000ff;">public Sequence(<span style="color: #0000ff;">int<span style="color: #000000;"> size) { items = <span style="color: #0000ff;">new <span style="color: #0000ff;">int<span style="color: #000000;">[size]; } <span style="color: #0000ff;">public <span style="color: #0000ff;">void add(<span style="color: #0000ff;">int<span style="color: #000000;"> x) { items[next++] =<span style="color: #000000;"> x; } <span style="color: #0000ff;">public<span style="color: #000000;"> Iterator iterator() { <span style="color: #0000ff;">return <span style="color: #0000ff;">new<span style="color: #000000;"> Iterator() { <span style="color: #0000ff;">int i = 0<span style="color: #000000;">; <span style="color: #0000ff;">public <span style="color: #0000ff;">int<span style="color: #000000;"> next() { <span style="color: #0000ff;">return items[i++<span style="color: #000000;">]; } <span style="color: #0000ff;">public <span style="color: #0000ff;">boolean<span style="color: #000000;"> hasNext(){ <span style="color: #0000ff;">if (i == next) <span style="color: #0000ff;">return <span style="color: #0000ff;">false<span style="color: #000000;">; <span style="color: #0000ff;">return <span style="color: #0000ff;">true<span style="color: #000000;">; } }; } } <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> Test { 静态内部类静态内部类常被称作嵌套类。静态内部类和外部类联系不是很大。 创建静态内部类的对象,并不需要外部类的对象。 不能从嵌套类的对象中访问非静态的外围类对象。 普通的内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以包含所有这些东西。 <span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> A {
<span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { B.C c = <span style="color: #0000ff;">new<span style="color: #000000;"> B.C(); } } 内部类的继承既然内部类对象一定要有某个关联外部类对象,那么继承自内部类的子类也一定需要外部类对象。 "外部类""内部类"<span style="color: #0000ff;">public <span style="color: #0000ff;">class InheritInner <span style="color: #0000ff;">extends<span style="color: #000000;"> WithInner.Inner {
InheritInner(WithInner wi) { wi.<span style="color: #0000ff;">super();<span style="color: #008000;">//<span style="color: #008000;"> 必须使用这样的语法 外部类对象引用+.super System.out.println("继承自内部类的类"<span style="color: #000000;">); } <span style="color: #0000ff;">public <span style="color: #0000ff;">static <span style="color: #0000ff;">void<span style="color: #000000;"> main(String[] args) { WithInner wi = <span style="color: #0000ff;">new<span style="color: #000000;"> WithInner(); InheritInner ii = <span style="color: #0000ff;">new<span style="color: #000000;"> InheritInner(wi); } } <span style="color: #008000;">/<span style="color: #008000;"> 外部类 内部类 继承自内部类的类<span style="color: #008000;">/ 内部类不能被重写,如下,此时A.Inner 和 B.Inner是毫不相关的两个类。 A { B A { Inner {} }
继承类的内部类可以继承自基类的内部类 此时不再需要上面继承内部类的构造器 <span style="color: #0000ff;">class A1 <span style="color: #0000ff;">extends<span style="color: #000000;"> A {
<span style="color: #0000ff;">class B <span style="color: #0000ff;">extends<span style="color: #000000;"> A.B { } } 内部类的名字 每个类都会生成一个.class文件。内部类的名字是:外部类名$内部类名.class,匿名内部类也有名字,外部类名$+一个数字来简单标识。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |