关于里氏替换原则, 子类在同名方法中,放大或者缩小输入参数类型的研究

关于int,Integer 作为传入参数,子类方法调用的问题

之前一道面试题,把我搞蒙蔽了。 形如下列代码(相关问题和答案写在注释里面了)

package groupId.test;

/**
 * 关于传入int和Integer参数,调用有啥区别?
 * 答: 对于 子类Son来说,因为继承的关系,同时 存在 M(int n),M(Integer n) 两个方法,
 * 根据传入的的参数来调用不同的方法。
 * 对于 F f = new Son() 这种情况下,对象f完成上转型,不在视作Son类。
 * 此时父类F只有一个方法 M(int n) 或者 M(Integer n),
 * 无论传入int或者Integer,它都先执行拆装箱,再传入对应的父类方法FM中。
 */

public class temp {
    public static void main(String[] args) {
        Son s = new Son();
        Father f = new Son();
        Son2 s2 = new Son2();
        Father2 f2 = new Son2();
        // 子类//拆箱
        s.doSomething(new Integer(1)); //父类 被执行。。。。1
        s.doSomething(1); //子类 被执行。。。。。1
        f.doSomething(new Integer(1)); //父类 被执行。。。。1
        f.doSomething(1); //父类 被执行。。。。1

        // 子类//装箱
        s2.doSomething(new Integer(1)); //子类2 被执行。。。。。1
        s2.doSomething(1); //父类2 被执行。。。。1
        f2.doSomething(new Integer(1)); //父类2 被执行。。。。1
        f2.doSomething(1); //父类2 被执行。。。。1
    }
}

class Father{
    public void doSomething(Integer n){
        System.out.println("父类 被执行。。。。"+n);

    }
}

class Son extends Father{
    //拆箱
    public  void doSomething(int n){
        System.out.println("子类 被执行。。。。。"+n);

    }
}


class Father2{
    public void doSomething(int n){
        System.out.println("父类2 被执行。。。。"+n);
    }
}

class Son2 extends Father2{
    //装箱
    public  void doSomething(Integer n){
        System.out.println("子类2 被执行。。。。。"+n);
    }
}

索性,扩展一下:

放大或缩小父类的参数类型(即用它的父类或者子类做参数)

