Java中“ClassCastException”的解释
我读了一些写在“ClassCastException”上的文章,但是我不明白这一点。 有没有好的文章,或者是一个简短的解释?
直接从ClassCastException
的API规范:
抛出以表明代码已经尝试将对象转换为其不是实例的子类。
因此,例如,当试图将一个Integer
为一个String
, String
不是Integer
一个子类,所以ClassCastException
一个ClassCastException
exception。
Object i = Integer.valueOf(42); String s = (String)i; // ClassCastException thrown here.
这真的很简单:如果您试图将类A的对象types转换为类B的对象,并且它们不兼容,则会得到类转换exception。
让我们来思考一个类的集合。
class A {...} class B extends A {...} class C extends A {...}
- 您可以将这些东西中的任何一个转换为Object,因为所有Java类都从Objectinheritance。
- 你可以投B或C到A,因为他们都是“种”A
- 只有当真实物体是B时, 才可以将A物体的引用转换为B.
- 即使他们都是A,你也不能投B。
这是一个exception,如果你试图向下转换一个类,但实际上该类不是这种types的。
考虑这个问题:
对象 – >动物 – >狗
你可能有一个方法叫做:
public void manipulate(Object o) { Dog d = (Dog) o; }
如果用这个代码调用:
Animal a = new Animal(); manipulate(a);
它会编译得很好,但是在运行时你会得到一个ClassCastException
因为o实际上是一个Animal,而不是一个Dog。
在更高版本的Java中,除非您执行以下操作,否则会收到编译器警告:
Dog d; if(o instanceof Dog) { d = (Dog) o; } else { //what you need to do if not }
考虑一个例子,
class Animal { public void eat(String str) { System.out.println("Eating for grass"); } } class Goat extends Animal { public void eat(String str) { System.out.println("blank"); } } class Another extends Goat{ public void eat(String str) { System.out.println("another"); } } public class InheritanceSample { public static void main(String[] args) { Animal a = new Animal(); Another t5 = (Another) new Goat(); } }
在Another t5 = (Another) new Goat()
:你将得到一个ClassCastException
因为你不能使用Goat
创buildAnother
类的实例。
注意 :只有在类扩展父类并将子类转换为其父类时,转换才有效。
如何处理ClassCastException
:
- 试图将一个类的对象转换为另一个类时要小心。 确保新types属于其父类之一。
- 您可以通过使用generics来防止ClassCastException,因为generics提供了编译时间检查,可用于开发types安全的应用程序。
注意和其他的来源
你明白铸造的概念吗? 铸造是types转换的过程,这在Java中是非常常见的,因为它是一种静态types的语言。 一些例子:
将string“1”投射到一个int – >没有问题
将string“abc”投射到一个int – >引发一个ClassCastException
或者考虑使用Animal.class,Dog.class和Cat.class的类图
Animal a = new Dog(); Dog d = (Dog) a; // no problem, the type animal can be casted to a dog, because its a dog Cat c = (Dog) a; // raises class cast exception, you cant cast a dog to a cat
你正试图把一个对象当作一个不是的类的实例。 这大致类似于尝试按吉他上的延音踏板(钢琴有阻尼踏板,吉他没有)。
当您尝试将一个数据types的Object转换为另一个数据types的对象时,Java抛出类抛出exception。
Java允许我们将一种types的variables转换为另一种types的variables,只要在兼容的数据types之间进行转换即可。
例如,您可以将一个string作为对象进行强制转换,同样可以将一个包含string值的对象转换为一个string。
例
让我们假设我们有一个包含多个ArrayList对象的HashMap。
如果我们写这样的代码:
String obj = (String) hmp.get(key);
它会抛出一个类抛出exception,因为哈希映射的get方法返回的值将是一个Array列表,但是我们试图将其转换为String。 这会导致exception。
在Java中,我可以给你classcastException的一个很好的例子是使用“Collection”
List list = new ArrayList(); list.add("Java"); list.add(new Integer(5)); for(Object obj:list) { String str = (String)obj; }
上面的代码会在运行时给你ClassCastException。 因为你正试图将整数转换为string,这将抛出exception。
一旦您意识到JVM无法猜测未知,您可以更好地理解ClassCastException并进行投射。 如果B是A的一个实例,那么堆中的类成员和方法比A多。JVM不能猜测如何将A转换为B,因为映射目标较大,JVM不知道如何填充其他成员。
但是,如果A是B的一个实例,那么这将是可能的,因为A是对B的完整实例的引用,所以映射将是一对一的。
下面的伪代码将以更好的方式解释它。
if (object to be casted follows an "ISA" relationship with the classtype it is being casted to) { There will not be any exception } else { It will throw class cast exception. }