首先明白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 的关系:
* 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