String type parameter passing and extension

String parameter passing

The parameter passing of JAVA data types and reference types is an enduring topic for Java beginners.
With the spare time, I will give you a general summary of the knowledge points of parameter passing, and expand the String type parameter passing method.

I believe that everyone has an understanding of the parameter passing of data types and reference types before, not much nonsense, just look at the code

 static void change(int methodVar) {
    
    
        System.out.println("change before,x=" + methodVar);     //10
        methodVar = 100;                                        
        System.out.println("change after,x=" + methodVar);      //100
    }

    public static void main(String[] args) {
    
    
        int mainVar = 10;
        System.out.println("main before,a=" + mainVar);               //10
        change(mainVar);
        System.out.println("main  after,a=" + mainVa);               //10
    }

The results of the operation are as follows.
Insert picture description here
The internal implementation principle is like this
Insert picture description here

Then there is an example of parameter passing by reference type

 static void change(int[] methodArr) {
    
    
        System.out.println("change before,arr[0]=" + methodArr[0]);  //10
        methodArr[0] = 30;
        System.out.println("change after,x[0]=" + methodArr[0]);     //30
    }

    public static void main(String[] args) {
    
    
        int[] mainArr = new int[] {
    
     10, 90 };
        System.out.println("main   before,a[0]=" + mainArr[0]);      //10
        change(mainArr);
        System.out.println("main   after,a[0]=" + mainArr[0]);       //30
    }

The results are as follows

Insert picture description here
Insert picture description here
Here we draw a summary

  • Pass basic type parameters: pass parameter values ​​(copy parameter values)

  • Pass reference type parameters: pass the heap space address value referenced by the parameter

Speaking of reference types, the String type that we have learned before is also a reference type.
Here we might as well try to use String type to pass parameters.

static void change(String methodStr) {
    
    
        System.out.println("change before:"+methodStr);      //小哥哥
        methodStr = "小姐姐";
        System.out.println("change  after:"+methodStr);      //小姐姐
    }

    public static void main(String[] args) {
    
    
        String mainStr = "小哥哥";
        System.out.println("main   before:"+ mainStr);       //小哥哥
        change(mainStr);
        System.out.println("main    after:"+ mainStr);       //小姐姐 ? 小哥哥
    }

Friends first think about whether the final console output is a little brother or a little sister

|
|
|
|

Thinking area
|
|
|
|
|
|
|
|
Code results When
Insert picture description here
you see the results, your friends may have doubts? Shouldn't
the way to pass parameters for reference types be the heap space address value referenced by the parameters?
Why the output result is little brother

At this time, if there is no accident, some friends who have learned to face the object will rush to answer, saying that it is not easy!
Insert picture description here

What this enthusiastic friend said makes sense

Here we first understand a point of knowledge: the heap memory space is used to store instance objects and arrays . In layman's terms, the new keyword is used
. There is no new keyword in the code to create String objects.
Then String mainStr = "little brother"; How is the bottom layer of this code implemented?
The so-called knowing what is happening must be foretelling why, then let’s first understand

Approximate model of JVM memory

Before understanding the approximate model of JVM memory, review what you have learned before

  • Heap: store object instances and arrays
  • Stack: also known as virtual machine stack. When each method is executed, a stack frame is created at the same time to store the local variables of the method, the operand stack (the so-called actual operating platform of the thread), etc...
  • Method area: The information, constants, static variables and other data after the "class" (class file) is loaded are stored here

Here we focus on the constant pool

And what is the constant pool in the class file?

Insert picture description here

The literals of text strings are loaded into the string constant pool

What is the string constant pool?

In our work, the String class is an object type that we use very frequently. In order to avoid the repeated creation of strings and increase unnecessary memory overhead, the JVM has opened up a space in the heap to maintain the String class. Improve performance and reduce memory overhead.

This space is the string constant pool, also known as: String Pool (String Pool)

In layman's terms: When a String class object wants to call a string, it can first go to the string constant pool to find if it wants what it wants, instead of just thinking about new, which will increase unnecessary memory overhead.

Not much nonsense, let's actually operate the two ways of creating string objects in Java:

  • Create String type objects in a literal way
public class StringDemo {
    
    
    public static void main(String[] args) {
    
    
        String str1="StringPool";
        String str2="StringPool";
        System.out.println(str1==str2);
    }
}

运行结果------------------- true

Insert picture description here

  • Use the new keyword to create String type objects
public class StringDemo {
    
    
    public static void main(String[] args) {
    
    
        String str1=new String("StringPool");
        String str2=new String("StringPool");
        System.out.println(str1==str2);
    }
}
 运行结果-------------------  false

Insert picture description here

This embodies the shortcomings of the string pool, which is the need to sacrifice the time required for the JVM to traverse objects in the constant pool, but the time cost is still much smaller than the saving of heap memory.

After understanding the general process of the string pool, let us go back and look at the previous example

