Java中编译器如何识别重写方法的返回类型是否兼容?
编译器判断重写方法返回类型兼容性的逻辑
首先明确前置规则:方法签名确实只包含方法名和参数列表,因此重写校验的第一步是先匹配签名,只有签名完全一致的子类方法才会进入返回类型兼容性校验环节,否则会被判定为方法重载或是语法错误。
主流面向对象编程语言(Java、C++、C#等)均支持协变返回类型特性,编译器的校验逻辑完全围绕该特性展开,具体步骤如下:
- 第一步:签名合法性校验
先比对子类方法和父类被重写方法的方法名、参数个数、参数类型、参数顺序是否完全一致,泛型场景下还要额外校验类型参数的上下界约束是否匹配,只有全部符合的才会被标记为重写候选方法。 - 第二步:返回类型兼容性校验
分两种场景做不同判断:- 若返回值为原始值类型(如Java的
int、char,C++的int、double等):要求返回类型完全相同,因为原始值类型不存在继承/子类型关系,无法做协变。例如父类方法返回int,子类重写方法就只能返回int,返回long、float都会被判定为不兼容。 - 若返回值为引用类型:要求重写方法的返回类型是被重写方法返回类型的可隐式向上转型的子类型。简单来说就是子类方法的返回值可以直接赋值给父类方法返回类型的变量,不需要做强制类型转换。比如父类方法返回
Number,子类可以返回Integer;父类方法返回List,子类可以返回ArrayList,均属于合法的协变场景。
- 若返回值为原始值类型(如Java的
可以参考如下Java代码示例理解:
// 父类 class Animal { public Animal getSelf() { return this; } public Number getWeight() { return 10.5; } } // 子类 class Cat extends Animal { // 合法,Cat是Animal的子类型,符合协变规则 @Override public Cat getSelf() { return this; } // 合法,Integer是Number的子类型,符合协变规则 @Override public Integer getWeight() { return 12; } /* 以下写法会直接报编译错误:返回类型不兼容 @Override public String getWeight() { return "12"; } */ }
如果是泛型返回类型的场景,编译器还会额外校验泛型参数的边界是否兼容:比如父类返回List<? extends Number>,子类可以返回List<Integer>,但不能返回List<String>。
内容的提问来源于stack exchange,提问作者Zarar Mahmud
相关产品推荐
相关产品推荐

