内部类都包含一个对外部类的引用,参见代码0:
代码0:
public class SerializeTest {
//成员内部类
class MemberInner{
public MemberInner(){
}
}
//局部内部类
public void show(){
class A{
}
}
//匿名内部类
private SerializeTest s=new SerializeTest(){{
System.out.println(1);
}};
public static void main(String[] args) {
}
}
Decompile:
A:
//成员内部类
class SerializeTest$MemberInner {
public SerializeTest$MemberInner(SerializeTest this$0) {
this.this$0 = this$0;
}
}
B.
//局部内部类
class SerializeTest$1A {
SerializeTest$1A(SerializeTest this$0) {
this.this$0 = this$0;
}
}
C.
//匿名内部类
class SerializeTest$1 extends SerializeTest {
SerializeTest$1(SerializeTest this$0) {
this.this$0 = this$0;
System.out.println(1);
}
}
所以其可以访问外部类的变量,
内部类访问外部变量:
在访问成员变量时,三者均没有限制,以下代码可以看出,内部类可以对成员变量进行读写,但是对于局部内部类和匿名内部类在访问局部变量时该变量只能是final类型的,原因?
public class SerializeTest {
int a = 0; //成员变量
//成员内部类
class MemberInner {
public MemberInner() {
System.out.println(++a);
}
}
//局部内部类
public void show() {
class A {
public void s() {
System.out.println(a++);
}
}
}
//匿名内部类
private SerializeTest s = new SerializeTest() {{
System.out.println(a++);
}};
public static void main(String[] args) {
}
}
代码1:
public class SerializeTest {
private int a=0;
class MemberInner{
}
public static void main(String[] args) {
new SerializeTest().a=100;
}
}
Decomplile:
class SerializeTest$MemberInner {
SerializeTest$MemberInner(SerializeTest this$0) {
this.this$0 = this$0;
}
}
代码2:
局部OR匿名内部类访问局部变量时必须是final的而且:
如果该变量在编译期间就可以确定就会直接复制一份放到所需要的地方反之将其作为参数传入;
public class SerializeTest {
public void doit(){
final int a=0;
class MemberInner{
public MemberInner(){
}
public void show(){
System.out.println(a);
}
}
}
public static void main(String[] args) {
new SerializeTest().doit();
}
}
Decomplie
class SerializeTest$1MemberInner {
public SerializeTest$1MemberInner(SerializeTest this$0) {
this.this$0 = this$0;
}
public void show() {
System.out.println(0);
}
}
代码3:
对比代码2发现,由于局部内部类中的a无法在编译期确定,因此在该内部类中会将此变量的引用作为参数传到内部类中
public class SerializeTest {
public void doit(int b){
final int a=b;
class MemberInner{
public MemberInner(){
}
public void show(){
System.out.println(a);
}
}
}
public static void main(String[] args) {
new SerializeTest().doit(100);
}
}
Decomplie:
class SerializeTest$1MemberInner {
public SerializeTest$1MemberInner(SerializeTest this$0, int var2) {
this.this$0 = this$0;
this.val$a = var2;
}
public void show() {
System.out.println(this.val$a);
}
}
特殊的:静态内部类
可以发现,静态内部类不包含对外部类的引用,而且在静态方法中建的类也是静态类;
从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。(http://baike.baidu.com/view/7942850.htm)静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。(http://www.cnblogs.com/dolphin0520/p/3811445.html)
代码1:
public class SerializeTest {
static class A{
}
public static void main(String[] args) {
}
}
Decompile:
class SerializeTest$A {
SerializeTest$A() {
}
}
代码2:在静态方法中建的类也是静态类
public class SerializeTest {
public static void show(){
class A{
}
}
public static void main(String[] args) {
}
}
Decompile:
class SerializeTest$1A {
SerializeTest$1A() {
}
}
代码3:
与其他内部类不同的是,静态内部类在访问成员变量时必须是static的
public class SerializeTest {
static int s=0;
public static void show(int b){
final int a=b; //必须是final
class A{
public void show(){
System.out.println(a);
s++; //必须是static
}
}
}
public static void main(String[] args) {
}
}
Decompile:
class SerializeTest$1A {
SerializeTest$1A(int var1) {
this.val$a = var1;
}
public void show() {
System.out.println(this.val$a);
++SerializeTest.s;
}
}
内部类的嵌套: