导读
本文适合Java入门,不太适合Java中高级软件工程师。本文以《Java程序设计基础篇》第10版为蓝本,采用不断提出问题,然后解答问题的方式来讲述。本篇文章只是这个系列中的一篇,如果你喜欢这种讲解方式,或者觉得从中能学到知识,可以关注我,以便查阅本系列其他文章。
让我们开始愉快地学习Java语言吧!
1什么是内部类
定义在另一个类中的类就是内部类。
为什么要使用内部类?
因为它具有一些独特的性质,所以用起来方便,并且对数据进一步封装,私密性更好,它具体有哪些优点呢,看看下面的阐述吧。
2内部类语法
基本概念
表示外围类的引用:OwterClass.this
使用内部类构造器构造对象:outerObject.new InnerClass(construction parameters)或new InnerClass(construction parameters)。
在外围类之外引用内部类:OuterClass.InnerClass
非静态内部类不能有static方法。
内部类中声明的所有静态域都必须是final,这是为啥呢?
因为每个外部类对象都有一个内部类实例,如果静态域不是final,那么这个静态域就不唯一,而我们希望所有外部类对象都持有一个共同的静态域,即保持静态域的唯一性。
Java API中的用例
让我们看看Java API中的一个例子:ArrayList。
下面是ArrayList定义的一个内部类Itr,这样只能在ArrayList内访问。并且它还提供了构造器,未指明访问性修饰符,那么默认是public
让我们再看下Java API中的另一个例子:HashMap。
在HashMap中定义了一个内部类KeySet,并将其声明为final,表明他不能被继承。
在第916和923行,引用了外围类:HashMap.this,其中在916行调用外围类方法HashMap.this.clear()。
那么是怎么使用内部类KeySet的呢?
看下面的代码,第908行,实例化一个新的KeySet将其赋给变量ks,使用的是new InnerClass(construction parameters)这种形式。
3局部内部类
定义在方法内的内部类,我们称之为局部内部类。
局部类不能用public或private修饰符进行声明。它的作用域被限定在声明这个局部类的块中。
局部类有一个优势, 即对外部世界可以完全地隐藏起来。
然而似乎将内部类用private修饰也可以保证隐藏起来,这有啥区别呢?
局部类的隐藏性是天生的,且从代码的组织行式上来讲,就将自己与其他类隔离开,明确其归属性。
4匿名内部类
基本概念
创建局部内部类时可以省略类名,这样的类被称为匿名内部类。
语法格式为:
new SuperType ( construction parameters )
{
inner class methods and data
}
匿名类不能有构造器。
Java API中的用例
让我们看下ArrayList这个类中如何使用局部内部类的。
ArrayList里边定义了SubList这个内部类,然后在SubList中定义了匿名内部类ListIterator。listIterator这个方法是SubList内定义的,其返回值就是ListIterator。
总结一下,这个用法,在类ArrayList中定义了内部类SubList,在内部类SubList中定义了匿名内部类,似乎很繁琐。但如果这些内部类仅供ArrayList自己使用,其他类根本不会使用的话,那么这种用法就相当取,体现了面向对象设计原则:封装。
5静态内部类
基本概念
使用static修饰符修饰的内部类称之为静态内部类,也有人称静态内部类为嵌套类。
如果声明内部类时不使用任何修饰符,那么默认是public static。
静态内部类可以有静态域和静态方法。
声明在接口中的内部类,默认是public static。
在内部类不需要访问外部类对象的时候,应该使用静态内部类。
Java API中的用例
Java API中使用了大量的静态内部类,尤其是数据结构这一块。
大家还记得吗,static可以修饰内部类,非内部类不能被它修饰。
前面讲到非静态内部类不能有static方法,那么让我们看看静态内部类。还是以HashMap为例,内部类TreeNode有一个静态方法moveRootToFront。
AbstractMap中定义了SimpleEntry类,且有一个静态域serialVersionUID,使用final修饰。