我必须调用一个带Class
参数的方法:
public action(Class<? extends SomeInterface> classVariable);
我能够做到这一点:
action(new SomeInterface() {
// implement interface
}.getClass());
但是,如果不实例化对象并调用getClass()
?
我必须调用一个带Class
参数的方法:
public action(Class<? extends SomeInterface> classVariable);
我能够做到这一点:
action(new SomeInterface() {
// implement interface
}.getClass());
但是,如果不实例化对象并调用getClass()
?
如果没有实例,您将如何访问匿名类?您将需要一个名称来以某种方式引用它,根据定义它没有(确保它在运行时会有一些编译器生成的名称,但是要查询您需要首先创建它,并且如果不实例化就无法创建它它)。
所以没有办法达到你想要的。
(@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
匿名类实例化的实例。
所以我们可以驳斥其他一些认为这应该是不可能的论点:
Class
存储的实例clazz
就足够了。(但我们确实不得不用生成的名称作弊X$1
。)this
行为方式相同。(尝试添加参数getAnon
并从中打印run
。)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());
}
也许你正在寻找这个?
action(SomeInterface.class);
我认为这可能是您正在寻找的,但这根本不涉及匿名类。
了解有关该方法 action
对类引用的作用的更多详细信息可能会有所帮助。
匿名类不能通过名称安全地引用,只能通过实例来引用。您可以预测名称并使用它,但它并不优雅或可靠。
private void neverCalled() {
SomeInterface si = new SomeInterface() {
// implement interface
};
}
Class anon = Class.forName(getClass()+"$1"); // hopefully its the first!
给类命名并使用它要简单得多。许多 IDE 允许您非常轻松地将其中一个更改为另一个。