局部内部类为什么只能访问final局部变量?

最近读《Effective Java》,其中描述了嵌套类的几种类别:

1.静态成员类。他只是位于某个内里而已,与外部类没有一毛钱关系。

2.非静态成员类。相当于外部类的成员,使用依赖于外部类的实例。

3.匿名类。如:Comparator,Runnable,Thread等。

4.局部类。位于方法内部,相当于方法的局部变量。

比较难理解的是局部类:

1.不能有public、private、protected修饰,好理解,局部变量也是没有这些修饰符的。

2.不能含有静态成员。内部类的实例对象是外部类的对象的一个成员,若没有外部对象,内部对象也是不存在的,何谈静态成员。

3.局部内部类只能访问final局部变量。你如果访问了非final变量,编译器会提示你将变量声明为final。局部变量的生命周期与局部内部类的对象的生命周期的不一致。局部变量当所处的函数执行结束后就已经死亡了,不存在了,但是局部内部类对象还可能一直存在(只要有人还引用该对象),这是就会出现了一个悲剧的结果,局部内部类对象访问一个已不存在的局部变量。那么,编译器是怎么实现的呢?编译器会将外部的final变量在编译阶段就作为内部类的成员变量写入内部类中,如下例子:

原始类:

public class S2 {

    public void outerDoSomething() {
        final String localObj = "hello";
        class InnerClass {
            public void innerDoSomething() {
                String a = localObj;
                System.out.println(a);
            }
        };

        InnerClass innerObj = new InnerClass();
        innerObj.innerDoSomething();
    }

    public static void main(String[] args) {
        S2 s2 = new S2();
        s2.outerDoSomething();
    }
}

编译后的class文件:

public class S2 {
    public S2() {
    }

    public void outerDoSomething() {
        String localObj = "hello";
        class InnerClass {
            InnerClass() {
            }

            public void innerDoSomething() {
                String a = "hello";
                System.out.println(a);
            }
        }

        InnerClass innerObj = new InnerClass();
        innerObj.innerDoSomething();
    }

    public static void main(String[] args) {
        S2 s2 = new S2();
        s2.outerDoSomething();
    }
}

所以访问外部的final变量,在编译器就放入内部类了,与外部无关。所以访问安全。

4.静态方法内的方法内部类。

静态方法是没有this引用的,因此在静态方法内的内部类遭受同样的待遇,即:只能访问外部类的静态成员,但可以不是final的,static修饰后就不受实例的束缚,取得静态成员变量了。

你可能感兴趣的:(Java开发,内部类)