关于String类型,我们对它是既熟悉又陌生,它可讲的地方还真是不少.众所周知,String类型算是Java 的一个难点,确实,刚开始我也是听困惑,也没觉得,不就是一个字符串吗?有什么好学的?于是就没怎么管.一直对它是模模糊糊的概念,就以为他是表示一个字符串,直到有一天看见了一篇关于讲解Java String类型的文章,突然觉得这东西还要那么多可以研究的地方.
下面进入正题,讲讲关于String 困惑大家的地方吧.
1.首先要明确一点,String不属于8个基本类型的数据,而是一个对象.
2.既然String是对象,就要说说怎么创建,
String str = new String("hello java"); //这是创建了一个String类型的对象,
String str2 = "hello java"; //这也可以啊,而且平时我们都是这么写的
那他们有什么区别呢?说到这里,就要说说String特有的String池了(StringPool),对于直接通过赋值创建的对象,他们都会被放在StringPool中,并且每次创建的时候,都会去StringPool中看看有没有相同的对象,有的话就将新创建对象的引用指向该对象,没有的话就对新创建这个对象,而用new 方法创建的对象,则不会放在StringPool中,而是放在堆内存中,不管有没有相同的对象,都回去重新创建一个新的对象,但是这是很耗内存的,虽然那点内存并不影响什么,但是还是不提倡这么使用.下面举个例子:
String a1 = "hello java";//执行这条语句的时候,会首先到StringPool中查找有没有"hello java"的的对象,发现没有,则会创建一个新的对象并放在StringPool中.a1则会指向该对象
String a2 = "hello java";//看看这行代码会干什么,先到StringPool中查找"hello java",发现有这个对象(上一行代码),然后a2就指向了找到的对象的引用.
再来看看new方法产生对象又是怎么的:
String a3 = new String("hello java");//执行这行代码使,这不会去找Stringpool中有无该对象,而是直接在堆内存中创建对象,并且不管堆内存有无该对象,直接创建
String a4 = new String("hello java");//这也就同理了
那我们来测试一下:
System.out.println("a1 == a2 ?"+(a1 == a2)); //运行结果为true a1,a2指向同一个对象
System.out.println("a3 == a4 ?"+(a3 == a4));//运行结果为false,a3,a4表示两个不同的对象,虽然值一样
3.下面我们来看看关于字符串的"==" 和 equals()
都知道"=="是用来判断两个对象是否相等,那么问题来了什么才算是相等呢?来看一个例子:
String a1 = "hello java";
String a2 = new String("hello java");
String a3 = a1;
System.out.println("比较 == --------------------");
System.out.println(a1 == a2);
System.out.println(a1 == a3);
System.out.println(a2 == a3);
看的出运行结果吗?
运行发现结果是:
比较 == --------------------
false
true
false
其实结果你也可能看出来了?a1和a3指向同一个对象,所以结果为true.a1和a2分别指向了不同的对象,但是值是一样的为什么为false."=="到底比较的是什么,其实"=="比较的就是内存地址值,由于指向了不同的对象,所以所指向的对象的内存地址值当然不同.
equals方法又比较的是什么呢:
String a1 = "hello java";
String a2 = new String("hello java");
String a3 = a1;
System.out.println("比较 equals --------------------");
System.out.println(a1.equals(a2));
System.out.println(a1.equals(a3));
System.out.println(a2.equals(a3));
运行结果如下:
比较 equals --------------------
true
true
true
查看API ,String是继承于Object类的,而Object类的equals()方法也是比较的对象是否相等,那就奇怪了这不和"=="作用相同吗,那结果怎么不一样啊,继续查看API,发现String类的equals方法定义如下:
String类中equals变成比较对象的值是否相同,而"=="比较的是内存地址值是否相同,那这里很多人就晕了,内存地址值我怎么知道是多少,其实Object类有一个hashcode()方法就是通过将该对象的内部地址转换成一个整数来实现的.Object原始的equals()方法用来比较两个对象的地址值,而原始的hashCode()方法用来返回其所在对象的物理地址.这里也就有点明白了吧,equals()方法其实依赖于hashcode()方法的返回值.而String类有重写了hashcode()方法:
String a1 = "hello java";
String a2 = new String("hello java");
String a3 = a1;
System.out.println("hashcode-----------------------");
System.out.println(a1.hashCode());
System.out.println(a2.hashCode());
System.out.println(a3.hashCode());
运行结果:
hashcode-----------------------
-1605094224
-1605094224
-1605094224
原来String类的哈希值是通过字符串计算出来的,那也就不奇怪了,对象不同,但是他们的字符串的内容相同,当然hashcode值也就相同,equals()方法当然会返回true.记住:"==" 比较的内存地址值,只要指向的不是同一个对象,就不相等,而equals()方法则是比较内容是否相等(针对String类).