【问题标题】:Why JAVA can not compile when using generic type in interface为什么JAVA在接口中使用泛型时无法编译
【发布时间】:2016-08-18 11:57:05
【问题描述】:

您好,我在 java 中使用泛型类型时遇到问题。实际问题是,当我在方法声明上使用泛型类型时工作正常。然后,如果我将泛型类型添加到接口声明中,则代码不会编译。以下是工作代码:

public interface IRuntimeConvert {
    public <T> T convertInstanceOfObject(String o, Class<T> clazz);
}

public class RuntimeConvertImpl implements IRuntimeConvert {

    private final Map<String, Object> hashMap;

    public RuntimeConvertImpl(Map<String, Object> hashMap) {
        this.hashMap = hashMap;
    }

    @Override
    public <T> T convertInstanceOfObject(String o, Class<T> clazz) {
        try {
            return clazz.cast(hashMap.get(o));
        } catch (ClassCastException e) {
            return null;
        }
    }
}

public static void main(String[] args) {

    Map<String, Object> hashMap = new HashMap<>();
    hashMap.put("s", "string");
    hashMap.put("i", 0);
    hashMap.put("l", 0L);

    IRuntimeConvert rtConvert = new RuntimeConvertImpl(hashMap);

    String s = rtConvert.convertInstanceOfObject("s", String.class);
    System.out.println(s);
    Integer i = rtConvert.convertInstanceOfObject("i", Integer.class);
    System.out.println(i);
    Long l = rtConvert.convertInstanceOfObject("l", Long.class);
    System.out.println(l);
}

上面的代码正在编译。当我进行以下更改时,代码无法编译。

public interface IRuntimeConvert<S> {

    public <T> T convertInstanceOfObject(String o, Class<T> clazz);

    public S getSomething(S s);
}

public class RuntimeConvertImpl implements IRuntimeConvert<Object> {

    private final Map<String, Object> hashMap;

    public RuntimeConvertImpl(Map<String, Object> hashMap) {
        this.hashMap = hashMap;
    }

    @Override
    public <T> T convertInstanceOfObject(String o, Class<T> clazz) {
        try {
            return clazz.cast(hashMap.get(o));
        } catch (ClassCastException e) {
            return null;
        }
    }

    @Override
    public Object getSomething(Object s) {
        throw new UnsupportedOperationException("Not supported yet."); 
    }

}

在主类中进行上述更改后,我为方法 rtConvert.convertInstanceOfObject("s", String.class) 的每次调用都设置了类型转换错误,并带有错误消息:

Incompatible types: Object cannot be converted to String.

如果我尝试运行 main 我得到:线程“main”中的异常 java.lang.RuntimeException:无法编译的源代码 - 不兼容的类型:java.lang.Object 无法转换为 java.lang.String

【问题讨论】:

  • 类型擦除。 Java 泛型不像 C++ 模板:docs.oracle.com/javase/tutorial/java/generics/erasure.html
  • 您好 cparaskeva - 您能否编辑您的问题以包含更多关于它如何以及在何处不编译的详细信息?
  • 如果出现错误,请始终包含错误消息。
  • 我在删除 ** 后测试你的代码,创建两个文件 IRuntimeConvert 和 RuntimeConvertImpl。添加并导入到 java.util.Map。它编译得很好。
  • 您使用的是什么 java/javac 版本?我刚刚用javac 1.8.0_92 很好地编译了它。 (当然是去掉星星之后)

标签: java generics


【解决方案1】:

发生这种情况是因为您在实现中将泛型类型指定为 Object 并使用以下行:

public class RuntimeConvertImpl implements IRuntimeConvert<Object> {

因此,对getSomething 的调用将始终必须返回Object。但是,由于StringObject 的子类,因此不能自动转换为String,您必须执行以下操作:

String s = (String) rtConvert.getSomething();

请注意,这并不能保证类型安全,可能会导致ClassCastExceptions。

【讨论】:

  • 如果你想使用泛型......使用它们!如果你想返回一个 String 对象,只需实例化它:IRuntimeConvert rtConvert 但是这个答案解释了这个问题,我投票支持它
  • 感谢您的解释!事实上,我对泛型有误解。
  • 据我所知,getSomething() 方法中没有 getSomething()。因此这里没有编译错误。
  • 确实,OP 没有提到 main 方法中的代码的任何更改,但我想举例说明这种使用泛型会导致什么。因此,短语“你必须”;)
【解决方案2】:

我无法为您编写 Java 语言规范。我只是得出一些结论。

如果您在main() 中更改一行:

IRuntimeConvert<?> rtConvert = new RuntimeConvertImpl(hashMap);
//        type ^^^^

然后main() 将编译。因此,显然,javac 需要所有为实际对象类型定义的泛型。然后就可以处理方法级别的泛型参数了。

【讨论】:

  • 并行编辑会发生这种情况。无论如何也要为你 +1。
【解决方案3】:

这可能是 Java 尝试推断泛型类型的问题。如果在main方法中指定rtConvert变量的泛型类型:IRuntimeConvert&lt;Object&gt; rtConvert,而不是IRuntimeConvert rtConvert,就解决了。

默认情况下,我总是尝试指定变量的泛型类型。

【讨论】:

  • 是的,谢谢,这就是问题所在!但是我认为默认情况下 Java 正在将未绑定类型替换为对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
相关资源
最近更新 更多