我决定从Android
app:
TextView txt = (TextView) findViewById(R.id.activity_display_message);
findViewById
返回View
个对象,然后我们将其转换为TextView
一个(TextView
是View
的子类)
似乎我误解了它的运作方式。我希望此代码能够正常运行,因为C extends B
因此我应该将B
对象转发给C
。
但是我在运行时遇到异常,我无法将B
强制转换为C
。
那么有人可以解释我错在哪里吗?为什么Android
样本有效?
public class A{
public static void main(String[] args){
B b = new B();
b.f();
C c = (C)b;
}
}
class B{
public void f(){
System.out.println("Class B");
}
}
class C extends B{
public void f(){
System.out.println("Class C");
}
}
答案 0 :(得分:2)
使用Cast操作可以更改对象的静态类型,这是另一种说法"告诉编译器您对正在投射的对象类型的了解。"
如果您的类型为B
的变量包含C
类型的对象,则可以将该变量强制转换为C
:
B b = new C();
C c = (C)b; // works fine
这是正确的,因为b
的对象实际上是C
。
当b
引用的对象不 a C
时,编译器将捕获您的错误,并抛出强制转换异常:
B b = new B();
C c = (C)b; // throws class cast exception
成功与失败之间的区别取决于运行时对象的实际类型。有效的代码可以将View
转换为TextView
,因为静态类型为View
的变量实际上在运行时引用了TextView
。
答案 1 :(得分:2)
在java中,如果没有superclass reference variable
的演员,则无法将subclass reference variable
分配给subclass type
。示例可以找到何时需要显式对象引用转换?当您明确地将超类引用转换为子类引用时,编译器很高兴,但编译器并不关心引用所持有的实际对象是什么。它实际上是否有一个超类对象,或者只是一个包含子类对象的超类引用?编译时没有回答,但它必须回答这个问题。
你不能只是拿一个父对象然后突然变成一个孩子。父对象不是子类的实例。如果引用所持有的实际对象是超类对象,则将其转换为子类引用会导致编译时错误。
根据您的情况B is parent class
和C is its child
。
class SuperClass {
// ...
}
class SubClass extends SuperClass {
// ...
}
public class Program {
public static void main(String[] args) {
// case 1: actual SuperClass object
SuperClass p1 = new SuperClass();
// case 2: SubClass object is referred by a SuperClass reference
SuperClass p2 = new SubClass();
SubClass s1 = (SubClass) p1; //run time error
SubClass s2 = (SubClass) p2; //OK
}
}
答案 2 :(得分:1)
在Android findViewById
中返回View
类的实例。这是TextView
和其他视图元素的直接超类。
所以,如果你想复制类似的东西,那么你可以这样做:
class Test {
public static void main(String args[]) {
A a = new A();
C c = (C)a.getViewByid('c');
c.f();
}
}
class A {
public B getViewByid(char c) {
B b = null;
switch (c) {
case 'b':
b = new B();
break;
case 'c':
b = new C();
break;
default:
b = new B();
}
return b;
}
}
class B {
public void f() {
System.out.println("Class B");
}
}
class C extends B {
public void f() {
System.out.println("Class C");
}
}