3

我必须调用一个带Class参数的方法:

public action(Class<? extends SomeInterface> classVariable);

我能够做到这一点:

action(new SomeInterface() { 
    // implement interface
  }.getClass());

但是,如果不实例化对象并调用getClass()?

4

5 回答 5

4

如果没有实例,您将如何访问匿名类?您将需要一个名称来以某种方式引用它,根据定义它没有(确保它在运行时会有一些编译器生成的名称,但是要查询您需要首先创建它,并且如果不实例化就无法创建它它)。

所以没有办法达到你想要的。

于 2011-02-04T22:56:33.067 回答
0

(@PeterLawrey答案的长格式)

问题是没有定义内部类而不实例化它的语法。我个人的感觉是,这意味着它没有得到语言的适当支持,你不应该这样做。

但从技术上讲,这是可能的。即使从未执行,匿名内部类定义/实例化仍将被编译并生成类文件。因此,如果您愿意破解并“猜测”为匿名内部类生成的名称,您可以Class<?>使用Class.forName.

import java.util.Arrays;

class X {
    @SuppressWarnings("unchecked")
    private Class<? extends Runnable> getAnon() {
        if (true) { // Circumvent dead code compiler error
            String innerName = getClass().getName() + "$1";
            System.out.println("Expect autogenerated inner class name to be " + innerName);
            try {
                return (Class<? extends Runnable>)Class.forName(innerName);
            } catch(ClassNotFoundException e) {
                throw new RuntimeException("CompileTimeException!", e);
            }
        } 
        // Here's our anonymous inner
        // And be careful:
        // if you stuff it into the else branch of the if above,
        // the class file won't get created
        new Runnable() {
            {
                System.out.println("Inner class instantiated!");
            }
            public void run() {
                System.out.println("My outer is \"" + name + "\".");
            }
        };
        // If you had multiple anonymous inner classes, the order would matter...
        return null;
    }

    final String name;

    X(String name) {
        this.name = name;
    }

    public static void main(final String... arguments) throws Exception {
        Class<? extends Runnable> clazz = new X("This won't be used").getAnon();
        System.out.println("Ctors: " + Arrays.toString(clazz.getDeclaredConstructors()));
        clazz.getDeclaredConstructor(X.class).newInstance(new X("magic")).run();
    }
}


这应该打印:

Expect autogenerated inner class name to be X$1
Ctors: [X$1(X)]
Inner class instantiated!
My outer is "magic".

请注意,如何仅构造内部类的一个实例,并且调用该实例的实例X不是getAnon匿名类实例化的实例。

所以我们可以驳斥其他一些认为这应该是不可能的论点:

  • 您需要一个名称来引用该类(@PéterTörök):Class存储的实例clazz就足够了。(但我们确实不得不用生成的名称作弊X$1。)
  • 内部类需要一个外部类来实例化(@PaŭloEbermann):内部类“捕获”的所有变量都成为其生成的构造函数的参数。this行为方式相同。(尝试添加参数getAnon并从中打印run。)
于 2021-05-31T02:38:58.503 回答
-1

You should be able to do the following:

public void action(Class<? extends SomeInterface> classVariable);

then call:

action(new SomeInterface() { // implement interface }.getClass());

Example code:

interface I {}

class A implements I
{    
}

public void action(Class<? extends I> c)
{
}


public void test()
{
   action(new I() {}.getClass());
}
于 2011-02-04T23:04:50.720 回答
-1

也许你正在寻找这个?

action(SomeInterface.class);

我认为这可能是您正在寻找的,但这根本不涉及匿名类。

了解有关该方法 action对类引用的作用的更多详细信息可能会有所帮助。

于 2011-02-04T23:25:05.900 回答
-1

匿名类不能通过名称安全地引用,只能通过实例来引用。您可以预测名称并使用它,但它并不优雅或可靠。

private void neverCalled() {
    SomeInterface si = new SomeInterface() { 
        // implement interface
    };
}

Class anon = Class.forName(getClass()+"$1"); // hopefully its the first!

给类命名并使用它要简单得多。许多 IDE 允许您非常轻松地将其中一个更改为另一个。

于 2011-02-04T23:08:32.660 回答