java签入Eclipse,泛型使用哪种类型
class A {};
class B extends A {};
class C extends B {};
class D extends B {};
class E {};
class X {
public static <T> T f(T[] a, Field<? extends T> b) { return null; }
public static <T> T[] g(Field<? extends T> a, Field<? super T> b) { return null; }
字段只是一个接口。当我得到一些指示,比如
A a = X.f(new B[3], new FieldFix<D>(8));
我知道这是可行的,因为泛型类型T将是A,因为D扩展了B,B扩展了A,所以这是一个非常合法的分配
但我有一些不同的地方,我对T的类型很不确定,也无法向自己解释为什么它起作用或不起作用。那么有什么方法可以看到T的类型呢?我已经使用过调试器,但我从未真正使用过它,所以我对它不是很熟悉
增加:
public interface Field<T> {
int size();
T get(int i);
T set(int i, T e); }
public class FieldFix<T> implements Field<T> {
private T[] a;
public FieldFix(int size) {
T[] tmp = (T[])new Object[size]; a = tmp; }
public int size() { return a.length; }
public T get(int i) {
try {
return a[i];
} catch (ArrayIndexOutOfBoundsException e) { ... }
}
public T set(int i, T e) {
try {
T result = a[i];
a[i] = e;
return result;
} catch(ArrayIndex...) { ... }
}
这就是我得到的所有指示,其中一些应该有效,而另一些则无效
A x01 = X.f(new B[3], new FieldFix<D>(8));
Object[] x02 = X.f(new C[2], new FieldFix<D[]>(8));
Feld x03 = X.f(new FieldFix[4], new FieldFix<FieldFix<A>>(8));
A[] x05 = X.g(new FieldFix<B>(8), new FieldFix<B>(8));
B[] x06 = X.g(new FieldFix<B>(8), new FieldFix<A>(8));
C[] x07 = X.g(new FieldFix<B>(8), new FieldFix<A>(8));
C[] x08 = X.g(new FieldFix<C>(8), new FieldFix<A>(8));
C[] x09 = X.g(new FieldFix<A>(8), new FieldFix<C>(8));
C[] x10 = X.g(new FieldFix<D>(8), new FieldFix<B>(8));
Object x11 = X.g(new FieldFix<B>(8), new FieldFix<D>(8));
B[] x12 = X.g(new FieldFix<A>(8), new FieldFix<Object>(8));
A[] x13 = X.g(new FieldFix<B>(8), new FieldFix<Object>(8));
Object x14 = X.g(new FieldFix<C[]>(8), new FieldFix<A[]>(8));
Object x15 = X.g(new FieldFix<Field<C>>(8), new FieldFix<Field<A>>(8));
Object x16 = X.g(new FieldFix<Field<C>>(8), new FieldFix<Field>(8));
像x09、x11、x15一样,Eclipse告诉我我使用了错误的参数,对于其他参数,我喜欢检查我对其工作原理的解释是否正确,因为有时我会对这些泛型和通配符的内容感到非常困惑。所以当我
A[] a = X.g(new FieldFix<B>(8), new FeldFix<B>(8));
,我是这样理解的:因为B可以变成B,C或者D,并且使第二个T变成B,A(或者甚至是物体?)。。。所以T应该是B,B扩展了A,这有点像A[]A=newa()
很抱歉我的英语不好,但我希望你能理解我的意思:D我只是想检查一下Java/Eclipse使用的是哪种类型,以及Java获得castet隐式的是什么
# 1 楼答案
你只需要问问自己,是否有任何
T
的赋值会使它有效(可能有多个有效选项,但重要的是是否至少有一个)?如果有,它应该编译我不确定您对
x0
-x16
行中的哪一行有问题。在后面的示例A[] a = X.g(new FieldFix<B>(8), new FieldFix<B>(8));
中,参数和返回类型具有以下约束:FieldFix<B>
是Field<? extends T>
的一个亚型(即B
是T
的一个亚型)FieldFix<B>
是Field<? super T>
的一个子类型(即B
是T
的一个超类型)T[]
是A[]
的一个亚型(即T
是A
的一个亚型)前两个约束已经保证只有
T
=B
是有效的,并且也满足第三个约束。所以它应该编译# 2 楼答案
在调用方法f的示例中,类型T的实际值由第一个参数-T[]a确定。在g中,它由发送的实际字段参数确定
我通过调用并深入到:
a.getClass().getGenericInfo().getTree()
路径,在运行时查看了T的类型赋值
A a = f(new B[3], ...)
不产生编译器错误的原因在于“B是a”现在,关于方法g:
您可以给方法g一个参数,该参数是
Field<B>
,例如,将其称为bField,然后仍然进行赋值:A[] a = g(bField, bField)
这将起作用,因为java中的数组是不变量:如果B扩展A,则B扩展A的长度大于
B[]
扩展A[]
例如,如果使用列表而不是数组,则赋值中将出现编译器错误:
这是因为在java中列表是协变的:即使B扩展了A,
List<B>
也不会扩展List<A>