构造函数获取内部泛型 class 的实例作为其参数。如何使用它?

The constructor gets an instance of inner generic class as its parameter. How to use it?

假设如下 class(没有任何错误甚至警告):

class C<T> {
    C(C1<T> c1) { /*...*/ }

    class C1<U> { /*...*/ }
}

现在,我如何创建它的新实例?

new C<String>(new C1<String>()) {};  // Error behind `<String>`: Type arguments given on a raw type 
                                     // + Warning behind `new C1<String>()`: Unchecked assignment: 'com.example.package.C.C1<java.lang.String>' to 'com.example.package.C<java.lang.String>.C1<java.lang.String>'type

new C<String>(new C1<>()) {};        // Error behind `<>`: Type arguments given on a raw type

new C<String>(new C1()) {};          // Warning behind `new C1()`: Unchecked assignment: 'com.example.package.C.C1' to 'com.example.package.C<java.lang.String>.C1<java.lang.String>'

虽然第三种方式没有报错,但这不是我想要的! 我要new C1<String>。此外,它还包含一个警告。


请注意,只有当 C1C 的内部 class(而不是 static)时才会出现问题。比如下面的代码就没有问题:

class C<T> {
    C(C2<T> c1) { /*...*/ }

    //class C1<U> { /*...*/ }
}

class C2<V> { /*...*/ }

...

new C<String>(new C2<String>()) {};  // OK
new C<String>(new C2<>()) {};        // OK (and is equivalent)

你已经搞定了。

当你有一个 inner class 是 not static 那么你 always 需要外部实例,包含 class 以创建内部 class 对象(参见 here 示例)。

从这个意义上说,您这里有一个 chicken/egg 问题,根本无法解决。您需要内部 class 的实例来创建外部对象,但您首先需要该外部对象来创建内部对象。

即使有一些肮脏的黑客来解决这个问题,那也很可能是 肮脏的 黑客。不要那样做。所以这里真正的答案是退后一步,仔细看看您实际上想要使用此设计解决的问题。然后找到一个不会被设计破坏的解决方案。

正如@GhostCat 所解释的,您永远无法在不提供外部实例的情况下实例化非静态内部。而type T作用域对innerclass是可见的,你不需要再定义一个type U。我会这样写:

    public class Solve {
       public static void main(String[] args){
            C<String> c = new C<>();
            c.c1 = c.new C1();
            c.c1.value = "Inner Generic Class";
            System.out.println(c.c1.value);
       }
    }


    class C<T> {   

       public C1 c1;

       class C1 {
            public T value;
       }
    }