构造函数获取内部泛型 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>
。此外,它还包含一个警告。
请注意,只有当 C1
是 C
的内部 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;
}
}
假设如下 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>
。此外,它还包含一个警告。
请注意,只有当 C1
是 C
的内部 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;
}
}