向上转型无需强制类型转换,因编译器可静态确认子类到父类赋值安全;向下转型必须显式强转并配合instanceof检查,否则运行时抛ClassCastException。
向上转型为什么不需要强制类型转换
因为编译器在编译期就能确认子类对象赋值给父类引用是安全的——子类一定拥有父类的全部公开成员,不会出现调用不存在方法的情况。
合法,
能正常调用(哪怕实际执行的是
),这是多态的基础。
常见错误现象:
编译通过但运行时抛出
——转型前没做类型检查。
向上转型本质是引用类型的“窄化”:把具体类型(
)视作更宽泛类型(
),不丢失信息
编译器只校验声明类型是否兼容,不关心运行时真实类型
所有继承关系中,子类 → 父类自动转型,无需
语法
向下转型必须显式强转且要防
因为父类引用可能指向任意子类实例,甚至就是父类自身实例。JVM 不允许你凭空假设一个
引用背后一定是
,所以必须用
显式告诉虚拟机“我确定它是”,否则编译不通过;而一旦判断错误,就在运行时崩。
使用场景:需要调用子类特有方法,比如
,但手头只有
类型的引用。
立即学习
“
Java免费学习笔记(深入)
”;
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
必须配合
使用:
在 Java 14+ 支持模式匹配:
,自动完成转型并绑定变量
避免对
做
判断(结果恒为
,但不会 NPE)
多态方法调用靠虚方法表(vtable),不是靠转型
转型本身不改变对象内存布局,也不触发任何方法重写逻辑。真正决定调用哪个
的,是对象实际类型对应的虚方法表指针——每个类加载时 JVM 就构建好它的 vtable,里面存着该类所有可被重写的方法的实际入口地址。
性能影响:虚方法调用比静态/私有方法慢一点点(现代 JVM 有内联优化,差距极小),但这是多态的必要开销。
—— 查的是
的 vtable,跳转到
—— 查的是
的 vtable,跳转到
转型(无论上下)只是改变编译期类型检查和引用视角,不影响 vtable 查找过程
泛型擦除让
无法直接转型为
这是容易被忽略的“伪多态”陷阱。虽然
是
的子类,但
和
在运行时都被擦除为原始类型
,二者没有继承关系,强制转型会绕过泛型检查,导致后续
破坏类型安全。
正确做法是用通配符:
接收
,但它只允许读、不允许写(除
)。
错误示例:
—— 编译警告,运行时可能出错
安全替代:
,此时
返回
,但不能
如果真要写,用
,它允许添加
及其子类,但读出来是
转型本身不改变对象,只改变你“怎么看待它”。最常翻车的地方,不是不会写
,而是忘了问一句:“我凭什么认定它就是
?”
Animal a = new Dog()a.speak()Dog.speak()Animal a = new Animal(); Dog d = (Dog) a;ClassCastExceptionDogAnimal(Parent)ClassCastExceptionAnimalDog(Dog)Dog.bark()Animalinstanceofif (a instanceof Dog) { Dog d = (Dog) a; d.bark(); }instanceofif (a instanceof Dog d) { d.bark(); }nullinstanceoffalsespeak()Animal a = new Dog(); a.speak();DogDog.speak()Animal a = new Cat(); a.speak();CatCat.speak()ListListDogAnimalListListListadd(new Cat())List extends Animal>ListnullList dogs = new ArrayList<>(); List animals = (List) dogs; List extends Animal> safe = dogs;safe.get(0)Animalsafe.add(...)List super Dog>DogObject(Dog)Dog