Java : 多态,包装类的面试题:

Java : 多态,包装类的面试题:

在这里插入图片描述


每博一文案

有人说:小孩子才会仰天大哭,成年人的世界早就调成了静音模式,连崩溃也很懂事。
一路走来,我们一边受伤,也一边变得更坚强,慢慢的不再逢人就笑了,也不再期待谁的拥抱了。
我们习惯了一边打伞一边奔跑,在没人帮的时候,学会了独立,也在没人疼的时候,学会了自愈,明白了
想要去的地方,要自己走过去。想要的安全感也只能自己给,没有人生来坚强,只是后来学会了隐藏。
听过这样的一句话,时间顺流而下,生活逆水行舟,人生不可能一帆风顺,经历过磨难在所难免。
很多时候,我们都是逼自己穿起了戎装,硬着头皮去面对,不愿在人面前露出一丝一毫的脆弱。
仿佛一旦示弱,就会被生活生吞活剥,其实这个世界上没有那么多的感同身受,有的,只是冷暖自知,你的眼泪
只有关心你的人心疼,你的笑容,也只有在乎你的人中重视,所以不要把硬抗伪装成坚强,把困难修饰成笑脸,
只为了让自己看起来还算体面。
你的眼睛很漂亮,看错人没关系,爱流眼泪也没关系,一定会有人时如珍宝。
愿你往后的每一次坚强都不是硬抗。
                                                   ——————   一禅心灵庙语


1. 多态面试题

如下代码,其中的 atest.add(1,2,3); 语句执行的是 其中的 add()的哪个方法 ,执行结果又是什么???

package blogs.blog1;

public class Topic {
    public static void main(String[] args) {
        Test test = new Test2();  // 多态
        test.add(1,2,3);  
    }

}


class Test{
    public void add(int a,int...arr) {
        System.out.println("Test:add");
    }
}


class Test2 extends Test{
    public void add(int a,int[]arr) {
        System.out.println("Test2:add");
    }
    
    public void add(int a,int b,int c) {
        System.out.println("Test: a, b, c");
    }
}

在这里插入图片描述

解析:

执行的是 Test2 子类中重写的 add() 的方法。

因为: 对于 public void add(int a,int...arr)public void add(int a,int[]arr) 是一样的参数列表,

最后的可变参数 int…arr ,本身就是旧的数组 int[]arr ,继承关系:方法名一样,参数列表一样,符合继承重写条件,在加上继承的多态所以调用的是子类重写的 public void add(int a,int[] arr) 方法


修改一下:

如下 其中的 test2.add(1,2,3); 调用的又是哪个类中的哪个方法,执行的结果又是什么???

package blogs.blog1;

public class Topic {
    public static void main(String[] args) {
        Test test = new Test2();  // 多态
        Test2 test2 = (Test2)test;
        test2.add(1,2,3);
    }

}


class Test{
    public void add(int a,int...arr) {
        System.out.println("Test:add");
    }
}


class Test2 extends Test{
    public void add(int a,int[]arr) {
        System.out.println("Test2:add");
    }

    public void add(int a,int b,int c) {
        System.out.println("Test: a, b, c");
    }
}

在这里插入图片描述

解析:

test2.add(1,2,3); 是通过 这行代码 : Test2 test2 = (Test2)test;强制向下转型得到的,一个子类 Test2 对象的

所以这里 add(1,2,3) 调用的是 Test2 子特有的 public void add(int a,int b,int c) 三个形参从方法。


2. 三目运算符

观察如下代码,思考运行结果是:什么 ???

public class Topic {
    public static void main(String[] args) {
        Object object = true ? new Integer(1) : new Double(2.0);
        System.out.println(object);
    }
}

在这里插入图片描述

解析:

因为对于运算: +,-,*,/ 都是需要保证两者之间是同一个数据类型才行的,如果不是的话,其中一个不符合的变量会自动提升到类型一致的情况后,再进行运算的。

