向上转型是子类对象赋值给父类引用,编译器自动允许,本质是安全收缩;向下转型需显式强转并用instanceof检查以防classcastexception;tostring、equals、hashcode重写后仍遵循多态。

什么是向上转型?它为什么不是“强制类型转换”
向上转型是子类对象赋值给父类引用,编译器自动允许,不加 cast 也合法。它本质是“安全收缩”——用父类视角看子类实例,只暴露父类定义的接口。
常见错误现象:NullPointerException 或调用不到子类特有方法,其实不是转型出错,而是误以为转型后能直接用子类方法。
- 必须通过父类声明的方法访问行为,哪怕子类重写了(多态生效)
- 不能直接调用子类新增的字段或方法,比如
Student继承Person,转成Person p = new Student()后,p.getStudentId()编译失败 - 转型本身不改变对象实际类型,
instanceof仍返回true,getClass()还是子类
向下转型什么时候必须写 (SubType)?怎么避免 ClassCastException
向下转型是把父类引用“还原”为子类类型,编译器不信任你,必须显式加括号强转。但运行时若对象实际不是那个子类,就抛 ClassCastException。
典型使用场景:从集合里取出 Object 或泛型擦除后的父类引用,需要恢复具体类型做操作;或者框架回调传入父类,但你知道内部实为某个子类。
立即学习“Java免费学习笔记(深入)”;
- 务必先用
instanceof检查,再转型——不是“可选习惯”,是防止崩溃的硬性步骤 - Java 14+ 可用模式匹配简化:
if (obj instanceof Student s) { s.getStudentId(); },s已是转型后变量 - 泛型集合如
List<person></person>存了Student,取出来仍是Person类型,转型不可少
toString()、equals()、hashCode() 的重写和多态关系
这三个方法默认来自 Object,一旦子类重写,向上转型后调用的仍是子类版本——这是多态最常被忽略却最实用的地方。
容易踩的坑:重写 equals() 时不遵守对称性/传递性,或没重写 hashCode(),导致放进 HashSet 出现重复或找不到。
-
toString()重写后,哪怕用Person p = new Student(),p.toString()输出的仍是Student自定义格式 -
equals()必须用instanceof判断类型,再强转比较字段;否则子类对象和父类对象互等可能失败 - 如果子类添加了新字段参与逻辑判断,
hashCode()也得包含它,否则哈希表行为异常
为什么 static 方法和 final 方法不参与多态?
因为它们在编译期就绑定了调用目标,不走运行时动态分派。所谓“重写” static 方法,其实是子类定义了一个同名新方法,跟父类无关。
性能影响很小,但语义混淆代价大:看起来像多态,实际不是,容易在调试时误判执行路径。
- 调用
Parent.staticMethod()或Child.staticMethod(),取决于引用类型,不是实际对象类型 -
final方法禁止重写,自然无法被动态绑定;JVM 可能内联优化,但和多态机制无关 - 构造器也不能多态——子类构造器第一行默认或显式调用
super(),但那只是初始化链,不是方法分派
static、非 private、非 final 的实例方法——其他都是干扰项。








