java面试题(2)equals()和==的思考

 

首先明白2个事情什么是:基本类型数据和引用类型数据

基本类型数据:八大数据类型:byte,short,int,long,float,double,char,boolean

补充:基本包装类:Byte、Short、Integer、Long、Float、Double、Character、Boolean

引用数据类型:它就是一个引用, 指向堆内存中一个具体的对象

public class test2 {
    public static void main(String[] args) {
        int num = 100;
        String str = "beijing";
    }
}

第1点:关于==

"==" :当比较基本数据类型的时候比较的是数值

"==" :判断两个引用数据类型是否相等的时候,实际上是在判断两个引用是否指向同一个对象

           比较引用类型时比较的是引用指向的地址

第2点:关于equals方法

java的核心思想面向对象,在java.lang包下:有个很牛逼的类叫:Object 类,并且Object 类中写有equals()方法:

Object类中的equals()方法源码
public boolean equals(Object obj) {
        return (this == obj);
}

在很多业务需求的对比对象的时候,编程人员可以通过重写 equals() 方法来实现自己的比较策略

于是看String类源码重写了

public boolean equals(Object anObject) {
    if (this == anObject) {	//先比较两个字符串的引用是否相等(是否指向同一个对象), 是直接返回true
        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;
}

 

Integer类源码重写了

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

举例:基础包装类equals方法:

扩展:java的装箱和拆箱:
所谓装箱,就是把基本类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,如我们可以把int型包装成Integer类的对象,或者把double包装成Double,等等。
所谓拆箱,就是跟装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为值类型的数据。

int i=10;
Integer j=Integer.valueOf(i); //手动装箱操作
int k=j.intValue();//手动拆箱操作

int i1=10
Integer j1=i1;//自动装箱操作
int k1=j1;//自动拆箱操作
public class test2 {
    public static void main(String[] args) {
        int a = 3;
        Integer b = new Integer(3);
        System.out.println(b.equals(a));

    }
}

结果返回:true

结论:

"equals()" :当比较基本数据类型包装类的时比较的还是基本数据类型的值

"equals()" :当调用 String 类型数据的 equals() 方法时,首先会判断两个字符串的引用是否相等,也就是说两个字符串引用是否指向同一个对象,是则返回true。如果不是指向同一个对象,则把两个字符串中的字符挨个进行比较。

 

补充拓展资料源于其他博文:(仅供参考搜集于网络)

博友文章地址:

hashCode和identityHashCode 的关系

/**
 * 一个对象的hashCode和identityHashCode 的关系:
 * 1:对象的hashCode,一般是通过将该对象的内部地址转换成一个整数来实现的
 * 2:当一个类没有重写Object类的hashCode()方法时,它的hashCode和identityHashCode是一致的
 * 3:当一个类重写了Object类的hashCode()方法时,它的hashCode则有重写的实现逻辑决定,此时的hashCode值一般就不再和对象本身的内部地址有相应的哈希关系了
 * 4:当null调用hashCode方法时,会抛出空指针异常,但是调用System.identityHashCode(null)方法时能正常的返回0这个值
 * 5:一个对象的identityHashCode能够始终和该对象的内部地址有一个相对应的关系,从这个角度来讲,它可以用于代表对象的引用地址,所以,在理解==这个操作运算符的时候是比较有用的
 *
 */
public class test2 {

    public static void main(String[] args) {

        String str1 = "zhangsan";
        String str2 = "zhangsan";

        String str3 = new String("zhangsan");   //str3指向的是堆内存中的字符串对象

        System.out.println("str1和str2比较:"+(str2==str1));
        System.out.println("st3和str2比较:"+(str3 == str2));

        System.out.println("str1的hashCode:"+str1.hashCode());
        System.out.println("str2的hashCode:"+str2.hashCode());
        System.out.println("str3的hashCode:"+str3.hashCode());

        System.out.println("str1的identityHashCode:"+System.identityHashCode(str1));
        System.out.println("str2的identityHashCode:"+System.identityHashCode(str2));
        System.out.println("str3的identityHashCode:"+System.identityHashCode(str3));
        
    }
}

输出结果:

str1和str2比较:true
st3和str2比较:false
str1的hashCode:-1432604556
str2的hashCode:-1432604556
str3的hashCode:-1432604556
str1的identityHashCode:396180261
str2的identityHashCode:396180261
str3的identityHashCode:625576447

【一个对象的identityHashCode能够始终和该对象的内部地址有一个相对应的关系,从这个角度来讲,它可以用于代表对象的引用地址,所以,在理解==这个操作运算符的时候是比较有用的】

str3用了new关键字,是不是创建了新对象呢

当我们查看对象的内存布局的时候:他的对象头确实不一样了:

查看class markword,JOL工具 查看对象结构:
<dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.9</version>
        </dependency>
        System.out.println("============================str1");

        System.out.println(ClassLayout.parseInstance(str1).toPrintable());
        System.out.println("============================str2");

        System.out.println(ClassLayout.parseInstance(str2).toPrintable());
        System.out.println("============================str3");

        System.out.println(ClassLayout.parseInstance(str3).toPrintable());

============================str1
java.lang.String object internals:
 OFFSET  SIZE     TYPE DESCRIPTION                               VALUE
      0     4          (object header)                           01 62 9f 09 (00000001 01100010 10011111 00001001) (161440257)
      4     4          (object header)                           5d 00 00 00 (01011101 00000000 00000000 00000000) (93)
      8     4          (object header)                           da 02 00 f8 (11011010 00000010 00000000 11111000) (-134216998)
     12     4   char[] String.value                              [z, h, a, n, g, s, a, n]
     16     4      int String.hash                               -1432604556
     20     4          (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

============================str2
java.lang.String object internals:
 OFFSET  SIZE     TYPE DESCRIPTION                               VALUE
      0     4          (object header)                           01 62 9f 09 (00000001 01100010 10011111 00001001) (161440257)
      4     4          (object header)                           5d 00 00 00 (01011101 00000000 00000000 00000000) (93)
      8     4          (object header)                           da 02 00 f8 (11011010 00000010 00000000 11111000) (-134216998)
     12     4   char[] String.value                              [z, h, a, n, g, s, a, n]
     16     4      int String.hash                               -1432604556
     20     4          (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

============================str3
java.lang.String object internals:
 OFFSET  SIZE     TYPE DESCRIPTION                               VALUE
      0     4          (object header)                           01 67 bb f8 (00000001 01100111 10111011 11111000) (-121936127)
      4     4          (object header)                           37 00 00 00 (00110111 00000000 00000000 00000000) (55)
      8     4          (object header)                           da 02 00 f8 (11011010 00000010 00000000 11111000) (-134216998)
     12     4   char[] String.value                              [z, h, a, n, g, s, a, n]
     16     4      int String.hash                               -1432604556
     20     4          (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我先来一碗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值