package hr.test;
//代码3:静态内部类对外部变量的引用
public class Outer{
private static int i=0;
//创建静态内部类对象
public Inner in=new Inner();
//静态
private static class Inner{
public void print(){
System.out.println(i); //如果i不是静态变量,这里将无法通过编译。
}
}
}
静态内部类和私有内部类最大的区别在于,静态内部类中无法引用到其外围类的非静态成员。这是为什么?我们还是来看看静态内部类Outer$Inner中发生了什么吧?
反编译代码
//反编译3
class Outer$Inner
{
private Outer$Inner();
Outer$Inner(hr.test.Outer$Inner);
}
与上面私有内部类反编译1比较发现,少了一个指向外围类对象的引用final Outer this$0; 也就是说静态内部类无法得到其外围类对象的引用,那么自然也就无法访问外围类的非静态成员了。因此,静态内部类只能访问其外围类的静态成员,除此之外与非静态内部类没有任何区别。
3、局部内部类 —— 在方法中定义的内部类
方法内部类也有两个特点
(1) 方法中的内部类没有访问修饰符, 即方法内部类对包围它的方法之外的任何东西都不可见。
(2) 方法内部类只能够访问该方法中的局部变量,所以也叫局部内部类。而且这些局部变量一定要是final修饰的常量。
class Outter{
public void outMethod(){
final int beep=0;
class Inner{
//使用beep
}
Inner in=new Inner();
}
}
这又是为什么呢?
(1) 我们首先对Outter类进行反射发现,Outter中再也没有返回私有域的隐藏方法了。
(2) 对Inner类的反射发现,Inner类内部多了一个对beep变量的备份隐藏域:final int val$i;
我们可以这样解释Inner类中的这个备份常量域,首先当JVM运行到需要创建Inner对象之后,Outter类已经全部运行完毕,这是垃圾回收机制很有可能释放掉局部变量beep。那么Inner类到哪去找beep变量呢?
编译器又出来帮我们解决了这个问题,他在Inner类中创建了一个beep的备份 ,也就是说即使Ouuter中的beep被回收了,Inner中还有一个备份存在,自然就不怕找不到了。
但是问题又来了。如果Outter中的beep不停的在变化那。那岂不是也要让备份的beep变量无时无刻的变化。为了保持局部变量与局部内部类中备份域保持一致。 编译器不得不规定死这些局部域必须是常量,一旦赋值不能再发生变化了。
所以为什么局部内部类应用外部方法的域必须是常量域的原因所在了。
内部类的特点总结
(1) 在方法间定义的非静态内部类:
● 外围类和内部类可互相访问自己的私有成员。
● 内部类中不能定义静态成员变量。
(2) 在方法间定义的静态内部类:
● 只能访问外部类的静态成员。
(3) 在方法中定义的局部内部类:
● 该内部类没有任何的访问控制权限
● 外围类看不见方法中的局部内部类的,但是局部内部类可以访问外围类的任何成员。
● 方法体中可以访问局部内部类,但是访问语句必须在定义局部内部类之后。
● 局部内部类只能访问方法体中的常量,即用final修饰的成员。
(4) 在方法中定义的匿名内部类:
● 没有构造器,取而代之的是将构造器参数传递给超类构造器。
ReflectUtil.java 附件下载:
------------------------------------------分割线------------------------------------------
具体下载目录在 /2015年资料/6月/14日/关于Java内部类的“内部”/
------------------------------------------分割线------------------------------------------