同理 ? 三目运算符也是运算符,同样需要保证两者变量的一致性,所以 Integer 会自动提升至 Double 类型后,再进行运算。

结果就是 Double 类型的了,为 1.0


3. 包装类中的 Integer 缓存问题

请仔细阅读如下代码,查看执行的结果是 : ???

public class Topic {
    public static void main(String[] args) {
        Integer i = new Integer(1);
        Integer j = new Integer(1);
        System.out.println("i == j: "+(i == j));

        Integer m = 1;
        Integer n = 1;
        System.out.println("m == n: "+(m == n));

        Integer x = 128;
        Integer y = 128;

        System.out.println("x == y: "+(x == y));

    }
}

在这里插入图片描述

解析:

  • 第一个 i == j 的结果是 : false。

因为我们使用的是 == 操作符,再加上使用的是 new 创建的实例对象,对于引用类型(除了String ) 比较的是 两个变量的地址是否相等 ,很显然地址是不同的。结果是 false

  • 第二个 m == n 的结果是:true 。

因为不是 new 创建的实例对象,而是通过自动装箱到包装类当中的,使用 == 比较的是两个变量的数值内容是否相等,很显然都是 1,相等,结果是 true;

  • 第三个 x == y 的结果是: false。

因为什么呢:这里我们使用和上面第二个自动装箱的方式,并没有 new ,按道理来说,应该也是比较的是两个变量的数值内容,返回的也应该是 true 才对,为什么返回的却是 false;

原因是:

Integer 内部定义了 IntegerCache 结构,IntegerCache 中定义了 Integer[] 保存了 从 -128~127 范围的整数,如果我们使用自动装箱的方式,给Integer赋值的范围在 -128~127范围内时,可以直接使用数组中的元素,就不用 new 了,从而提高效率。

而这里的 128 自动装箱不在该[-128~127]的范围内,数组中没有该元素,就会 new 一个对象,存储该数值 128 ,new 一个实例对象,再 == 操作符,引用类型的比较的就不再是变量的数值内容了,而是变量的地址了,显然地址是不相同的。返回 false

我们在从源码上分析

private static class IntegerCache {
        static final int low = -128;
        static final int high; 
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

从源码上我们可以到 low 是为 -128high 是为 127 ,我们在通过获取到的信息阅读如下代码


public static Integer valueOf(int i) {
    // low = -128 , high = 127
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

以发现, 当 i >= -128 && i <= 127 的时候,在该范围内时,取值是在IntegerCache.cache[] 数组中取的数值的,并不是 new 来的,在该范围内取的数值的来源是相同的,自然也就是会相等的,但是当需要取的值是超出该范围[-128~127]的时候,是return new Integer(i); 创建一个新的实例对象来的。

而在引用类型中的 == 等号,比较的就并不是数值了,而是其引用对象的地址,所以超过该范围的取值,比较时是地址,不是数值,结果就可能不相等了。


我们再比较 127 自动装箱看看,如下代码

public class Topic {
    public static void main(String[] args) {
        Integer x = 127;
        Integer y = 127;
        System.out.println("x == y: "+(x == y));
    }
}

在这里插入图片描述

在该 [-128~127]的数组范围内,从IntegerCache.cache[] 数组中取数值,不是 new 出来的引用类型,== 操作符比较的就是两个变量的值了。

4. 总结:

  1. 对于 public void add(int a,int...arr)public void add(int a,int[]arr) 是一样的参数列表,
  2. 对于运算: +,-,*,/ 都是需要保证两者之间是同一个数据类型才行的,如果不是的话,其中一个不符合的变量会自动提升到类型一致的情况后,再进行运算的。**?**三目运算符也是一样的
  3. 注意对于 Integer 包装类,自动装箱的数值如果是在 [-128~127] 范围内的话,是从 IntegerCache.cache[] 数组中取值,超过该范围的数值就是 new 创建一个实例对象,保存了。

5. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值