Some knowledge about the String class

// original link: https: //blog.csdn.net/songylwq/article/details/7297004

String str=new String(“abc”);

Immediately after this code is often the problem, and that is what this line of code to create a few String objects? I believe we no stranger to this question, the answer is known, two. Then we unfold from this question, review some JAVA knowledge related to creating String objects together.

We can put this line of code above into String str, =, "abc" and the new String () to look at four parts. String str just defines a variable named str String type, so it does not create the object; = str variable is initialized, the reference (or call handler) assigned to it an object, apparently did not create the object ; now only new String ( "abc") a. Then, new String ( "abc") Why can be seen as "abc" and the new String () do? We look at is we call the constructor of the String:

 

  1. public String(String original) {
  2. //other code 。..
  3. }

 

We all know that we often create an instance (object) of a class of the following two methods:

Use new object is created.

Call newInstance method of class Class, create objects using the reflection mechanism.

What we call above using new String class constructor method that creates an object and its reference assigned to the variable str. At the same time we note that the constructor method is called to accept the argument is a String object that is the "abc". Thus, we have to create a String object to introduce another way discussion - contains text within quotation marks.

String this way is unique, and there is a big difference between it and the new way.

String str=“abc”;

There is no doubt that this line of code creates a String object.

String a=“abc”;

String b=“abc”;

That here it? The answer is a.

String a=“ab”+“cd”;

Look at it here? The answer is three. Strange it? Here, we need to introduce a review of the relevant knowledge of the string pool.

It exists in a string pool JAVA virtual machine (JVM) in which to save a lot of String object, and can be shared, so it improves the efficiency. Because the String class is final, its value can not be changed once created, so we do not worry about String objects share and bring chaos program. String pool maintained by the String class, we can call the intern () method to access the string pool.

We look back at the String a = "abc" ;, when this line of code is executed, JAVA virtual machine first in the string pool to find whether there is a value of "abc" of such an object, its judgment is based on return value String class equals (Object obj) method. If so, then no longer create a new object, direct returns a reference to an object that already exists; if not, create the object, and then add it to the string pool, and then returns a reference to it. Therefore, it is not difficult to understand why the previous three examples in the first two examples are the answer.

For the third example:

String a=“ab”+“cd”;

"Ab" and "cd", respectively, to create an object, they pass "+" connected to create an object and then "ABCD", and therefore a total of three, and they are stored in a string pool.

Now the question again, is not after all "+" to get the connection string will be added to the string pool it? We all know that "==" can be used to compare two variables, it has the following two situations:

If the comparison of the two basic types (char, byte, short, int, long, float, double, boolean), it is judged whether their values ​​are equal.

If the table is two objects more variables, it is determined whether they point to the same reference object.

Here we use "==" to do a few tests. For illustrative purposes, we point to an existing string pool object is also considered as the object is added to the string pool:

 

  1. public class StringTest {
  2. public static void main(String[] args) {
  3. String a = “ab”;// 创建了一个对象,并加入字符串池中
  4. System.out.println(“String a = \”ab\“;”);
  5. String b = “cd”;// 创建了一个对象,并加入字符串池中
  6. System.out.println(“String b = \”cd\“;”);
  7. String c = “abcd”;// 创建了一个对象,并加入字符串池中
  8. String d = “ab” + “cd”;
  9. // 如果d和c指向了同一个对象,则说明d也被加入了字符串池
  10. if (d == c) {
  11. System.out.println(“\”ab\“+\”cd\“ 创建的对象 \”加入了\“ 字符串池中”);
  12. }
  13. // 如果d和c没有指向了同一个对象,则说明d没有被加入字符串池
  14. else {
  15. System.out.println(“\”ab\“+\”cd\“ 创建的对象 \”没加入\“ 字符串池中”);
  16. }
  17. String e = a + “cd”;
  18. // 如果e和c指向了同一个对象,则说明e也被加入了字符串池
  19. if (e == c) {
  20. System.out.println(“ a +\”cd\“ 创建的对象 \”加入了\“ 字符串池中”);
  21. }
  22. // 如果e和c没有指向了同一个对象,则说明e没有被加入字符串池
  23. else {
  24. System.out.println(“ a +\”cd\“ 创建的对象 \”没加入\“ 字符串池中”);
  25. }
  26. String f = “ab” + b;
  27. // 如果f和c指向了同一个对象,则说明f也被加入了字符串池
  28. if (f == c) {
  29. System.out.println(“\”ab\“+ b 创建的对象 \”加入了\“ 字符串池中”);
  30. }
  31. // 如果f和c没有指向了同一个对象,则说明f没有被加入字符串池
  32. else {
  33. System.out.println(“\”ab\“+ b 创建的对象 \”没加入\“ 字符串池中”);
  34. }
  35. String g = a + b;
  36. // 如果g和c指向了同一个对象,则说明g也被加入了字符串池
  37. if (g == c) {
  38. System.out.println(“ a + b 创建的对象 \”加入了\“ 字符串池中”);
  39. }
  40. // 如果g和c没有指向了同一个对象,则说明g没有被加入字符串池
  41. else {
  42. System.out.println(“ a + b 创建的对象 \”没加入\“ 字符串池中”);
  43. }
  44. }
  45. }



 

