Java中的ClassCastException和解析
时间:2020-01-09 10:34:58 来源:igfitidea点击:
如果尝试将对象强制转换为非实例类型,则抛出Java中的ClassCastException。
例如,考虑以下代码
Object l = Long.valueOf("120"); System.out.println(l); //120 Number n = (Number)l; System.out.println(n); // 120
在这里,我们有一个存储在Object类型中的Long值引用。稍后我们将其强制转换为Number,因为Number是Long的超类(Long也是Number类型),因此可以毫无问题地将Long转换为Number。
现在我们对其进行更改,以便将Long值的引用存储在Number类型中。后来我们将其转换为Integer。
Number l = Long.valueOf("120"); System.out.println(l); Integer i = (Integer)l; System.out.println(i);
输出:
120 Exception in thread "main" java.lang.ClassCastException: class java.lang.Long cannot be cast to class java.lang.Integer
由于Long不是Integer类型,因此将类型转换为Integer会导致java.lang.ClassCastException。 Long和Integer均为Number类型,但不能在Integer和Long之间进行强制转换。
当我们具有继承性(父子类)并使用运行时多态性(其中超类可以存储对子类的引用)时,在这种情况下,当我们进行类型转换以将一种类型的对象转换为另一类ClassCastException时,将被抛出。这是要理解何时抛出ClassCastException的另一类层次结构。
Class A { .. } class B extends A { ... } class C extends A { ... }
A是B类和C类的父类。使用此层次结构,我们具有以下铸造规则。
- 我们可以将A,B或者C中的任何一个实例转换为Object,因为Object是Java中所有类的超类。
- 我们可以将B或者C的实例强制转换为A,因为B和C的类型也均为A。
- 如果A持有对B类型实例的引用,则可以将其仅强制转换为B而不是C。对于C类型实例也是如此。这样就可以了。
A a = new B(); System.out.println((B)a);
不是这个
System.out.println((C)a);
再次,这没关系
A a = new C(); System.out.println((C)a);
不是这个
System.out.println((B)a);
- 尽管B和C均为A类型,但它们彼此不兼容,因此无法从B转换为C或者从C转换为B。
Java ClassCastException层次结构
如果为RuntimeException类型,则为ClassCastException,这表示它是未经检查的异常。
Java中ClassCastException的异常层次结构如下:
如何避免ClassCastException
通过使用通用Collections和随后的类型安全,已经避免了ClassCastException的一个主要原因。
避免ClassCastException的另一种方法是在转换对象之前使用instanceof运算符确定对象的兼容性。
class B extends A { } class C extends A { } public class A { public static void main(String[] args) { A obj1 = new B(); A obj2 = new C(); if(obj2 instanceof B) { System.out.println((B)obj2); } else { System.out.println("Not compatible"); } if(obj1 instanceof B) { System.out.println((B)obj1); } else { System.out.println("Not compatible"); } } }
输出:
Not compatible Hyman@theitroad