目的
为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合,我并不是很清楚,留下一些值得思考的问题作为记录,说不定以后能自己来填。于是就会有这篇文章啦。
常规使用方法我也不想介绍,网上一大把,我就说说比较容易错的,值得注意的地方。
注意
这篇文章只是分享一下我对内部类的一些研究与困惑吧,说不定对大家有帮助,说不定能引导大家一起思考学习。Java语法知识其实是很复杂很容易错的,特别是在细节方面。所以我的观点可能会有各种错误。
另外我的JDK版本是1.7。JDK1.8的版本貌似对内部类的规则有一些修改,所以请大家注意。
非静态非匿名内部类
不能拥有static成员
网上大部分文章的说法大致是这样的,就是告诉你这种内部类不能拥有static的方法,属性。其实这句话有那么点小问题。非静态内部类也可以拥有static的属性的(static区块不行),但是要求这个static属性必须是常量,这个地方经过我的研究,我觉得和 “调用类的static属性,但却不会初始化这个类的static区块和其他static变量” 有点相似。什么意思?就是说
class Outter{
class Inner{
final static int a = 9;
}
}
这样是没有编译错误的。要求静态变量a必须是final类型的,且是基本类型,且是字面值
class Outter{
class Inner{
final static int a = get();
} static int get(){
return 1;
}
}
这样就会报错,因为a不是字面值。
这里我想请大家看一下我的另外一篇学习记录,这种变量是不会触发类初始化的。
地址:http://www.cnblogs.com/abcwt112/p/4567332.html 分析标题下面的第二小点。
当然,这种字面值貌似没什么卵用啊。。。。所以说这种内部类不能有static成员大致上好像也算对吧。。
为什么不能拥有static成员?
我觉得道理是这样的(个人理解)。非静态的内部类是和普通成员一样的,是隶属于外部类对象的,创建这种内部类对象需要先创建外部类对象。也就是说这种内部类是不能单独于外部类对象存在的。这个道理大家都明白,一个成员变量怎么能脱离于类的对象独立存在呢。那假设这种内部类可以拥有static的属性,比如static int a = 1;那这个a数据存在哪里呢?根据前面的分析,应该是存在于分配给外部类对象拥有的内存中的,那么等外部类对象呗销毁以后,这个a分配的内存也会被销毁。这样的话修改这个a毫无意义,因为每次都是重新分配内存,每次值都是1。所以这个static没什么用,并不是全局的。
这个问题我是这么理解的。我觉得等我看完JVM虚拟机(我觉得有可能final static int与static int变量值存的地方可能不一样)或者学习汇编(可以观察数据是怎么存储的)以后再看它可能会有更深的理解。
静态内部类
只能调用外部类的静态方法与属性
这点蛮好理解,就像静态方法main里不能调用非静态的属性,方法一样。但是这并不代表静态内部类就不能定义 非静态的方法和属性。它不能调用外部类的非静态的成员,但是却可以在自己内部定义。毕竟它是个类。。。。
public class StaticTest {
static int a = 9; private static class Inner{
public static void main(String[] args) {
System.out.println(StaticTest.a);
} public void doSomething(){ }
}
public static class Inner2{
}
}
这里代码就没有什么问题,能编译通过(doSomething方法)。
用途(废话)
静态内部类是没有指向外部类的引用的,所以说它和外部类并没有什么关系,因此,即使没有外部类的对象,也可以直接创建静态内部类的对象。但是我觉得如果是这样使用的话,那完全没必要把类弄成静态内部的,直接创建外部类一般的类就OK了。所以说静态内部类肯定有它自己独特的作用。既然是个内部类,我觉得应该会声明成private,不然还不如创建一个外部类呢。。。。那private static的class有啥用处呢?我也不清楚。。。现在我唯一觉得有用的地方就是可以把测试代码main方法写在里面。因为是private的类,外接不能调用它,也就不能调用写的main函数了。。但是如果只是测试的话可以使用junit test呀。。。不可能为了测试就专门搞这么一个语法。。。这点值得日后研究,等我代码看得多了,说不定会有新体会。
我看Apache Shiro框架中的Ini类就有个静态内部类Section(被声明为public类型),这个Section类独立存在毫无意义,外部只需要用到Ini类就行了。但是又不能没有,因为这个类地位其实和外部类Ini差不多,Ini是整个配置文件的抽象,Section是整个配置文件中每一小节的抽象。如果没有这个类,可能Ini中可能需要定义大量的static方法和大量的map来做关联,这样可能会很麻烦,所以shiro用到了这个静态内部类。具体内容可以查看我的另外一篇文章,介绍了Ini类:http://www.cnblogs.com/abcwt112/p/4641500.html