• Java基础


    Java基础

    1. i++++i,在字节码中如何体现的

    • i++ :先读取i的值,然后在将本地变量表中的i增加1
      • int b = a++在字节码中的表现,假设a在本地变量表中的index是1,b的index是2
        1. iload_1 //先读取a的值,放入栈顶
        2. iinc 1 by 1 // iinc,修改本地变量的值,第一个1是变量在本地变量表中的的下标,后一个1是增加的值
        3. istore_2 // 将栈顶元素赋值给本地变量表中的第二个变量,也就是b
    • ++i :先将本地变量表中的i值增加1,然后在读取i的值
      • int b = ++a在字节码中的表现
        • iinc 1 by 1
        • iload_1
        • istore_2

    2. java的自动装箱与拆箱

    • Java的自动装箱拆箱其实就是Java的语法糖,简化代码.实际上在编译阶段JVM已经自动将类型转换写入到了字节码中. 装箱时自动调用Integer.valueOf(int),拆箱时调用Integer.intValue()
    • Integer a = 6在字节码中的表现,假设a在本地变量表中的index为1
      • sipush 6 // 将int型6压入栈顶
      • invokestatic #2 <java/lang/Integer.valueOf> // 调用静态方法Integer.valueOf(6)
      • astore_1
    • int b = a在字节码中的表现,a的index为1,值为Integer类型的6,b的index为2
      • aload_1 //将a压入栈顶
      • invokevirtual #3 <java/lang/Integer.intValue> // 调用实例方法a.intValue()
      • astore_2

    3. Object类中的equals和hashCode方法的作用?什么时候要重写hashCode?

    • Object中的equals和hashCode方法
      • equals:直接比较两个对象地址是否相同
      • hashCode:native方法,根据对象地址算出一个hash值
    • 为啥修改equals的时候要同时修改hashCode?

    因为在使用散列表的情况下,比如HashMap,HashSet
    会先根据hashCode来计算对象在散列表中的位置,
    如果修改了equals的逻辑,但是没有修改hashCode,就可能造成错误.
    比方说现在有个Ball类,它有个color属性,我们重写了equals方法,只要color相同就行,我们将各种颜色的球都放入HashSet中,要求如果HashSet中不能有相同颜色的球.
    如果没有重写hashCode方法,那么hashCode返回的是对象内存地址相关的值,不同的对象肯定不相同
    HashMap在put时,会根据hash值算出它在table中的index,如果当前table的index位置没有数据,就直接放入,如果有数据,依次遍历这些数据,判断原有数据是否等于要put的对象,如果等于的话,根据需要替换对象或者不替换.
    关键就在这个判断原有数据是否等于要加入的数据:
    hashMap中先判断两个数据的hash值是否相同,如果不相同,就认为这两个对象不相同
    只有hash值相同了,才会去调用equals看是否相同.
    p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))
    p表示hashMap中现有的数据,
    首先判断要put的数据的hash值是否等于现有的数据,如果不等于,就认为put数据和原有数据不相等.

    • HashMap中对hashCode的运用:

    在HashMap内部维护了一个table数组,
    对象通过一定的hash算法确定在table中的index
    如何获得对象放入HashMap中table的index:
    1, 调用自身的hashCode获取一个hash值
    2, hash ^ (hash>>>16) 获取对象在HashMap中的hash值
    3, index = (length-1) & hash
    通常HashMap长度不会很大,使用(length-1) & hash获取到index的时候,
    大多只有hash低位的在参与运算,决定index的值,
    而通过第2步,hash值与自身右移16位后亦或,将hash值的高位信息融入到低位,
    这样就能减小hash冲突的概率

    3-1. Runnable和Callable接口

    • 实现方法:
      • Runnable需要实现public abstract void run();
      • Callable需要实现V call() throws Exception;
    • 相同之处:
      • Runnable和Callable都是接口,都是为了要执行某一任务
    • 不同之处:
      1. call方法有返回值,而run没有返回值
      2. call方法能够抛出checked exception,而run不行
      3. Callable和Runnable都可以用于Executors,而Thread类只支持Runnable
        • Future接口,一般都是取回Callable执行状态用的,主要方法有:
          • cancel,取消Callable的执行,当Callable还没有完成时
          • get,获取Callable的返回值
          • isCancled,判断是否取消了
          • isDone,判断是否完成

    3-2. synchronized锁升级过程


  • 相关阅读:
    ie浏览器设定主页修改
    诺基亚5800通讯录倒入到dopod的联系人中去的解决办法
    局域网中根据IP地址反查主机的名称(C#)
    U盘维修
    查找xml文件中某接点的值
    如何更改任务栏颜色
    如何给一个div赋值(改变div原来的值)
    explicit的作用
    重建二叉树
    常函数
  • 原文地址:https://www.cnblogs.com/Serenity1994/p/12497703.html
Copyright © 2020-2023  润新知