Java内部类总结
Java的内部类内容挺多,不是很好理解,但说白了也就是一个类中还包含着另外一个类。
内部类的基本结构
在讲解之前让我们先来看一段代码。
- class Out { //外部类
- private int age = 12;
- class In { //内部类
- public void print() {
- System.out.println(age);
- }
- }
- }
- public class Demo {
- public static void main(String[] args) {
- Out.In in = new Out().new In();
- in.print();
- //或者采用下种方式访问
- /*
- Out out = new Out();
- Out.In in = out.new In();
- in.print();
- */
- }
- }
- /* 运行结果:12 */
从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点。
程序编译过后会产生两个.class文件,分别是Out.class和Out$In.class,其中$代表了上面程序中Out.In。
Out.In in = new Out().new In() 可以用来生成内部类的对象,这种方法存在两个小知识点需要注意。
- 开头的Out是为了标明需要生成的内部类对象是在哪个外部类当中
- 必须先有外部类的对象才能生成内部类的对象。因为内部类是可以访问外部类中的成员变量,如果外部类没有被实例化,那么就会出现空指针异常。(不过编译器也不允许这种事情的发生)
PS:C#与JAVA不一样,C#的内部类是不可以访问外部类的非静态内容。C#内部类相当于JAVA的静态内部类
内部类中变量的访问形式
访问内部类本身的成员变量直接this.属性名就可以了,而访问外部类的成员变量则需要使用Out.this.属性名
- class Out {
- private int age = 12;
- class In {
- private int age = 13;
- public void print() {
- int age = 14;
- System.out.println("局部变量:" + age);
- System.out.println("内部类变量:" + this.age);
- System.out.println("外部类变量:" + Out.this.age);
- }
- }
- }
- public class Demo {
- public static void main(String[] args) {
- Out.In in = new Out().new In();
- in.print();
- }
- }
- /*
- 运行结果:
- 局部变量:14
- 内部类变量:13
- 外部类变量:12
- */
静态内部类
- class Out {
- private static int age = 12;
- static class In {
- public void print() {
- System.out.println(age);
- }
- }
- }
- public class Demo {
- public static void main(String[] args) {
- Out.In in = new Out.In();
- in.print();
- }
- }
- /* 运行结果:12 */
可以看到,使用static可以将内部类静态化,静态化之后的内部类就只能访问外部类的静态成员变量了,具有了局限性。
其次,因为内部类被静态化了,所以Out.In可以当做一个整体看。简而言之就是可以直接new 出内部类的对象了。
私有内部类
如果希望一个内部类只能在外部类中操作,那么可以使用private来修饰内部类。
- class Out {
- private int age = 12;
- private class In {
- public void print() {
- System.out.println(age);
- }
- }
- public void outPrint() {
- new In().print();
- }
- }
- public class Demo {
- public static void main(String[] args) {
- //此方法无效
- /*
- Out.In in = new Out().new In();
- in.print();
- */
- Out out = new Out();
- out.outPrint();
- }
- }
- /* 运行结果:12 */
上面的代码中,我们只能在Out类里面对In类生成的对象进行操作,而无法再使用Out.In in = new Out().new In() 来生成内部类的对象了。
也就是说,此时的内部类只能被外部类所控制。