01-知识点

一.hashCode、equals、== 的区别

1.java官方推荐重写equals方法时也要重写hashCode方法。  
  如果2个对象的equals比较时为true,则hashCode也要相同, 
  如果2个对象的hashCode相同时,equals方法可以不同,  
  因为hashCode底层是hash算法,hash算法的原则就是,如果2个输入相同,则输出一定相同;      
  反之如果输出相同,输入则未必相同,比如md5算法。如果输入不同,输出相同就叫做hash冲突。   
2.Object类中的hashCode、equals、toString 方法  
  hashCode:为native方法,具体实现和JVM厂商有关 
  equals: 用==比较的是内存地址值    
  toString: 打印的是类名和hashCode的16进制值  

3.个人理解:   
  (1):如果一个对象继承自Object类并且没有重写hashCode、equals、toString方法,   
  hashCode的返回值就是该对象的内存地址值,注意Object中的hashCode方法为native方法。具体实现和JVM厂商有关。   
  (2):hashCode是对象的hashCode方法,equals方法是对象的equals方法,== 比较的是对象的内存地址值。   

4.hashMap的存取原理:
   (1):hashMap要求key值不能相同,一般意义上比较相同应该是要比较equals方法,但是如果hashMap在    
    put元素的时候每个已经放入的key都和新key比较equals方法的话,当hashMap中键值对比较多情况下,
    效率非常低。既然是hashMap,底层实现其实是散列表,用的算法就是hash。当往hashMap中put值时:   
    首先计算key的hashCode方法的返回值,在散列表中查找有没有,没有,则为新元素,因为hashCode不同, 
    则equals一定不同,直接添加新元素;如果相同,再比较2个对应key的元素的equals方法,   
    如果相同,则为相同元素,替换value值,如果equals不同,则key不同,当新元素添加。     
    由上可知,hashMap中的所有key的equals方法一定不同,hashCode方法可能相同     

5.java中equals方法的几个特性    

自反性:对任意引用值X,x.equals(x)的返回值一定为true. 
对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true; 
传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true 
一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变 
非空性:任何非空的引用值X,x.equals(null)的返回值一定为false 

二.java 中基本类型的比较为值比较

java 中的基本类型为byte、short、char、int、long、float、double、boolean

三.java 中字符串的比较

1.java中的字符串为引用类型  
2.字面量定义的字符串都会进入常量池,只会实例化一份   
  比如:String s1="abc"; String s2="abc"; s1==s2 为true   
3.new关键字实例化字符串,每次都会重新创建   
  比如:String s1=new String("abc"); String s2=new String("abc"); s1==s2 为false

四.java中int、Integer的比较

1.int 之间是值比较  
2.int、Integer之间比较,先将Integer 拆箱,然后再进行值比较     
3.Integer 之间是引用类型比较的是地址值  
  注意:    (1)Integer会将-128到127之间的值进行缓存,直接从缓存中拿;   
             范围之外的则不会被缓存,会调用new Integer 进行实例化    
        (2)Integer a = 127,在编译的时候,被翻译成-> Integer b1 = Integer.valueOf(127);   
        //Integer会将-128到127之间的值进行缓存,直接从缓存中拿;
        //范围之外的则不会被缓存,会调用new Integer 进行实例化
        Integer integer4 = 127;
        Integer integer5 = 127;
        System.out.println("integer4==integer5----->"+(integer4==integer5));//true

        //-128到127之外,相当于new Integer(128)
        Integer integer6 = 128;
        Integer integer7 = 128;
        System.out.println("integer6==integer7----->"+(integer6==integer7));//false

五.java 字符串拼接效率StringBuilder>StringBuffer>String

1.StringBuilder 是线程不安全的,效率高;StringBuffer是线程安全的,效率低   
2.StringBuilder、StringBuffer都是可变的字符序列,类似于String的字符串缓存区; 
  而String 是不可变对象,在每一次改变字符串时都会创建新的String对象。  
3.所以一般拼接字符串时+号的效率没有StringBuffer高,但是比较方便     

六.HashMap、HashTable、ConcurrentHashMap的区别与联系

  1.线程安全角度 
    HashMap线程不安全,在单线程中使用,并发环境不应该使用  
    HashTable线程安全,单线程和并发环境都可以使用,其内部方法都用synchronized 加锁,重量级锁,效率低   
    ConcurrentHashMap线程安全,单线程和并发环境都可使用,其内部用分段锁实现,效率高   

  2.null 值 null 键  
    HashMap 允许null值null键 
    HashTable 不允许null值null键   
    ConcurrentHashMap 不允许null值null键    

   为什么?  
   可以这样解释:   

   因为hashtable,concurrenthashmap它们是用于多线程的,并发的 ,如果map.get(key)得到了null,    
   不能判断到底是映射的value是null,还是因为没有找到对应的key而为空,   
   而用于单线程状态的hashmap却可以用containKey(key) 去判断到底是否包含了这个null。   

  3.HashMap的负载因子是0.75   

  4.初始化HashMap的时候,如果明确知道容器容量时建议制定容量大小;  
    因为我们没有设置初始容量大小,随着元素的不断增加,HashMap会发生多次扩容,   
    而HashMap中的扩容机制决定了每次扩容都需要重建hash表,是非常影响性能的  

七.return 和 finally的执行先后问题

finally会在return执行之后,方法返回之前执行

理解: 
1.当执行return 的时候,编译器先根据方法的返回值类型,将其存入预留的内存里;  
然后再执行finally里的方法.finally执行完再从内存里取出返回值返回。方法调用完毕。  

2.finally里如果return语句的话,在执行finally过程中,   
 修改了返回值的值,如果返回值类型为基本类型,则最终返回值不会受影响。  
 如果返回值类型为引用类型,则会影响最终的返回值。  

 如果finally里也有return语句,最终返回值结果以finally里为准

代码示例

    private static int test(){
        try {
            System.out.println("e----->before");
            int a = 8/0;
            System.out.println("e----->after");
            return 1;
        }catch (Exception e) {
            System.out.println("catch");
            return 2;
        }finally{//这里finally里直接return 0 那么最终的返回值就是0,而不是catch中的2
            System.out.println("finally模块被执行");
            return 0;
        }
    }

    /**
     * 该方法的返回值为0
     * finally 中改变了基本类型的返回值变量,不会影响最终的返回值
     */
    private static int test1(){
        int num = -1;
        try {
            System.out.println("e----->before");
            int a = 8/0;
            System.out.println("e----->after");
            return num;
        }catch (Exception e) {
            System.out.println("catch");
            num = 0;
            return num;
        }finally{//finally 中改变了基本类型的返回值变量,不会影响最终的返回值,返回值为0
            System.out.println("finally模块被执行");
            num = 1;
        }
    }

    /**
     * finally 中改变了引用类型的返回值变量,会影响最终的返回值
     * @return
     */
    private static String test2(){
        String s = "hello";
        try {
            System.out.println("e----->before");
            int a = 8 / 0;
            System.out.println("e----->after");
            return s;
        } catch (Exception e) {
            System.out.println("catch----->message="+e.getMessage());
        }finally{//finally 中改变了引用类型的返回值变量,会影响最终的返回值
            System.out.println("finally模块执行");
            s += "world";
        }
        return s;
    }

Last updated

Was this helpful?