在java中,执行比较运算的操作一般有: == 和 equals()两个操作符
而且在java中== 比较的是两个字符串的引用是否相同, 而 equals()则是比较两个字符串的内容是否相同
我们可以通过一个例子来进行一下验证:
String a1 = "ab";
String a2 = "ab";
String b1 = new String("ab");
String b2 = "ab";
System.out.println("a1 == a2 : " + (a1 == a2));
System.out.println("a1.equals(a2) : " + (a1.equals(a2)));
System.out.println("b1 == b2 : " + (b1 == b2));
System.out.println("b1.equals(b2) : " + (b1.equals(b2)));
最终运行的结果为:
a1 == a2 : true
a1.equals(a2) : true
b1 == b2 : false
b1.equals(b2) : true
由此我们可以看出 在java中==比较的是两个对象的引用是否相同 而eqausls()方法才是比较两个对象的内容是否相同
那为什么字符串b1和字符串b2的引用不相同 但是内容相同的呢,这就需要从字符串String在java内存中的分配来说了:
如以上的示意图所示,当我们画出以上创建的四个String对象的内存分配示意图的时候我们其实就可以很清楚的得出结果了:
1. a1 == a2 -> true
由于String这种类型的数据会在java程序中频繁的使用因此java从性能的角度出发设计了一个字符串常量池的概念,字符串常量池存在于
java内存中的方法区中,当我们创建一个String对象时如果该对象表示的字符串存在于字符串常量池中的话那么就直接取字符串常量池中
的字符串进行使用,否则会创建该字符串并将该字符串存入字符串常量池当中,那么当下次使用时会直接从字符串常量池中进行获取
由此我们可以得出创建a1对象时 由于字符串常量池中没有"ab"这个字符串那么会创建"ab"字符串对象并将其放入到字符串常量池中
而创建a2对象时会直接取字符串常量池中进行获取 直接将a2指向字符串常量池中的"ab"对象 由此在执行a1 == a2的时候这两个对象
的引用肯定是相同的 即返回true
2.a1.equals(a2) 内容都是为"ab"因此肯定相同返回true
3. b1 == b2
在创建b1的时候 我们是通过new String("ab")这种方式显式的创建了字符串b1对象 那么在这种创建方式下 会首先在堆内存中
为b1对象分配空间,然后在初始化内容时,由于字符串常量池中已经有了"ab"这个字符串对象那么堆内存中的b1对象会直接
指向方法去中的字符串常量池中的"ab"对象,那么此时栈中的b1对象指向的是堆内存中的一块区域,再由栈内存中的区域指向
字符串常量池中的"ab"对象,而b2 对象由于不是显式的创建的会直接有栈中指向方法区中的字符串常量池中的"ab"对象
由此 b1 == b2 判断对象引用是肯定返回false因为一个是执行堆内存 一个指向的是方法区中的字符串常量池
4. b1.equals(b2) 由于b1和b1内容相同 因此返回的肯定是true
说完了java中的字符串比较 我们就来说说 kotlin中的字符串比较:
在kotlin中用于比较运算的有三个 分别是: == === equals()方法
我们先来看看一下的代码:
var a: String = "hello"
var b: String = "hello"
println("a == b ${a == b}")
println("a === b ${a === b}")
println("a equals b ${a.equals(b)}")
var c = String(listOf<Char>('a', 'b').toCharArray())
var d = "ab"
println("c == d ${c == d}")
println(" c === d ${c === d}")
println("c equals d ${c.equals(d)}")
运行结果如下:
a == b true
a === b true
a equals b true
c == d true
c === d false
c equals d true
通过以上的结果我们可以得出:
在kotlin中== 和 equals()方法的作用是一样的都是比较两个对象的内容是否相同
而=== 则是和java中的==一样比较的是两个对象的引用是否相同