package groupId;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class LspOverriedOrOverwriteTest {
    public static void main(String[] args) {
        //invoke1();//父类1 被执行。。。。
        //invoke11();//父类1 被执行。。。。 放大输入类型参数,重载,调用的还是父类的方法
        //invoke2();//父类2 被执行。。。。。
        //invoke21();// 子类21 被执行。。。。缩小输入类型参数, 覆写
        // 子类21 缩小参数输入范围,子类重载了父类方法,子类行为不同于父类,在设计角度父类无法预料子类的行为,
        // 这是非常危险的

        //invoke3(); //父类3 被执行。。。。
        //invoke31();//子类31 被执行。。。。。 缩小或等于输出类型参数,  此时相当于覆写了父类方法
        //invoke4(); //父类4 被执行。。。。
        //invoke41(); //父类4 被执行。。。。//放大输出类型参数,编译不通过 ,所以执行的还是父类的方法
        //invoke5(); //父类5 被执行。。。。1
        //invoke51();//输入类型 子类参数 Integer,"装箱",,父类5 被执行。。。。1 (子类传入 1)    子类51 被执行。。。。。1 (子类传入new Integer(1))

        //invoke6(); //父类6 被执行。。。。1
        //invoke61();//输入类型 子类 参数 int,"拆箱",子类61 被执行。。。。1 (子类传入 1)    父类5 被执行。。。。。1 (子类传入new Integer(1))
        //invoke7(); //父类7 被执行。。。。1
        //invoke71(); //父类7 被执行。。。。1 输出值 "拆箱",编译不通过 即 方法名,参数类型,个数,位置相同,不允许出现返回值不同的方法
        //invoke8(); //父类8 被执行。。。。1
        //invoke81(); //父类8 被执行。。。。1 输出值 "装箱",编译不通过 即 方法名,参数类型,个数,位置相同,不允许出现返回值不同的方法

        invoke9(); //父类9 被执行。。。。
        invoke91(); //父类9 被执行。。。。 在子类的输出参数缩小,输入参数放大的情况下,执行父类方法,{重载}

        /**
         * 总结,针对输出参数,子类的返回值在只能缩小或等于父类的情况下,整体上 子类是趋向于{覆写}父类方法的,
         * 所以一般返回值类型视作相同。
         * 针对输入参数,子类的输入参数在放大父类的情况下,或者多于父类同名方法的参数个数,或者参数位置调整情况,
         * 整体子类是{重载}的,
         * 子类调用父类的同签名方法,执行的是父类的方法,形如 father.dosomething(? supper Father T)
         *
         * 子类子类的输入参数在小于等于父类的情况下,{覆写} 父类方法
         *
         * 同时,1, int与Integer做两个测试; int与Integer作为输入参数,视作两个不同的参数类型
         * 不会收到 jvm 默认拆装箱的影响, 同样 作为返回类型 他们不能同时存在子类相同方法名上,编译会报错。
         * 又java规定 方法名,参数类型,个数,位置相同,不允许出现返回值类型不同的方法,故作为参数时,
         * int 与Integer是两个完全不同的参数,其他原始类型与包装类型 类似。
         * 补: F f = new Son() 这种情况下:若父类F只有一个方法 FM(int n) 或者 FM(Integer n),
         * 无论传入int或者Integer,它都先执行拆装箱,再传入对应的父类方法FM中。
         * 2,在子类的输出参数缩小,输入参数放大的情况下:
         *  invoke91() 执行父类方法,{重载} . 说明 一般情况下,无需考虑返回类型,子类的行为
         *  取决于输入参数的类型, 输入参数类型>父类的,{重载},调用父类方法
         *  输入参数<= 父类的,{覆写} ,调用子类方法、
         *  
         *  因为输出参数>父类的,编译报错,所以不考虑 子类的输出参数放大,输入参数缩小的情况。
         */
    }
    public static void invoke1(){
        //父类存在的地方,子类就应该能够存在
        Father1 f = new Father1();
        HashMap map = new HashMap();
        f.doSomething(map);
    }

    public static void invoke11(){
        //父类存在的地方,子类就应该能够存在
        Son1 f = new Son1();
        HashMap map = new HashMap();
        f.doSomething(map);
    }

    public static void invoke2(){
        //父类存在的地方,子类就应该能够存在
        Father2 f = new Father2();
        HashMap map = new HashMap();
        f.doSomething(map);
    }
    public static void invoke21(){
        //父类存在的地方,子类就应该能够存在
        Son2 f = new Son2();
        HashMap map = new HashMap();
        f.doSomething(map);
    }

    public static void invoke3(){
        //父类存在的地方,子类就应该能够存在
        Father3 f = new Father3();
        HashMap map = new HashMap();
        f.doSomething(map);
    }
    public static void invoke31(){
        //父类存在的地方,子类就应该能够存在
        Son3 f = new Son3();
        HashMap map = new HashMap();
        f.doSomething(map);
    }

    public static void invoke4(){
        //父类存在的地方,子类就应该能够存在
        Father4 f = new Father4();
        HashMap map = new HashMap();
        f.doSomething(map);
    }
    public static void invoke41(){
        //父类存在的地方,子类就应该能够存在
        Son4 f = new Son4();
        HashMap map = new HashMap();
        f.doSomething(map); //放大输出类型参数,编译不通过 ,所以执行的还是父类的方法
    }


    public static void invoke5(){
        //父类存在的地方,子类就应该能够存在
        Father5 f = new Father5();

        f.doSomething(1);
    }
    public static void invoke51(){
        //父类存在的地方,子类就应该能够存在
        Son5 f = new Son5();
        HashMap map = new HashMap();
        f.doSomething(new Integer(1)); //装箱
        //f.doSomething(1); //装箱
    }

    public static void invoke6(){
        //父类存在的地方,子类就应该能够存在
        Father6 f = new Father6();

        f.doSomething(1);
    }
    public static void invoke61(){
        //父类存在的地方,子类就应该能够存在
        Son6 f = new Son6();
        HashMap map = new HashMap();
        //f.doSomething(new Integer(1)); //装箱
        f.doSomething(1); //装箱
    }

    public static void invoke7(){
        //父类存在的地方,子类就应该能够存在
        Father7 f = new Father7();

        f.doSomething(1);
    }
    public static void invoke71(){
        //父类存在的地方,子类就应该能够存在
        Son7 f = new Son7();
        HashMap map = new HashMap();
        //f.doSomething(new Integer(1)); //装箱
        f.doSomething(1); //装箱
    }

    public static void invoke8(){
        //父类存在的地方,子类就应该能够存在
        Father8 f = new Father8();

        f.doSomething(1);
    }
    public static void invoke81(){
        //父类存在的地方,子类就应该能够存在
        Son8 f = new Son8();
        HashMap map = new HashMap();
        //f.doSomething(new Integer(1)); //装箱
        f.doSomething(1); //装箱
    }



    public static void invoke9(){
        //父类存在的地方,子类就应该能够存在
        Father9 f = new Father9();
        HashMap map = new HashMap();
        f.doSomething(map);
    }
    public static void invoke91(){
        //父类存在的地方,子类就应该能够存在
        Son9 f = new Son9();
        HashMap map = new HashMap();
        f.doSomething(map); //放大输出类型参数,编译不通过 ,所以执行的还是父类的方法
    }



}
class Father1{
    public Collection doSomething(HashMap map){
        System.out.println("父类1 被执行。。。。");
        return map.values();
    }
}
class Son1 extends Father1{
    //放大输入类型参数
    public Collection doSomething(Map map){
        System.out.println("子类11 被执行。。。。。");
        return map.values();
    }
}

