我在玩匿名子类,发现一个无法解决的问题。

编辑:由于托马斯,问题得以解决,完整的工作代码在pastebin(Foo.java; FooTest.java)上

2节课Foo和FooTest ...
代码优先:

class Foo {

    public Foo () {}

    public void whichClassAmI () {
        System.out.println(this.getClass());
    }

    public void say () {
        System.out.println("Foo says: nothing");
    }

    public <T extends Foo> T getAnotherFoo () {

        try {
            Class<? extends Foo> c = this.getClass();
            T r = (T)(c.getConstructor().newInstance());
            return r;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}


_

class FooTest {

    public static String stuff = "";

    public static void main (String[] args) {

        Foo f1 = new Foo();

        // instance of anon subclass
        Foo f2 = new Foo(){
            public void say () {
                System.out.println("Modded Foo says: " + stuff);
            }
        };

        f1.whichClassAmI();
        f2.whichClassAmI();

        stuff = "stuff";
        f1.say();
        f2.say();

        Foo f3 = f1.getAnotherFoo();
        f3.say();

        Foo f4 = f2.getAnotherFoo(); // <-- exception here
    }

}


因此,此代码会以不安全的操作警告进行编译,运行并引发异常。输出为:

Note: Foo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
class Foo
class FooTest$1
Foo says: nothing
Modded Foo says: stuff
Foo says: nothing
Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodException: FooTest$1.<init>()
    at Foo.getAnotherFoo(Foo.java:20)
    at FooTest.main(FooTest.java:23)
Caused by: java.lang.NoSuchMethodException: FooTest$1.<init>()
    at java.lang.Class.getConstructor0(Class.java:2723)
    at java.lang.Class.getConstructor(Class.java:1674)
    at Foo.getAnotherFoo(Foo.java:17)
    ... 1 more


我不明白的是:


f2类是FooTest $ 1,此类似乎没有扩展Foo
如果(1)是true,为什么可以使用FooTest $ 1设置“ Class c = [...]”
如果(1)为假而(2)正确工作,为什么找不到方法?

最佳答案

改为1):f2的类型为FooTest$1,它扩展了Foo,但未打印出来,您只获得当前类,没有超类或接口。

至2):由于1)为假,因此这里没有问题:)

到3):问题在于,匿名内部类FooTest$1需要创建外部FooTest实例。通过反射调用构造函数将尝试创建没有FooTest封闭实例的新实例,并且这样的方法不可用(即,创建内部类的实例而没有封闭类的实例的方法)。

您需要做的是获取将封闭类的实例作为其参数的构造函数。有关更多信息,请查看以下问题:Is it possible to create an instance of nested class using Java Reflection?

编辑:

我再次阅读您的代码,感到as愧,我错过了这一点:FooTest$1类实际上是一个静态内部类,因为它是在静态main方法中创建的。因此,它没有构造函数接受封闭的类实例。

但是,由于您创建了类及其内联的构造函数,因此该构造函数不是公开可见的。因此,getClass().getConstructor()不会返回它(此类仅返回公共构造函数。在这种情况下,您必须使用getClass().getDeclaredConstructor()。对于字段和方法,仅对于记录而言,情况也是如此。

09-10 06:00