论坛首页 Java企业应用论坛

浅谈非静态内部类不能有静态成员

浏览 16644 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (4) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-05-05   最后修改:2010-05-10

1 非静态内部类为什么不能有静态成员,我自己总结了下,

如下代码

public class OuterClass{
     class InnerClass{
         private static int i;
     }
}

 对于java类加载顺序我们知道,首先加载类,执行static变量初始化,接下来执行对象的创建,如果我们要执行代码中的变量i初始化,

那么必须先执行加载OuterClass,再加载Innerclass,最后初始化静态变量i,问题就出在加载Innerclass上面,我们可以把InnerClass看成OuterClass的非静态成员,它的初始化必须在外部类对象创建后以后进行,要加载InnerClass必须在实例化OuterClass之后完成 ,java虚拟机要求所有的静态变量必须在对象创建之前完成,这样便产生了矛盾。

Verion 0.11:

对于红色标记的部分,当时理解上有误,我们知道InnerClass可以有静态常量(static final),那么InnerClass类加载一定在OuterClass对象创建之前完成,但这还不足以说明为什么非静态内部类里面不能有静态的变量(基本类型 或对象因用),这里面涉及到Java语言的定义以及JVM的类加载的原理方面的知识,我将进一步研究这个问题,技术是严谨的,也希望各位读者提出宝贵的意见。

 

下面是我验证的代码解释InnerClass加载是在OuterClass对象创建之前完成的:

public class OuterClass {
	
	static int k = printI();
	
	static int printI(){
		System.out.println("Inner Class is loading before creating OuterClass instance");
		return InnerClass.i ;
	}
	
	OuterClass(){
		System.out.println("OuterClass constructor");
	}
	
	class InnerClass{
		private static final int i = 1;
		
	}
	public static void main(String[] args) {
		OuterClass o;
	}
}
//* out:
// Inner Class is loading before creating OuterClass instance
 

2 静态内部类可以有静态成员:

我们可以把静态内部类作为外部类OuterClass的一个静态成员,在执行类加载过程中,静态内部类在加载OuterClass后会进行初始化,同样的原理,静态内部类的静态成员也将被初始化,进行内存的分配,注意到,这时无论是内部类还是外部类,对象都没有实例化,这也说明了非静态内部类为什么不能有静态成员的原因。

public class OuterClass{
     static class InnerClass{
         private static int i;
     }
}
   发表时间:2010-05-06  
对于非静态内部类不能有静态成员,核心问题是在内部类的加载原理,个人认为执行内部类加载,是在外部类对象创建之后。
0 请登录后投票
   发表时间:2010-05-06  
    public class OuterClass{  
         class InnerClass{  
             private static final int i = 1;  
         }  
    }  

这样写。
0 请登录后投票
   发表时间:2010-05-06  
Agrael 写道
    public class OuterClass{  
         class InnerClass{  
             private static final int i = 1;  
         }  
    }  

这样写。

首先static 成员不直接赋值同样也会完成自动初始化,楼上的写法没有本质的区别。
0 请登录后投票
   发表时间:2010-05-06  
Arron.li 写道
Agrael 写道
    public class OuterClass{  
         class InnerClass{  
             private static final int i = 1;  
         }  
    }  

这样写。

首先static 成员不直接赋值同样也会完成自动初始化,楼上的写法没有本质的区别。


呵呵,这个区别大了,你去试下吧。
0 请登录后投票
   发表时间:2010-05-06  
Agrael 写道
Arron.li 写道
Agrael 写道
    public class OuterClass{  
         class InnerClass{  
             private static final int i = 1;  
         }  
    }  

这样写。

首先static 成员不直接赋值同样也会完成自动初始化,楼上的写法没有本质的区别。


呵呵,这个区别大了,你去试下吧。

才看清楚,原来多了个final,回去好好研究下,谢谢你
0 请登录后投票
   发表时间:2010-05-07  
为什么ls的这种写法可以呢?
求教了
0 请登录后投票
   发表时间:2010-05-07  
加final变量为常量了,这要区别 静态常量 与 静态变量 吧
0 请登录后投票
   发表时间:2010-05-07  
关注这个问题.非静态内部类的final静态成员是何时初始化的?
singleton有一种写法就是这样的,这种写法到底是否比饿汉式好一直没搞清楚.
0 请登录后投票
   发表时间:2010-05-07  
查了下sun公司java language specification,提到内部类的规范:
Inner classes may not declare static initializers (§8.7)  or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).

对于非静态内部,可以有编译常量,不过至于为什么,还有待于进一步研究。
参考网址:http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3
1 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics