JAVA 学习笔记 第三篇 内部类
2012-03-10 17:17
267 查看
这一段时间工作一直忙的不可开胶,下载的食品看的比较少,基本上都是在公交车或者睡觉前看看书。上次提到的一本《JAVA语言程序设计》中没有到内部类,现在必须道歉,愿望它了。是在图形界面应用程序中事件驱动的应用程序设计中讲到的。不过总体上来说,也就是很短的一小节。也许是JAVA中内部类规则比较复杂,作者不愿多说,毕竟是一本基础入门书籍。于是我在互联网上找了一些资料,这里记录一下学习成果。
所谓内部类,就是在一个类的内部再声明一个类类型。
这样一个包含内部类的JAVA源文件 编译之后 会得到两个class文件:
我反编译了这两个类文件,查看内容是 解决的一些疑惑的同事也带了了一些疑惑(如图所示)。可能是反编译器的问题,类名应该是OuterClass$InnerClass,其中的编码其实是汉字。
解决的疑惑是:1,在外部来的 外部,非静态的内部类的创建为什么一定要绑定外部类,也就是说,必须县创建外部类,然后通过外部类的实例才能创建内部类的实例。
从反编译后的代码 可以看到,内部多了一个 this$0 字段,它是外部类型 的,而且 构造方法中 多出了一个为 this$0赋值的语句,看到这里我们就应该能够推理出 内部类的不少规则了
1.非静态内部类必须 通过外部类的实例来创建,或者通过 内部类的一个实例方法 在外部类内部创建 并返回一个内部非静态类的实例。但是无论如何,必须在外部类的实例上基础上创建内部类。
2、内部类可以访问 外部类的 成员变量。这一点也很容易理解了,内部类中的this$0关键则应该是和 this关键字一样的作用,用于方位实例的数据字段的。也就是说 内部类其实是通过 这个thie$0这个成员变量访问外部类的实例成员的。那么是不是这样的,我们来测试一下 下面是完整代码
以上代码的结果证明了从反编译器中得到的结果。这个有点儿像是javascript中的闭包呵呵。
不过 我也产生了一个疑问,为什么内部类不能声明任何静态成员呢。这个确实是百思古德其解,如果可能问老师吧.
2/静态 的内部类型
静态的内部类型 编译之后 与 非静态的内部类 编译后 生成的文件一样,但是他们有本质的不同,就是体现在 静态内部类型编译后与普通的静态类一样,编译器没有做更多的干涉,没有添加 this$0之类的东西。 起调用方法也不需要 外部类的实例。直接使用 OutClas.InnerClass 就可以了。 也因此,静态内部类只能访问 外部类的 静态成员,不能访问外部类的任何实例成员。
3、生命在方法或者语句块的内部类,则更像是 方法中的局部变量,可以相见,除非 起所在的方法返回 其内部类的实例,否则,不管是在内部类的其它方法或代码块中是无法创建内部类的实例的。
作者:duanmengchao 发表于2012-3-10 17:16:50 原文链接
阅读:8 评论:0 查看评论
所谓内部类,就是在一个类的内部再声明一个类类型。
class OuterClass { private int outData =0; public OuterClass(){ System.out.println("创建一个外部类的实例"); } public void outInstanceMothed(){ System.out.println("外部类的实例方法"); } public static void outStaticMothed(){ System.out.println("内部类的静态方法"); } //声明内部类型 public class InnerClass { public InnerClass(){ System.out.println("创建一个内部类的实例"); } public void innerMothed(){ System.out.printf("内部类的实例方法可以访问外部类的任何可访问级别的成员变量%d",outData); } } }
这样一个包含内部类的JAVA源文件 编译之后 会得到两个class文件:
OuterClass.class 和 OuterClass$InnerClass.class
我反编译了这两个类文件,查看内容是 解决的一些疑惑的同事也带了了一些疑惑(如图所示)。可能是反编译器的问题,类名应该是OuterClass$InnerClass,其中的编码其实是汉字。
解决的疑惑是:1,在外部来的 外部,非静态的内部类的创建为什么一定要绑定外部类,也就是说,必须县创建外部类,然后通过外部类的实例才能创建内部类的实例。
从反编译后的代码 可以看到,内部多了一个 this$0 字段,它是外部类型 的,而且 构造方法中 多出了一个为 this$0赋值的语句,看到这里我们就应该能够推理出 内部类的不少规则了
1.非静态内部类必须 通过外部类的实例来创建,或者通过 内部类的一个实例方法 在外部类内部创建 并返回一个内部非静态类的实例。但是无论如何,必须在外部类的实例上基础上创建内部类。
public class InnerClassTest { public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass(); OuterClass.InnerClass inner2 = outer.getInnderClass(); } }
2、内部类可以访问 外部类的 成员变量。这一点也很容易理解了,内部类中的this$0关键则应该是和 this关键字一样的作用,用于方位实例的数据字段的。也就是说 内部类其实是通过 这个thie$0这个成员变量访问外部类的实例成员的。那么是不是这样的,我们来测试一下 下面是完整代码
import java.lang.*; import java.lang.reflect.*; public class InnerClassTest { public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass(); OuterClass.InnerClass inner2 = outer.getInnderClass(); try { Class classOfInner = inner2.getClass(); Field[] fields = classOfInner.getFields(); Field f1 = classOfInner.getDeclaredField("this$0"); System.out.println(f1.getName()); System.out.println(f1.toString()); 这里的输出 与反编译看到的代码一直 System.out.println(f1.getType()); f1.setAccessible(true); Object value = f1.get(inner2); OuterClass out = (OuterClass)value; System.out.println(outer == value); // } catch (Exception ex) { System.out.println("出错了"); System.out.println(ex.getMessage()); } } } class OuterClass { private int outData =0; public OuterClass(){ System.out.println("创建一个外部类的实例"); } public void outInstanceMothed(){ System.out.println("外部类的实例方法"); } public static void outStaticMothed(){ System.out.println("内部类的静态方法"); } public InnerClass getInnderClass() { return new InnerClass(); } //声明内部类型 public class InnerClass { private int innerData; public InnerClass(){ System.out.println("创建一个内部类的实例"); } public void innerMothed(){ //System.out.print(this$0); System.out.printf("内部类的实例方法可以访问外部类的任何可访问级别的成员变量%d",outData); } } public static class InnerStaticClass { public static void innerStaticMothed() { System.out.println("InnerStaticClass"); } } }
以上代码的结果证明了从反编译器中得到的结果。这个有点儿像是javascript中的闭包呵呵。
不过 我也产生了一个疑问,为什么内部类不能声明任何静态成员呢。这个确实是百思古德其解,如果可能问老师吧.
2/静态 的内部类型
静态的内部类型 编译之后 与 非静态的内部类 编译后 生成的文件一样,但是他们有本质的不同,就是体现在 静态内部类型编译后与普通的静态类一样,编译器没有做更多的干涉,没有添加 this$0之类的东西。 起调用方法也不需要 外部类的实例。直接使用 OutClas.InnerClass 就可以了。 也因此,静态内部类只能访问 外部类的 静态成员,不能访问外部类的任何实例成员。
3、生命在方法或者语句块的内部类,则更像是 方法中的局部变量,可以相见,除非 起所在的方法返回 其内部类的实例,否则,不管是在内部类的其它方法或代码块中是无法创建内部类的实例的。
作者:duanmengchao 发表于2012-3-10 17:16:50 原文链接
阅读:8 评论:0 查看评论
相关文章推荐
- Java核心技术(第8版)学习笔记_接口与内部类
- Java 学习笔记 (3) -抽象类 abstract 接口 interface 内部类 inner class 继承 extends 实现 implements 包 package
- 黑马程序员 Java基础学习笔记10 内部类
- Java学习笔记五(内部类 )
- 2)Java学习笔记:匿名内部类
- Java学习笔记57. 再谈接口,兼论匿名内部类
- C\C++ 程序员从零开始学习Android - 个人学习笔记(八) - java基础 - 继承、抽象类、接口、内部类(待续)
- 内部类--毕向东Java基础教程学习笔记
- 我的java学习笔记(17)关于内部类(part 2)
- java_内部类学习笔记(二)
- thinkinginjava学习笔记09_内部类
- java学习笔记 内部类
- C\C++ 程序员从零开始学习Android - 个人学习笔记(八) - java基础 - 继承、抽象类、接口、内部类(待续)
- java 从零开始,学习笔记之基础入门<内部类>(十四)
- java学习笔记9--内部类总结
- java学习笔记day06---匿名内部类
- Java学习笔记—内部类(转载)
- 学习笔记 Java_ch04_内部类内部接口 2014.7.27
- 【Java学习笔记之二十六】深入理解Java匿名内部类
- Java学习笔记29 内部类(Inner Cla…