有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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隐式的是什么


共 (2) 个答案

  1. # 1 楼答案

    你只需要问问自己,是否有任何T的赋值会使它有效(可能有多个有效选项,但重要的是是否至少有一个)?如果有,它应该编译

    我不确定您对x0-x16行中的哪一行有问题。在后面的示例A[] a = X.g(new FieldFix<B>(8), new FieldFix<B>(8));中,参数和返回类型具有以下约束:

    • FieldFix<B>Field<? extends T>的一个亚型(即BT的一个亚型)
    • FieldFix<B>Field<? super T>的一个子类型(即BT的一个超类型)
    • T[]A[]的一个亚型(即TA的一个亚型)

    前两个约束已经保证只有T=B是有效的,并且也满足第三个约束。所以它应该编译

  2. # 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[]

    例如,如果使用列表而不是数组,则赋值中将出现编译器错误:

    List<A> goo = goo(bField, bField); //Error: goo cannot be applied to bField...
    

    这是因为在java中列表是协变的:即使B扩展了A,List<B>也不会扩展List<A>