JAVA中的数据类型分两种:
- 基本数据类型(byte、int、boolean、char 等等)
- 引用类型(对象、数据、String)
基本类型比较
- 使用 == 判断值是否相等
引用类型比较
- 重写了equals方法,比如String。
- 第一种情况:使用==比较的是String的引用是否指向了同一块内存。
- 第二种情况:使用equals比较的是String的引用的对象内用是否相等。
- 没有重写equals方法,比如User等自定义类
- ==和equals比较的都是引用是否指向了同一块内存。
String是个较为特殊的包装类型,直接用=“”创建的数据是存放在常量池,且无论数据大小都不会申请空间创建,除非使用new关键字。
如果使用new关键字,会在常量池和堆中都存在一个对象,若有一个相同的对象已经在常量池存在,就只会在堆中创建对象。
String a1 = new String("abc"); // 在常量池和堆中创建对象(共两个),在栈中创建对象引用(a1)
String b1 = new String("abc"); // 由于常量池存在相同对象,只在堆中创建对象,在栈中创建对象引用(b1)
System.out.println(a1 == b1); // 比较a1和b1的对象引用的指向地址(堆中对象)是否相同 ,简单地说就是指向的区域是否相同,false
如果直接赋值,则只会在常量池中创建对象
String c1 = "abc"; // 在常量池中创建对象,在栈中创建对象引用
String d1 = "abc"; // 在常量池已有此内容,不再选择创建对象,在栈中创建引用
System.out.println(c1 == d1); // 判断两个引用是否指向同一区域,true
包装器类型
JVM会自动维护八种基本类型的常量池,int常量池中初始化-128~127的范围,所以当为Integer i=127时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时,128不在常量池范围内,所以在自动装箱过程中需new 128,所以地址不一样。
Integer e1 = 122; // 包装器类型在-128~127时,自动装箱取自常量池
Integer f1 = 122;
System.out.println(e1 == f1); // 指向同一区域,true
Integer e2 = 1222; // 包装器类型大于128,所以这一句相当于Interger e2 = new Integer(1222);
Integer f2 = 1222; // 所以这里就是创建了两个对象
System.out.println(e2 == f2); // 指向了两个对象所以为false
具体事例
String a1 = new String("abc"); // 在常量池和堆中创建对象(共两个),在栈中创建对象引用(a1)
String b1 = new String("abc"); // 由于常量池存在相同对象,只在堆中创建对象,在栈中创建对象引用(b1)
System.out.println(a1 == b1); // 比较a1和b1的对象引用的指向地址(堆中对象)是否相同 ,简单地说就是指向的区域是否相同
String a2 = new String("abc");
String b2 = new String("abc");
System.out.println(a2.equalsIgnoreCase(b2)); // 比较a2和b2两个对象的内容是否相等(在堆中分别占有空间)
String c1 = "abc"; // 在常量池中创建对象,在栈中创建对象引用
String d1 = "abc"; // 在常量池已有此内容,不再选择创建对象,在栈中创建引用
System.out.println(c1 == d1); // 判断两个引用是否指向同一区域
String c2 = "abc";
String d2 = "abc";
System.out.println(c2.equalsIgnoreCase(d2)); // 判断c2和d2内容是否相等
Integer e1 = 122; // 包装器类型在-128~127时,自动装箱取自常量池
Integer f1 = 122;
System.out.println(e1 == f1); // 指向同一区域
Integer e2 = 1222; // 包装器类型大于128,所以这一句相当于Interger e2 = new Integer(1222);
Integer f2 = 1222; // 所以这里就是创建了两个对象
System.out.println(e2 == f2); // 指向了两个对象所以为false
Integer g1 = 122; // 很明显相同
Integer h1 = 122;
System.out.println(g1.equals(h1));
Integer g2 = 1222; // 很明显相同
Integer h2 = 1222;
System.out.println(g2.equals(h2));
运行结果:
false
true
true
true
true
false
true
true