为什么java编译器没有为此转换告诉"无法转错"?

sur*_*iva 4 java

我刚刚对一个java编译场景感到困惑,该场景对于给定的问题表现得很奇怪.

下面的代码将给出编译错误(不能转换类型),因为A和B是不同的类,它们之间没有关系.

        A a = new A();
        B b = new B();

        B b1 = (B)a;
        A a1 = (A)b;
Run Code Online (Sandbox Code Playgroud)

以同样的方式,如果我将List和Map相互转换,它应该给我编译错误.但它没有给出任何这样的错误,当然我在运行时得到ClassCastException.

        List<String> listObj = new ArrayList<String>();
        Map<Integer,Float> mapObj = new HashMap<Integer,Float>();

        Map newMapObj = (Map) listObj;
        List newListObj = (List) mapObj;
Run Code Online (Sandbox Code Playgroud)

可能是这次调整的原因......

Cos*_*atu 7

那是因为Map并且List是接口,你可以有一个实现两者的类.这对于类无效,因为Java中不可能进行多重继承.


即使这样的用例使得编译器看起来相当愚蠢(因为很明显,在这种情况下,转换将永远不会成功),深入研究初始化代码是没有多大意义的,因为这需要跟踪所有可能的分配参考:

List<String> someOtherList = getSomeOtherList();
List<String> listObj = someOtherList != null ? someOtherList : new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)

这将使不可行的编译器可以说什么样的ListlistObj将是这行之后.

即使使用您的简单示例,编译器也需要在初始声明listObj和转换尝试之间进行跟踪,因此没有对该变量的其他赋值(因此它可以确定肯定listObj是肯定的ArrayList).一旦在赋值和转换之间放置其他代码行,这种跟踪就变得很难以实现.


但我确实同意这样的编译器限制令人沮丧; 我有时会发现以下事实无法编译:

final int i;
try {
    i = Integer.parseInt("someString");
} catch (NumberFormatException e) {
    i = -1;
}
Run Code Online (Sandbox Code Playgroud)

...因为"变量'我可能已被分配给",这显然是不可能的.但编译器实际上并不关心我的try块中的内容,它假定NumberFormatException在该赋值之后可以通过某行代码抛出a ; 所以i不能宣布final.