贪婪的君子程序员Java学习笔记

Java内部类总结

2017-04-03  本文已影响59人  贪婪的君子

关于Java中的内部类(Inner Classes),咱们可得好好说道说道。

概述


面向对象程序设计(OOP)中,可以在一个类的内部定义一个新类,即为我们平时口中说的嵌套类。Java是一种面向对象程序设计语言,自然也包含了这样的特性。

在Java中,嵌套类又分为以下两种:

嵌套类可以声明在外部类中的任何位置,一般情况下Java中类的修饰符必须是public或者是默认的package private,但是无论是静态还是非静态内部类,其修饰符可以为 public,private,protected,package private 中的任意一种,这也体现出了内部类与普通外部类的不同。

class OuterClass {  
    //...  
    static class StaticNestedClass {  
        //...  
    }  
    class InnerClass {  
        //...  
    }  
}   

静态嵌套类(静态内部类)


静态嵌套类(static),与非静态嵌套类(non-static)相比,缺少了对外部类的引用,由修饰符(static)可以看出,静态嵌套类不属于外部类,缺少了对外部类的引用(这就实现了将一个类隐藏在另一个类的内部,却消除了对外部类的引用),也就有了如下性质:

OuterClass.StaticNestedClass
OuterClass.StaticNestedClass nestedObject =
     new OuterClass.StaticNestedClass();
StaticNestedClass.StaticMember

非静态嵌套类(内部类)

局部内部类


public class OuterClass {  
    //...
    public void method() {  
    class LocalClass1 { /*...*/ }//定义在方法体中  
    if (true) {  
        class LocalClass2 { /*...*/ }//定义在if嵌套中  
    }  
    for(;;;) {  
        class LocalClass3 { /*...*/ }//定义在循环体中  
    }  
}  

局部内部类(Local Classes),Java官方文档中将其与给出的解释是:
  "You can define a local class inside any block."

即,局部内部类可以定义在任何的语句块中,比如说方法体(method),循环体(loop),甚至是分支执行的if子句中。
  但由于局部内部类是定义在块( Block)内的类,不是外部类的一部分,并且只在当前的块内有效(可以访问当前块内的final常量,以及外部类的所有成员),所以其不能有任何的访问控制符。

说到这里,可能会有些疑问,不是外部类的一部分,怎么还能访问外部类的内容呢?
  虽然局部内部类不是外部类的一部分,但是他还是外部类的内容,想想Java中的方法,也能直接访问外部类的所有成员就知道了。

为什么只能访问块内的final变量(在SE 8中可以访问effectively final变量,一种无final修饰的,但在初始化之后值不再更改的类final变量)?
  解释起来很麻烦,简言之就是作用域的问题,因为局部变量的生命周期与局部内部类的生命周期不一致导致编译技术上无法实现或是实现代价极高。而之所以能够访问final变量,则是因为Java采用了一种copy local variable的方式实现,篇幅原因,这里不做过多的解释,如有兴趣,可以参考http://blog.csdn.net/salahg/article/details/7529091

匿名内部类

匿名内部类(Anonymous Classes),官方文档中简单说明:
  "an inner class within the body of a method without naming the class. "

并且表示匿名内部类可以使代码更加简洁(现在有了lambda表达式之后,代码可以更加简洁)。

匿名内部类是扩展自超类,或者是实现了某一个接口。
  这一性质决定了必须先声明一个类或者是接口,然后以下方式创建:

new SuperClass() { ... }  

或者是

new InterfaceName() { ... }
public class OuterClass {  
    class InnerClass {  
        private int in = 3;  
        public InnerClass(int i) { ... }  
        public int getIn() {  return in;  }  
    }
    public InnerClass newInstance(int x) {  
        return new InnerClass(int x) {//这里调用超类的构造方法  
        public int getIn() {//这里使用super关键字调用超类的getIn()方法  
            return super.getIn() * 10;
        }  
    }  
}  

内部类与外部类之间的关系


  1. Java生成的class文件中,外部类文件名为"OuterClassName.class",内部类则为"OuterClassName$InnerClassName.class",匿名内部类稍有不同:"OuterClassName$InnerClassName#.class",其中符号"#"为匿名类的序号。
  2. 外部类成员对内部类透明,上文已经提及,这是由于非静态内部类(non-static nested class)隐式的含有一个指向外部类的引用。
  3. .this与.new可以的到对外部类的一个引用。
  4. 内部类可以通过外部类的方法生成,并且可以向上转型生成超类实现的接口对象
  5. 除了上述所说,内部类还具有普通类的被继承的性质(但是比较麻烦),甚至可以像方法一样被重载(虽然感觉并没有用处)。
public class OuterClass {  
    private int i = 3;  
    public class InnerClass {
        private int i = 1;   
        public void print() {  
            System.out.println("i = " + i);  
            System.out.println("this.i = " + this.i);  
            System.out.println("OuterClass.this.i = " + OuterClass.this.i);  
        }   
    }  
    public InnerClass newInstance() {  
        return new InnerClass() {};  
    }  

    public static void main(String[] args) {   
        new OuterClass().newInstance().print();  
    }  
}  

总结


Java将嵌套类划分成静态与非静态嵌套类两种类型。
  嵌套类的存在提高了类的封装性(encapsulation),以及代码的可读性(readable)。

之所以需要使用内部类,原因如下:

上一篇 下一篇

猜你喜欢

热点阅读