美文网首页君临天下-Java
Java面试题(二)

Java面试题(二)

作者: 老荀 | 来源:发表于2020-04-23 10:38 被阅读0次

    本实验平台主要是基于本人的MacbookPro,之后会考虑测试其他操作系统版本
    基于jdk1.8,HotSpot
    macOS Catalina 10.15
    内存 8 GB 2133 MHz LPDDR3

    $ uname -a
    Darwin MacBook-Pro.local 19.0.0 Darwin Kernel Version 19.0.0: Wed Sep 25 20:18:50 PDT 2019; root:xnu-6153.11.26~2/RELEASE_X86_64 x86_64
    $ java -version
    java version "1.8.0_181"
    Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
    Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
    

    实验下来的正确答案已用粗斜体表示

    1

    float a = 0.125f; double b = 0.125d; 
    System.out.println((a - b) == 0.0);
    

    代码的输出结果是什么?
    A. true
    B. false


    二进制究竟如何表示整数和浮点数

    这道题解释起来会牵涉到怎么用二进制表示小数,小数部分不停的乘以2,取整数部分作为二进制数位
    0 | 0.125 * 2 = 0.25
    0 | 0.25 * 2 = 0.5
    1 | 0.5 * 2 = 1
    结合整数部分就是 0.001
    是因为不停乘以2之后,小数部分就消失了,无论是单精度还是双精度都是一样,答案才会是true
    如果题目中的0.125换成0.124或者其他,就会是false
    以0.124举例
    0 | 0.124 * 2 = 0.248
    0 | 0.248 * 2 = 0.496
    0 | 0.496 * 2 = 0.992
    0 | 0.992 * 2 = 1.984
    1 | 0.984 * 2 = 1.968
    1 | 0.968 * 2 = 1.936
    1 | 0.936 * 2 = 1.872
    1 | 0.872 * 2 = 1.744
    1 | 0.744 * 2 = 1.488
    1 | 0.488 * 2 = 0.976
    0 | 0.976 * 2 = 1.952
    .
    .
    .
    可以看到0.124不管算多久都算不到小数部分消失(就算能算到小数部分消失,也早就超过了double所能存储的64位长度
    所以转换成二进制的0.124其实已经不等于数学中的0.124了,另外float和double的精度不同,4位和8位存储的区别导致截取之后结果变得不同,当然相减后不会等于0

    2

    double c = 0.8;
    double d = 0.7;
    double e = 0.6;
    // false
    System.out.println((c - d) == (d - e));
    

    那么 c-d 与 d-e 是否相等?
    A. true
    B. false


    这道题和上一道其实差不多一个意思,因为0.8、0.7、0.6用二进制都无法做到精确表示,自然在两两相减的结果是不一样的

    3

    System.out.println(1.0 / 0);
    

    1.0 / 0 首先会把除数向上转型成double,就变成了1.0 / 0.0,又由于浮点数表示问题,0.0在二进制中并不等于0,而是一个非常非常小的数,那任意数(不包括0或0.0)除以一个这样的数字都会得到(正负)无穷大
    在Double中也有两个成员定义成了这样

    public final class Double extends Number implements Comparable<Double> {
        public static final double POSITIVE_INFINITY = 1.0 / 0.0;
        public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
        ...
    }
    

    A. 抛出异常
    B. Infinity
    C. NaN

    4

    System.out.println(0.0 / 0.0);
    

    A. 抛出异常
    B. Infinity
    C. NaN
    D. 1.0

    5

    >> 和 >>> 的区别是?

    A. 任何整数没有区别
    B. 负整数一定没有区别
    C. 浮点数可以 >> 运算,但是不可以 >>> 运算
    D. 正整数一定没有区别


    以int为例,32位的int由于要表示正负,只能用最高位来表示,1为负数,0为正数,所以正整数只能表示最大为2^31 - 1

    以右移一位举例
    正整数
    16
    00000000 00000000 00000000 00010000
    >>1(整体右移,高位补0,符号位是不动的)
    8
    00000000 00000000 00000000 00001000
    >>>1(整体右移,高位补0,符号位是跟着一起动的)
    8
    00000000 00000000 00000000 00001000
    负整数
    -16
    11111111 11111111 11111111 11110000
    >>1(整体右移,高位补1,符号位是不动的)
    -8
    11111111 11111111 11111111 11111000
    >>>1(整体右移,高位补1,符号位是跟着一起动的,符号位是补0,所以对负数做无符号右移会变成正数)
    2147483640
    01111111 11111111 11111111 11111000
    

    6

    void f(String s) {
    }
    void f(Integer s) {
    }
    

    那么 f(null) 的会调用哪个方法?

    A. 前者
    B. 后者
    C. 随机调用
    D. 编译出错


    常量null,无法确定类型,所以这里编译会报错

    7

    void g(double d) {
    }
    void g(Integer i) {
    }
    

    那么 g(1) 的会调用哪个方法?
    A. 前者
    B. 后者
    C. 随机调用
    D. 编译出错


    Java方法重载的优先级是基本类型>引用类型的
    而基本类型中又以byte>short>int>long>float>double
    但是由于Java中字面数字常量默认就是int,所以byte和short基本不用讨论

    8

    String a = null; switch(a) 匹配 case 中的哪一项?

    A. null
    B. "null"
    C. 不与任何东西匹配,但不抛出异常
    D. 直接抛出异常

    9

    <String, T, Alibaba> String get(String string, T t) { 
        return string; 
    } 
    

    此方法:
    A. 编译错误,从左往右第一个 String 处
    B. 编译错误,T 处
    C. 编译错误,Alibaba 处
    D. 编译正确

    10

    HashMap 初始容量 10000 即 new HashMap(10000),当往里 put 10000 个元素时,需要 resize 几次?

    A. 1 次
    B. 2 次
    C. 3 次
    D. 0 次


    jdk1.8中的HashMap在new完之后是不会创建数组的,只有在第一次put元素的时候,才会进行数组的初始化,原因在源码中如下:

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                       boolean evict) {
            Node<K,V>[] tab; Node<K,V> p; int n, i;
            if ((tab = table) == null || (n = tab.length) == 0)
                n = (tab = resize()).length;
            ...
    }
    

    而又由于在创建HashMap的时候传入了构造器参数10000,在构建数组的时候会找到离10000最近的2的次方的数(16384),而HashMap的loadFactor没有被修改,默认为0.75f,所以下一次数组扩容的
    时机在16384*0.75=12288个元素的时候,而往Map中放10000个元素是达不到扩容的条件的。
    所以总结:
    只会在第一个元素被put的时候调用resize方法,之后就不会再调用

    相关文章

      网友评论

        本文标题:Java面试题(二)

        本文链接:https://www.haomeiwen.com/subject/zxdoihtx.html