class Father2{
    public Collection doSomething(Map map) {
        System.out.println("父类2 被执行。。。。。");
        return map.values();
    }
}
class Son2 extends Father2{
    //缩小输入参数范围
    public Collection doSomething(HashMap map){
        System.out.println("子类21 被执行。。。。");
        return map.values();
    }
}

class Father3{
    public Iterable doSomething(Map map){
        System.out.println("父类3 被执行。。。。");
        return  map.values();
    }
}
class Son3 extends Father3{

    //缩小或等于输出类型参数
    public  Collection doSomething(Map map){
        System.out.println("子类31 被执行。。。。。");
        return map.values();
    }
}

class Father4{
    public Collection doSomething(Map map){
        System.out.println("父类4 被执行。。。。");
        return  map.values();
    }
}
class Son4 extends Father4{
    //放大输出类型参数,编译不通过
    /*public Iterable doSomething(Map map){
        System.out.println("子类41 被执行。。。。。");
        return map.values();
    }*/

}


class Father5{
    public Collection doSomething(int n){
        System.out.println("父类5 被执行。。。。"+n);
        return  new HashMap().values();
    }
}
class Son5 extends Father5{

    //装箱
    public  Collection doSomething(Integer n){
        System.out.println("子类51 被执行。。。。。"+n);
        return new HashMap().values();
    }
}
class Father6{
    public Collection doSomething(Integer n){
        System.out.println("父类6 被执行。。。。"+n);
        return  new HashMap().values();
    }
}
class Son6 extends Father6{

    //拆箱
    public  Collection doSomething(int n){
        System.out.println("子类61 被执行。。。。。"+n);
        return new HashMap().values();
    }
}

class Father7{
    public Integer doSomething(Integer n){
        System.out.println("父类7 被执行。。。。"+n);
        return  n;
    }
}
class Son7 extends Father7{

    //输出值 拆箱,编译不通过 即 方法名,参数类型,个数,位置相同,不允许出现返回值不同的方法
    /*public  int doSomething(Integer n){
        System.out.println("子类71 被执行。。。。。"+n);
        return n.intValue();
    }*/

    //输出值 不同,编译不通过 即 方法名,参数类型,个数,位置相同,不允许出现返回值不同的方法
    /*public  boolean doSomething(Integer n){
        System.out.println("子类71 被执行。。。。。"+n);
        return n.intValue();
    }*/
}


class Father8{
    public int doSomething(Integer n){
        System.out.println("父类8 被执行。。。。"+n);
        return  n.intValue();
    }
}
class Son8 extends Father8{

    //输出值 装箱,编译不通过, 即 方法名,参数类型,个数,位置相同,不允许出现返回值不同的方法
    /*public  Integer doSomething(Integer n){
        System.out.println("子类81 被执行。。。。。"+n);
        return n.intValue();
    }*/
}


class Father9{
    public Iterable doSomething(HashMap map){
        System.out.println("父类9 被执行。。。。");
        return  map.values();
    }
}
class Son9 extends Father9{
    //测试 子类的输出参数缩小,输入参数放大的情况
    public  Collection doSomething(Map map){
        System.out.println("子类91 被执行。。。。。");
        return map.values();
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值