内部类如何访问外部类中的元素?

时间:2016-12-24 16:02:43

标签: java inheritance anonymous anonymous-class

我应该提一下,在我考虑过这个问题之后,我已经找到了具体的编程问题,所以这不是一个编程问题,更多是关于问题背后原因的问题。

在使用访问修饰符时,我一直在测试Java的局限性,并开始将这些测试应用于基本的继承概念。

以下是代码:

package test.Inheritance;

public class SuperClass {

    private static int x = 0;
    protected static int y = 1;

    public static void main(String[] args){
        SupplementalClass2 child = new SupplementalClass2();
        NestedClass local = new NestedClass();
        InnerClass test;

        child.setObject(child.new InnerClass(){
            @Override public void display(){System.out.println("Hey!");}
        });
        test = child.getObject();

        System.out.println(test.equals(child.receiveObject));
        SuperClass.NestedClass.display();
        SuperClass.NestedClass2.display();
        test.display();
        child.display();
        local.message();
    }

    public static class NestedClass {
        public static void display()
        {
            System.out.println("x before first static context change: " + x);
            x = 25;
            System.out.println("x after first static context change: " + x);
        }
        public void message()
        {
            System.out.print("Nested Class Field Access Test: " + "before(" + y + ") | ");
            y = 20;
            System.out.println("after(" + y + ")");
        }
    }

    public static class NestedClass2 {
        public static void display()
        {
            System.out.println("x before second static context change: " + x);
            x = 30;
            System.out.println("x after second static context change: " + x);
        }
    }

    public class InnerClass {
        public void display(){}
    }
}

abstract class SupplementalClass extends SuperClass {
    protected String test = "Parent Class String";
    protected InnerClass receiveObject;
}

interface SupplementalInterface {
    public static final int test = 3;
    public abstract void display();
}

class SupplementalClass2 extends SupplementalClass implements SupplementalInterface {
    public void display()
    {
        System.out.println("Supplemental Interface Field Access Test: " + SupplementalInterface.test);
        System.out.println("Supplemental Parent Field Access Test: " + super.test);
    }
    public void setObject(InnerClass in){
        receiveObject = in;
    }

    public InnerClass getObject()
    {
        return receiveObject;
    }
}

这是固定版本:InnerClass有一个方法display()来覆盖SupplementalClass2中的方法。

之前,InnerClass为空,我试图在Anonymous Class实例中设置显示方法,而不是类本身,因为我相信内部类将继承通过{{1}实现的抽象显示方法}。

所以我的问题是,如果不通过继承,嵌套和内部类如何访问其持有者中的数据?

1 个答案:

答案 0 :(得分:3)

内部类实例访问其外部类实例的字段和方法,就像任何对象访问另一个对象的字段和方法一样。唯一的区别是,为了能够访问私有成员,编译器生成合成桥接方法(非私有),由内部类调用,以访问私有成员。

例如参见class:

Complex

如果您编译并致电public class Outer { private int privateField; public int publicField; private void privateFoo() {} public void publicFoo() {} private class Inner { void bar() { privateFoo(); publicFoo(); System.out.println("privateField = " + privateField); System.out.println("publicField = " + publicField); } } } ,您将获得以下输出:

javap -c Outer Outer.Inner

如您所见,Outer类还有两个静态方法:Compiled from "Outer.java" public class com.foo.Outer { public int publicField; public com.foo.Outer(); Code: 0: aload_0 1: invokespecial #3 // Method java/lang/Object."<init>":()V 4: return public void publicFoo(); Code: 0: return static void access$000(com.foo.Outer); Code: 0: aload_0 1: invokespecial #2 // Method privateFoo:()V 4: return static int access$100(com.foo.Outer); Code: 0: aload_0 1: getfield #1 // Field privateField:I 4: ireturn } Compiled from "Outer.java" class com.foo.Outer$Inner { final com.foo.Outer this$0; void bar(); Code: 0: aload_0 1: getfield #1 // Field this$0:Lcom/foo/Outer; 4: invokestatic #3 // Method com/foo/Outer.access$000:(Lcom/foo/Outer;)V 7: aload_0 8: getfield #1 // Field this$0:Lcom/foo/Outer; 11: invokevirtual #4 // Method com/foo/Outer.publicFoo:()V 14: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 17: new #6 // class java/lang/StringBuilder 20: dup 21: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V 24: ldc #8 // String privateField = 26: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 29: aload_0 30: getfield #1 // Field this$0:Lcom/foo/Outer; 33: invokestatic #10 // Method com/foo/Outer.access$100:(Lcom/foo/Outer;)I 36: invokevirtual #11 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 39: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 45: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 48: new #6 // class java/lang/StringBuilder 51: dup 52: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V 55: ldc #14 // String publicField = 57: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 60: aload_0 61: getfield #1 // Field this$0:Lcom/foo/Outer; 64: getfield #15 // Field com/foo/Outer.publicField:I 67: invokevirtual #11 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 70: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 73: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 76: return } access$000(),它们分别调用private方法并返回private字段的值。内部类通过这些方法调用私有方法并访问私有字段。

但是,以通常的方式访问公共方法和字段,因为没有什么能阻止对象访问另一个对象的公共成员。

我允许您对嵌套类和静态成员进行相同的实验,以了解它是如何正常工作的。