访问内部匿名类成员

发布于 2024-07-09 14:01:13 字数 35 浏览 8 评论 0原文

除了使用反射来访问匿名内部类的成员之外,还有其他方法吗?

Is there any way other than using reflection to access the members of a anonymous inner class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

枕头说它不想醒 2024-07-16 14:01:13

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

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

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

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);

Anonymous inner classes have a type but no name.

You can access fields not defined by the named supertype. However once assigned to a named type variable, the interface is lost.

Obviously, you can access the fields from within the inner class itself. One way of adding code is through an instance initialiser:

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

The value returned by the anonymous inner class expression has the anonymous type, so you have one chance to use it outside of the class itself:

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

You can also pass it through a method declared similar to:

<T extends Runnable> T doRun(T runnable);
幼儿园老大 2024-07-16 14:01:13

您可以使用本地类而不是匿名类。 看:

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 )或接口中声明的字段/方法。

You can use local classes instead anonymous class. Look:

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

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

You can have reference of MyInner type only in the method body though. So outside of the method you will not be able to use its fields/methods that are not declared in its super class (java.lang.Object in this case) or interface.

缺⑴份安定 2024-07-16 14:01:13

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
    }
}

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
    }
}
平生欢 2024-07-16 14:01:13

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

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

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

In the case of anonymous classes, there is also a tradeoff between the clutter caused by the class and the convenience of having it anonymous. Complicated classes rarely belong as anonymous but rather as named private inner.

In most anonymous classes, we only need to "feed" knowledge and can do it at construction.
In a few anonymous classes (e.g., return value vehicles) we also care about one return value.

As we know, data members should not directly be accessed but rather with a getter setter. This, if you find yourself in a situation that you have added lots of getters and setters, you are probably doing something wrong anyway and shouldn't be using an anonymous class.

愚人国度 2024-07-16 14:01:13

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

If it implements an interface or extends an existing class, you can access the members defined in the interface or base class.

谁人与我共长歌 2024-07-16 14:01:13

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

Mr Fooz is right, except that interfaces can only define constant members. the best way would be to add getter/setter methods to your interface and then use those to get your value. but then for each anonymous class you would have to define those methods (kind of a pain).

ぃ弥猫深巷。 2024-07-16 14:01:13

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

If you want readable, maintainable code, don't use anonymous classes. If you use anonymous classes and want readable, maintainable code, don't use anonymous classes when you need to access the element in that inner class. There are ways of doing so, but I beg of you to not use any of those hacks. Readability trumps all other virtues.

卖梦商人 2024-07-16 14:01:13

这个问题已经有15年历史了,但我认为还有另一种方法可以做到这一点!

该示例涉及为 MyService 编写单元测试:

public class MyService {

    public Result doSomething() {
        Result result = new Result();
        result.setToday(today();
        return result;
    }

    // not private but package-private so it can be overridden
    Date today() {
        return new Date();
    }
}

以下是单元测试:

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.doSomething();            
        assertSame(capturedToday, result.getToday());

在此示例中,MyService 在内部创建一个 Date 并根据其结果设置它。 为了检查这个逻辑,我创建了一个匿名内部类,它在创建实例时捕获实例并将其存储在 captureToday 字段中:

MyServiceTest.this.capturedToday = today;

此语法允许内部类访问其外部类的字段,从而公开其值。

This question is 15 years old, but I think there is another way to do this!

The example concerns writing a unit test for MyService:

public class MyService {

    public Result doSomething() {
        Result result = new Result();
        result.setToday(today();
        return result;
    }

    // not private but package-private so it can be overridden
    Date today() {
        return new Date();
    }
}

Here is the unit test:

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.doSomething();            
        assertSame(capturedToday, result.getToday());

In this example MyService creates a Date internally and sets it on its result. To check this logic I created an anonymous inner class which captures the instance when it is created and stores it in the capturedToday field:

MyServiceTest.this.capturedToday = today;

This syntax allows an inner class to access fields of its outer class and thus to expose its values.

初吻给了烟 2024-07-16 14:01:13

如果使用 var,您可以从声明的块(或子块)内部访问匿名类的成员。 示例:

public static void main(String[] args) {
    var annon = new Object() {
        int field;
        void method() {
            System.out.println("method called with field=" + field);
        }
    };

    annon.field = 123;
    annon.method();  // prints "method called with field=123"
}

如果成员被声明为静态,这甚至可以工作。

如果我们声明了 Object annon = new Object() { ... 我们会得到编译错误,因为 Object 没有任何 field 或 <代码>method() 成员。

You can access the members of an anonymous class from inside the block (or sub-block) it was declared in, if using var. Example:

public static void main(String[] args) {
    var annon = new Object() {
        int field;
        void method() {
            System.out.println("method called with field=" + field);
        }
    };

    annon.field = 123;
    annon.method();  // prints "method called with field=123"
}

This even works if the members were declared static.

If we had declared Object annon = new Object() { ... we would get compilation errors since Object does not have any field or method() members.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文