```go
 public static void main(String[] args) {
    
    
        //先判断字符串常量池里是否存在"小哥哥",没有,则把"小哥哥"载入字符串常量池,设地址为0x11
        String mainStr = "小哥哥";
        //这里的mainStr变量引用地址为0x11---"小哥哥"   输出    "小哥哥"
        System.out.println("main   before:"+ mainStr);       //小哥哥
        change(mainStr);
        //由于mainStr引用的地址0x11内容没有被修改,所以输出   ---小哥哥
        System.out.println("main    after:"+ mainStr);       //小姐姐 ? 小哥哥
    }

//mainStr变量调用change方法时,把引用的地址拷贝给方法参数 methodStr变量
static void change(String methodStr) {
    
    
        //这里的+methodStr变量引用地址为0x11---"小哥哥"   输出   "小哥哥"
        System.out.println("change before:"+methodStr);      //小哥哥
        //先判断字符串常量池里是否存在"小姐姐",没有,则把"小姐姐"载入字符串常量池,设地址为0x22
        methodStr = "小姐姐";
        //这里的methodStr变量引用地址为0x22---"小姐姐"   输出    "小姐姐"
        System.out.println("change  after:"+methodStr);      //小姐姐
    }

Small scale chopper

 public class StringDemo {
    
    
    public static void main(String[] args) {
    
    
        String str1 = new String("strA");
        String str2 = new String("strB");
        String str3 = "strA";
        String str4 = "strB";
        String str5 = "strA";
        System.out.println(str1 == str2);               
        System.out.println(str3 == str4);              
        System.out.println(str3 == str5);                
        System.out.println(str1.equals(str2));           
        System.out.println(str3.equals(str4));            
        System.out.println(str1.equals(str3));            
    }
}

|
|
|
|

Thinking area
|
|
|
|
|
|
|
|
Code results

 public class StringDemo {
    
    
    public static void main(String[] args) {
    
    
        String str1 = new String("strA");
        String str2 = new String("strB");
        String str3 = "strA";
        String str4 = "strB";
        String str5 = "strA";
        System.out.println(str1 == str2);                  //false
        System.out.println(str3 == str4);                  //false
        System.out.println(str3 == str5);                  //true
        System.out.println(str1.equals(str2));             //false
        System.out.println(str3.equals(str4));             //false
        System.out.println(str1.equals(str3));             //true     ????
    }
}

Will some friends feel puzzled here? Does the equals() method compare the reference addresses of two objects?

str1, str2 both interfere with each other, there is an address stack , the address of an existing string constant pool of
equals () method comparison results Why is it ture?

String class equals() method extension

It turns out that the bottom layer of the String class has rewritten (overridden) the equals() method of the Object class

Equals () method IDEA mouse in front of a String object called ctrl + left view is rewritten after toString () method;
Insert picture description here

public boolean equals(Object anObject) {
    
    
    //首先用==比较,如果相等,说明就是同一个对象,肯定是相等的
    if (this == anObject) {
    
    
        return true;
    }
    //前置判断:是否是String类型,否则肯定不相等
    if (anObject instanceof String) {
    
    
        String aString = (String)anObject;
        //coder方法其实就是获取字符串采用的编码方式,如果编码方式都不一样,肯定结果为false
        if (coder() == aString.coder()) {
    
    
            //根据数据是否是压缩数据,采用不同的比较方式
            return isLatin1() ? StringLatin1.equals(value, aString.value)
                : StringUTF16.equals(value, aString.value);
        }
    }
    return false;
}

It doesn't matter if you don't understand it, let's take a look at the internal equals() method
Insert picture description here
. Isn't this the array we are familiar with?

The following is the integration of the source code we have seen before

public boolean equals(Object anObject) {
    
    
		//首先通过(this == anObject)判断两个对象堆内存地址是否相同
        if (this == anObject) {
    
     
            return true;
        }
        //判断anObject对象是否为String类的实例  如果是则再进行判断,不是直接返回false
        if (anObject instanceof String) {
    
     
            //将anObject对象转为String类型      
            String anotherString = (String)anObject;
            int n = value.length;
            //然后通过判断两个String对象的字段长度是否一样  如果长度一样则再进行判断,不是直接返回false
            if (n == anotherString.value.length) {
    
    
                //把两个String对象转为字符数字
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                //通过while循环判断两个String对象的value数组中的每一个字符是不是相同的
                while (n-- != 0) {
    
    
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

Below is my summary of the source code of the equals() method of the String class:

Compare address

  • true returns true

  • false ---------> 1—judgment type, 2—compare length, 3—compare character

After understanding the source code, look back at this question

 public class StringDemo {
    
    
    public static void main(String[] args) {
    
    
        String str1 = new String("strA");
        String str3 = "strA";
        /*
           1.比较地址为false,进一步比较其"内容"
           2.str3是String类的实例,true,继续下一个判断
           3.str1 str3的内容字段长度一样 返回true,最后进行字符的一一对比
           4.通过遍历char[]数组对比str1 str3的字符之后,最后返回true
        */
        System.out.println(str1.equals(str3));           
    }
}

Now, do you think you have made another big step on the Java road?

Insert picture description here
Finally, leave a question for everyone

String a = ''a" + ''b"+ ''c";

Question: How many objects are created in the string constant pool after this code runs?

Guess you like

Origin blog.csdn.net/weixin_48254340/article/details/107847064