为什么编译器状态不存在唯一的最大实例?

我有以下类:

public class Obj<T> extends BaseModel {

    public static final String OBJECT = "object";

    public Obj(T object) {
        setObject(object);
    }

    public T getObject() {
        return get(OBJECT);
    }

    public void setObject(T object) {
        set(OBJECT, object);
    }
}

和。。。

/** This is a 3rd party library class **/
public class BaseModel implements ModelData, Serializable {
  //...members and stuff...

  @SuppressWarnings({"unchecked", "rawtypes"})
  public <X> X get(String property) {
    X obj = null;
    if (start > -1 && end > -1) {
      Object o = map.get(property.substring(0, start));
      String p = property.substring(start + 1, end);
      if (o instanceof Object[]) {
        obj = (X) ((Object[]) o)[Integer.valueOf(p)];
      } else if (o instanceof List) {
        obj = (X) ((List) o).get(Integer.valueOf(p));
      } else if (o instanceof Map) {
        obj = (X) ((Map) o).get(p);
      }
    } else {
      obj = (X) map.get(property);
    }
    return obj;
  }
}

编译时,我收到以下错误。

type parameters of <X>X cannot be determined; no unique maximal instance exists for type variable X with upper bounds T,java.lang.Object -> getObject()

这在Eclipse中没有发生,据我所知,Eclipse使用与我的Ant构建相同的JDK。我看过关于 Sun 编译器问题的 SO 线程,但这似乎是针对动态声明类型的静态方法。

为什么我会得到这个错误,更重要的是,我该如何解决它?

到目前为止,我发现的唯一原因就是像我这样转换我的方法:

@SuppressWarnings({"unchecked"})
public T getObject() {
    return (T) get(OBJECT); //yuck
}

告诉我我在裂缝上,这是正确的方式是可以接受的。


答案 1

这是在 Java SE 7 中修复的虚拟错误


答案 2

它不会编译,因为你的代码对泛型的期望太高了 -> 即,< X > X 部分:

public <X> X get(String property) { ... }

在下面的代码中:

public T getObject() {
  return get(OBJECT);
}

您必须记住,在编译器实际开始编译Java代码之前,泛型总是“展开”的。这是一个预处理步骤。

在你的例子中,编译器不知道在编译时用什么来替换X。编译器需要确定 X 的类型,因为它需要对照 T 检查它以验证代码。因此,错误...

您的问题的解决方案是将 X < X >替换为 Object:

public Object get(String property) { ... }

并在以下位置添加强制转换:

public T getObject() {
  return (T) get(OBJECT);
}

您将在编译时收到未选中的强制转换警告,但您的代码将编译(因此,是的,您的解决方法是有效的)。


推荐