Java的那些坑(一)

来源:互联网 发布:美国本周经济数据 编辑:程序博客网 时间:2024/06/11 22:22

1,== 和equals
基本数据类型,保存在栈中,用==进行数值判断。
而引用数据类型比如Object,对象实体保存在堆中,对象引用地址保存在栈中,则==用来比较地址是否相等,而equals通过看底层源码发现

    /**     * Compares this string to the specified object.  The result is {@code     * true} if and only if the argument is not {@code null} and is a {@code     * String} object that represents the same sequence of characters as this     * object.     *     * @param  anObject     *         The object to compare this {@code String} against     *     * @return  {@code true} if the given object represents a {@code String}     *          equivalent to this string, {@code false} otherwise     *     * @see  #compareTo(String)     * @see  #equalsIgnoreCase(String)     */    public boolean equals(Object anObject) {        if (this == anObject) {            return true;        }        if (anObject instanceof String) {            String anotherString = (String)anObject;            int n = value.length;            if (n == anotherString.value.length) {                char v1[] = value;                char v2[] = anotherString.value;                int i = 0;                while (n-- != 0) {                    if (v1[i] != v2[i])                        return false;                    i++;                }                return true;            }        }        return false;    }

默认也是比较对象的地址是否相等,String类型的可以比较对对象的内容是否相等,equals和hashcode是子类可以重写的方法,子类可以根据自己的具体业务重写达到业务的需求。String类型的数据会涉及到jvm编译时优化问题比如下列

package com.sparkhuu.base;public class StringTest {    public static void main(String[] args) {        String s1 = "a" + "b" + 1; // 编译时自动优化为:"ab1"        String s2 = "ab1";        // == 当比较基本数据类型时,比较数值,当比较引用数据类型时,比较引用地址        System.out.println(s1 == s2);        // equals 默认比较对象的地址, 可被重写,String已经重写了equals方法        System.out.println(s1.equals(s2));        String a = "1";        final String testA = "1";        String b = a + "2" + 3; // 编译时不会优化 b,c不是同一个对象,但b,c值相同 String重写了equals方法        String c = "123";        String testB = testA + "2" + 3;        System.out.println(testB == c);        System.out.println(testB.equals(c));        System.out.println(b == c);         System.out.println(b.equals(c));        String eString = "a";        String fString = eString + "b";        String gString = "ab";        String hString = new String(gString);// 通过new的都只有在运行时才能确定        System.out.println(fString == gString);        System.out.println(hString == gString);        System.out.println(hString.intern() == gString.intern());    }   }

结果为

truetruetruetruefalsetruefalsefalsetrue

2,基本数据类型的封装类
int –> Integer
char –> Character
double –>Double等
这里会涉及到装包和拆包
如下测试

package com.sparkhuu.base;public class BaseNumberTest {    public static void main(String[] args) {        Integer a = 1;        Integer b = 1;        Integer e = -127;        Integer f = -127;        // Integer.valueOf(); [-128 127]之前是被cache的 所以是同一个对象 而其他范围会new Integer() 所以不是同一个对象        Integer c = 200;        Integer d = 200;        System.out.println(a == b);        System.out.println(e == f);        System.out.println(c == d);        char x = '中';        char x1 = 'a';        byte y = 'a';        Boolean tr = true;        Boolean shBoolean = true;        System.out.println(tr == shBoolean);    }}

结果为

truetruefalsetrue

主要原因是基本数据类型转化为封装类的时候会调用封装类的init,而封装类的部分代码进行了cache,
Integer,Short,Long的cache范围是-128到127,其中Integer可以通过配置修改范围,而Short和Long则不行。
Boolean 的cache范围是true, false,
Characher全部缓存
Double,Float没有缓存。

0 0