运行结果如下:

String a = “ab”;

String b = “cd”;

“ab”+“cd” 创建的对象 “加入了” 字符串池中

a +“cd” 创建的对象 “没加入” 字符串池中

“ab”+ b 创建的对象 “没加入” 字符串池中

a + b 创建的对象 “没加入” 字符串池中

从上面的结果中我们不难看出,只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中。对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,对此我们不再赘述。因此我们提倡大家用引号包含文本的方式来创建String对象以提高效率,实际上这也是我们在编程中常采用的。

接下来我们再来看看intern()方法,它的定义如下:

public native String intern();

这是一个本地方法。在调用这个方法时,JAVA虚拟机首先检查字符串池中是否已经存在与该对象值相等对象存在,如果有则返回字符串池中对象的引用;如果没有,则先在字符串池中创建一个相同值的String对象,然后再将它的引用返回。

我们来看这段代码:

 

  1. public class StringInternTest {
  2. public static void main(String[] args) {
  3. // 使用char数组来初始化a,避免在a被创建之前字符串池中已经存在了值为“abcd”的对象
  4. String a = new String(new char[] { ‘a’, ‘b’, ‘c’, ‘d’ });
  5. String b = a.intern();
  6. if (b == a) {
  7. System. out.println(“b被加入了字符串池中,没有新建对象”);
  8. } else {
  9. System. out.println(“b没被加入字符串池中,新建了对象”);
  10. }
  11. }
  12. }



运行结果:

b没被加入字符串池中,新建了对象

如果String类的intern()方法在没有找到相同值的对象时,是把当前对象加入字符串池中,然后返回它的引用的话,那么b和a指向的就是同一个对象;否则b指向的对象就是JAVA虚拟机在字符串池中新建的,只是它的值与a相同罢了。上面这段代码的运行结果恰恰印证了这一点。

最后我们再来说说String对象在JAVA虚拟机(JVM)中的存储,以及字符串池与堆(heap)和栈(stack)的关系。我们首先回顾一下堆和栈的区别:

栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。

堆(heap):用于存储对象。

我们查看String类的源码就会发现,它有一个value属性,保存着String对象的值,类型是char[],这也正说明了字符串就是字符的序列。

当执行String a=“abc”;时,JAVA虚拟机会在栈中创建三个char型的值‘a’、‘b’和‘c’,然后在堆中创建一个String对象,它的值(value)是刚才在栈中创建的三个char型值组成的数组{‘a’,‘b’,‘c’},最后这个新创建的String对象会被添加到字符串池中。如果我们接着执行String b=new String(“abc”);代码,由于“abc”已经被创建并保存于字符串池中,因此JAVA虚拟机只会在堆中新创建一个String对象,但是它的值(value)是共享前一行代码执行时在栈中创建的三个char型值值‘a’、‘b’和‘c’。

说到这里,我们对于篇首提出的String str=new String(“abc”)为什么是创建了两个对象这个问题就已经相当明了了

Guess you like

Origin www.cnblogs.com/cold-windy/p/11517036.html