访问内部匿名类成员

问题描述 投票:0回答:8

除了使用反射之外还有什么方法可以访问匿名内部类的成员吗?

java anonymous-class
8个回答
9
投票

匿名内部类有类型但没有名称。

您可以访问未由指定超类型定义的字段。然而,一旦分配给命名类型变量,接口就会丢失。

显然,您可以从内部类本身访问这些字段。添加代码的一种方法是通过实例初始化程序:

final AtomicInteger y = new AtomicInteger();
new Runnable() {
    int x;
    {
        x = 5;
        doRun(this);
        y.set(x);
    }
    public void run() {
        ... blah ...
    }
};

匿名内部类表达式返回的值具有匿名类型,因此您有一次机会在类本身之外使用它:

final int y = new Runnable() {
    int x;
    {
        x = 5;
        doRun(this);
    }
    public void run() {
        ... blah ...
    }
}.x;

您还可以通过类似于以下声明的方法来传递它:

<T extends Runnable> T doRun(T runnable);

9
投票

您可以使用本地类代替匿名类。看:

public class Test {
    public static void main(String... args) {
        class MyInner {
            private int value = 10;
        }

        MyInner inner = new MyInner();
        System.out.println(inner.value);
    }
}

您只能在方法体中引用

MyInner
类型。因此,在该方法之外,您将无法使用其超类(在本例中为
java.lang.Object
)或接口中未声明的字段/方法。


1
投票

public class AccessAnonymous {
    private Runnable runnable; // to have instance of the class

    public static void main(String[] args) throws Exception {
        AccessAnonymous a = new AccessAnonymous();
        a.a(); // init field

        Class clazz = a.runnable.getClass();
        Field field = clazz.getDeclaredField("i");
        field.setAccessible(true);

        int int1 = field.getInt(a.runnable);
        System.out.println("int1=" + int1);
    }

    public void a() {
        runnable = new Runnable() {
            private int i = 1;

            public void run() {
                i = 90;
            }

        };
        runnable.run();// change value
    }
}

1
投票

对于匿名类,在类造成的混乱和匿名的便利性之间也需要权衡。复杂的类很少属于匿名类,而是属于命名的私有内部类。

在大多数匿名类中,我们只需要“喂”知识并且可以在构造时完成。 在一些匿名类(例如,返回值载体)中,我们也关心一个返回值。

众所周知,数据成员不应该直接访问,而应该通过 getter setter 访问。如果您发现自己添加了很多 getter 和 setter,那么您可能做错了什么,并且不应该使用匿名类。


0
投票

如果它实现接口或扩展现有类,则可以访问接口或基类中定义的成员。


0
投票

Fooz 先生是对的,只不过接口只能定义常量成员。最好的方法是将 getter/setter 方法添加到您的界面,然后使用它们来获取您的值。但是对于每个匿名类,您都必须定义这些方法(有点痛苦)。


0
投票

如果您想要可读、可维护的代码,请不要使用匿名类。如果您使用匿名类并且想要可读、可维护的代码,那么当您需要访问该内部类中的元素时,请勿使用匿名类。有很多方法可以做到这一点,但我恳求您不要使用任何这些技巧。可读性胜过所有其他美德。


0
投票

这个问题已有15年历史了,但我认为还有另一种方法可以做到这一点! 该示例涉及单元测试:

public class MyServiceTest {

    private Date capturedToday;

    // anonymous inner class
    private final MyService testSubject = new MyService() {

        @Override
        Date today() {
            // capture the Date instance created by MyService
            Date today = super.today();
            MyServiceTest.this.capturedToday = today;
            return today;
        }
    };

    @Test
    void myTest() {

        MyResult result = testSubject.run();            
        assertSame(capturedToday, result.getToday());

在此示例中,MyService 在内部创建一个 Date 并将其放入结果中。为了检查该值,我创建了一个匿名内部类,该内部类在创建实例时捕获该实例并将其存储在 captureToday 字段中:

MyServiceTest.this.capturedToday = today;

此语法允许内部类访问其外部类的字段。因此,通过外部类中的字段可以读取值。

© www.soinside.com 2019 - 2024. All rights reserved.