我有三个班级:A
,AA
和Top。 A和AA延伸顶部。
为什么这不会编译:
A a = new A();
AA aa = (AA)a;
但这会:
float f = 4.3f;
int i = (int) f;
答案 0 :(得分:1)
类A
和类AA
位于同一层次结构中,但它们是并排的,因此它们不能彼此强制转换。
让我们说类A
定义如下:
public class A extends Top{
public A() {
}
public void foo(int i) {
System.out.println(i);
}
}
该课程AA
的定义如下:
public class AA extends Top {
public AA() {
}
public void bar(String s) {
}
}
现在让理论上想象一下如果你试图将A
强制转换为AA
并且它有效的话会发生什么:
A a = new A();
(AA) aa = (AA) a;
由于aa
的静态类型为AA
,因此Java会让您编写如下代码:
aa.bar("hi!");
由于AA
类有一个条形方法,但是aa
的动态类型为A
,这意味着变量的实际对象{ {1}}指的是没有有一个名为aa
的方法。
(对象的静态类型告诉您可以在其上调用哪些方法,动态类型告诉您它实际具有哪些方法。)
因此,Java会告诉bar("hi!")
执行aa
,但bar("hi!")
不知道该怎么做,因为aa
没有定义aa
方法
答案 1 :(得分:0)
您可以在要强制转换的类中创建强制转换方法。这里我使用a.cast(B b)方法将类型转换为类型A.
public class A {
public int i;
public A cast(B b){
A a = new A();
a.i=b.i;
return a ;
}
}
public class B {
public int i=10;
}
public class Tester {
public static void main(String[] args) {
B b = new B();
A a= new A();
a=a.cast(b);
System.out.println(a.i);
}
}
答案 2 :(得分:0)
Widening Primitive Conversion
(无信息丢失)和Narrowing Primitive Conversion
(信息可能丢失),您可以找到更多详细信息在the official Java docs。因此,你可以int i = (int) f;
的原因是转换规则是在Java规范和Java编译器中定义的,允许你这样做。如果您尝试过,则无法int a = (int) true
,因为没有将boolean
类型转换为int
的规则。
引用类型的类型转换规则也很简单,编译器只允许您在认为A a = (A) b
的类型 b
时执行类型转换A
或者类型层次结构中sub-type
的{{1}},请看下面的代码:
A
编译器只知道b是类型Object b = c;
A a = (A) b;
但不知道它的特定类型,因为Object
是Java类型层次结构的Object
,所以{{1}的实际类型也许是任何类型,比如类型root
,所以编译器允许你这样做。如果b
实际上不一个A
,则只有在投放b
时才能在运行时找到错误。
另一方面,当明确知道 A
不是ClassCastException
类型时,编译器会阻止您执行A a = (A) b
:
b
如果您具有类型A
和class A {}
class B {}
的上述定义,那么编译器有足够的信息表明实例A
绝对不是B
类型,因此它会给出当您尝试B
时,编译错误为A
。这是使用强类型编程语言的一大好处:保证类型安全(在Java的编译时)。