1、内部类定义

  内部类在维基百科的定义为:  面向对象编程中,内部类(又叫做嵌套类)是在另一个类或者接口中进行声明的类。内部类不同于子类(subclass)。(译者注:wiki的注解有误,内部类和嵌套类并不完全等同,详见下文。)

  在Java中,上面的定义可以如下示例:

 public final class Clazz {
private final class InnerClazz implements Runnable {
public InnerClazz() {
}
@Override
public void run() {
System.out.println("Hello world");
}
} public Clazz() {
}
public Runnable getRunnable(){
return new InnerClazz();
}
}

  上面这个示例除了声明了一个内部类之外,没做其他任何事情。我举这个例子是想强调嵌套类和内部类的不同,因为不是所有的程序员都理解这一点。

2、内部类(Inner class

  上面的示例代码中声明了一个内部类“InnerClazz”。每次调用getRunnable方法的时候InnerClazz类的实例就会被创建出来。如果你在FindBugs中调试这段代码,你会看到下面这条警告信息: SIC:应该是个静态内部类(SIC_INNER_SHOULD_BE_STATIC) 。 这个类是一个由其外部对象创建的内部类,但是它没有使用内置的指向外部对象的引用。这个引用可以使得内部类实例更大,并且可以使得外部对象的生存期尽可能长。如果可能,这个类应该被定义成静态的。

  这条警告信息很明确:内部类会保留一个指向其父类的引用,因此只要InnerClazz类被引用了,其父类就不能被JVM的垃圾回收机制自动垃圾回收(内部类和其父类的引用关系是很稳固的,你可以通过内存管理这篇文章了解更多)。如果你想使用这个引用,下面这种嵌套类是非常有用的:

 1 public final class Clazz {
2 private final class InnerClazz implements Runnable {
3 public InnerClazz() {
4 }
5 @Override
6 public void run() {
7 // print the value of a member of its "parent" class
8 // it's possible because the inner class has an implicit reference
9 // on the Clazz instance
10 System.out.println(_currentNumber);
11 }
12 }
13 private int _currentNumber = 0;
14 public Clazz() {
15 }
16 public Runnable getRunnable() {
17 _currentNumber++;
18 return new InnerClazz();
19 }
20 }

3、非内部类的嵌套类(Nested but not inner class)

  如果你并不需要保留Clazz实例和InnerClazz实例之间的非常稳固的引用关系,那么就将InnerClazz声明为一个静态成员类(下面的例子中的NestedNotInnerClazz类)。

 1 public final class Clazz {
2 // static keyword is added
3 static private final class NestedNotInnerClazz implements Runnable {
4 public NestedNotInnerClazz() {
5 }
6 @Override
7 public void run() {
8 System.out.println("Hello world");
9 }
10 }
11
12 public Clazz() {
13 }
14 public Runnable getRunnable(){
15 return new NestedNotInnerClazz();
16 }
17 }

最新文章

  1. PowerDesigner逆向工程导入MYSQL数据库总结
  2. string类实现(C++)
  3. 闭包和this
  4. Android课程---Android Studio简单设置
  5. Linux生产服务器Shell脚本分享
  6. JS来操作hover
  7. VMWare虚拟机下RedHat 9.0linux的网络设置
  8. Verilog HDL中阻塞语句和非阻塞语句的区别
  9. BZOJ 1003 物流运输 (动态规划 SPFA 最短路)
  10. EF中的贪婪加载和延迟加载(懒加载)
  11. java 字符串反转
  12. AutoTile 自动拼接(六 大结局) 学习与实践
  13. MySQL——数据类型
  14. python面向对象之封装
  15. Python dict和set的实现原理
  16. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)
  17. Timeout occurred while waiting for latch: class 'ACCESS_METHODS_DATASET_PARENT'
  18. mybatis源码分析(四)---------------代理对象的生成
  19. python3 列表的赋值和深浅拷贝
  20. 原创:vsphere概念深入系列一:关于vsphere虚拟交换机的端口的数量限制。

热门文章

  1. HDU 4568 Hunter(最短路径+DP)(2013 ACM-ICPC长沙赛区全国邀请赛)
  2. Tengine/Nginx 安装
  3. udf.dll 源码
  4. QWidget一生,从创建到销毁事件流
  5. node中的path.resolve
  6. 完整和增量备份MySQL脚本
  7. 使用gdb查看栈帧的情况, 没有ebp
  8. sql 插入列放第一列
  9. [洛谷P4171][JSOI2010]满汉全席
  10. lighttpd - 配置