为什么在Java中不能直接转换类型?

4
在下面的代码片段中,为什么第1行和第2行可以正常工作,而第3行会导致编译错误?难道前两行在功能上不等同于第三行吗?
Loader loader = getLoaderManager().getLoader(0);
PatientLoader patientLoader = (PatientLoader) loader;
patientLoader = (PatientLoader) getLoaderManager().getLoader(0); // ERROR!

抛出此异常:
java: somepath/Patient.java:99: inconvertible types
found   : android.content.Loader<java.lang.Object>
required: com.example.package.PatientLoader

PatientLoader 间接继承自 Loader<>

我来自 C# 背景,在 C# 中这不是问题,所以也许我对 Java 类型系统有所遗漏。

PatientLoader 继承自 AsyncTaskLoader<Cursor>。熟悉 Android SDK 的任何人都知道 AsyncTaskLoader<> 继承自 Loader<>

1个回答

8

这与括号的放置无关。

这个问题与泛型有关:

例如,编译失败:

Loader<Object> loader = getLoaderManager().getLoader(0);
PatientLoader ch = (PatientLoader)loader; // Will show compile error (Cannot cast from Loader<Object> to PatienLoader)

但是下面的代码可以顺利编译:
Loader<?> loader = getLoaderManager().getLoader(0);
PatientLoader ch = (PatientLoader)loader; // Compiles fine.

区别在于<Object>泛型和<?>泛型声明的不同。

问题在于getLoader(int)被定义为返回一个Loader<D>。这意味着在下面的语句中,'getLoaderManager().getLoader()'被解释为一个Loader<Object>而不是Loader<?>。

PatientLoader ch = (PatientLoader)getLoaderManager().getLoader(0); // Compile error.

我认为这是SDK中的一个“漏洞”。getLoader(int)方法应该被定义为返回Loader<?>而不是Loader<D>。

这是Java类型擦除的产物吗? - Andrew Young
不,这不是类型擦除。类型擦除是指运行时无法区分例如ArrayList<String>或ArrayList<Integer>之间的区别。 - Streets Of Boston

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接