为什么A的实例可以转换为List而不能转换为String?
class A{}
...
A a = new A();
List list = (List)a; //pass
String s = (String)a; //compile error
答案 0 :(得分:7)
引用JLS:
如果对于任何两个类(非接口)Vi和Vj,Vi不是Vj的子类,反之亦然,那么这是一个编译时错误。
A
和List
是不相关的类,因此它是编译时错误。 A
是一个接口,因此不会导致相同的错误。
请注意你的断言
A的实例可以转换为List
不完全正确:List
无法投放到.
;它只是运行时故障,而不是编译时故障。
答案 1 :(得分:6)
根据规范,编译器在对转换进行这些检查时仅考虑声明的a
类型。
所以,你写道:
A a = new A();
但编译器只考虑
A a; // = <something>;
所以它知道a
不能是String
,因为一个类只能有一个超类(没有多重继承),所以不能成为类{{1}的子类这也是一个字符串。
但对于接口来说,这不是真的。因此,虽然我们知道课程A
没有实现A
,但可能会有一个类List
定义如下:
B
由于编译器只考虑声明的类型,因此必须假设您已将class B extends A implements List {}
分配给new B()
。
因此,因为a
的子类可以实现接口A
,所以编译器不能假设转换为List
总是失败。
当然,演员会在练习中失败 - 在运行时。但不是在编译时。
答案 2 :(得分:1)
Java中的类只能转换为其超类型之一,或其超类型之一的接口之一。
在您的情况下,类String
不是A
的子类。因此String
无法投放到String
。此外,A
是一个最终类,因此您无法编写可以转换为String
的类Object
。
Java已经认识到需要轻松地将类显示为字符串,尤其是出于调试/日志记录的目的。为满足此需求,toString()
类附带Object
方法。由于所有Java类都从toString()
类扩展,因此所有Java类都包含toString()
方法的实现。
重要的是要记住,A
方法的存在并不意味着A
是一个字符串,而是意味着你可以从A
得到一个字符串描述A
实例。如果您发现所提供的说明不适合您的目的,您可以覆盖toString()
的{{1}}方法并返回更好的说明,就像这样
@Override
public String toString() {
return "my better description";
}
由于覆盖是用Java编写的,您还可以包含任何变量或其他项目,最终可以将其转换为字符串(因为所有对象都包含toString()
几乎所有内容)。