首先,你代码一里面的表现是符合你预期的,并且这个错误也正是反映了你标题问题的答案:父类实例不允许传入用子类声明的方法参数中,至于为什么,其实简单来说就是子类一定包含父类所有的特性,但反过来是不成立的,所以当这个参数传入方法使用时,任何针对子类方法和属性的操作都无法保证同样适用于父类对象,但反过来是可以的,这也是为什么用父类声明的参数子类可以传入的原因。
回到你的代码二,为什么代码二可以没问题呢?主要是因为范型的原因,首先,你的compare方法之所以可以声明成接受Integer,是因为接口Comparator上有范型声明,子类继承时声明T类型为Integer,所以compare方法从接受T参数变成Integer参数,这也是范型最基本的应用场景。那既然声明了T为Integer为什么使用时传入Object还不出错呢,其实这个代码有一点小问题,问题在于less方法的第一个参数-Comparator,这个参数没有范型声明,没有范型声明就意味着范型校验丢失,这个又要回到Java范型的特性上,Java为了保持代码向前兼容,范型其实是带有妥协性的,这个范型不是bytecode级别的,而是编译器级别的,就是说,这个范型只会在编译器阶段验证,运行期就不会再有范型校验了,所以当less第一个参数Comparator没有范型声明时,范型校验就已经被抛弃了,Java会用最原始的默认类型参数去运行compare函数,就是Object类型,所以这个代码就不出错了。所以你看那个截图,less第一个参数下方是有warning波浪线的,其实就是范型校验丢失。
为了加深理解,你可以尝试把less方法第一个参数加上范型校验Comparator,这时你就能看到红彤彤的报错信息了。