Discussion invariance in Java strings

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/lidelin10/article/details/102767711

String objects in Java is designed to be immutable, which is mainly reflected in the following aspects:

1, class String is declared as final.

2, class String of char [] can not be accessed. In the presence of char [] is the constructor method parameters or substring Copies are by way of implementation.

Let's look at these two design objectives, first of all why the class String is declared as final?

class String is declared as final in itself represents a non-inheritance of this class can not inherit any subclass does not explain it, so this way there is no subclasses override class String destroy the possibility of its immutability. For example, if we implement a succession String implements MutableString, such a method of this class exist setCharAt(int index, char ch), when we declare String mutableString = new MutableString("string")when this mutableString may be treated as a common string is quoted everywhere, ordinary strings are satisfied invariance but if there is a transition operation mutableString down, this time by setCharAt(int index, char ch)modifying the method string, the string is broken invariance.

For the second design, String of char [] can not be accessed, we can modify the value array to see what wonderful things through unsafe.

public static void setStringCharAt(String str, int i, char ch)throws NoSuchFieldException, IllegalAccessException{
    Unsafe unsafe = getUnsafe();
    Class<?> stringClass = String.class;
    Field value = stringClass.getDeclaredField("value");
    value.setAccessible(true);
    long valueAddress = unsafe.objectFieldOffset(value);
    Class<?> charArrayClass = char[].class;
    long baseOffset = unsafe.arrayBaseOffset(charArrayClass);
    int scale = unsafe.arrayIndexScale(charArrayClass);
    Object valueObject = value.get(str);
    long charAddress = i * scale + baseOffset;
    unsafe.putChar(valueObject, charAddress, ch);
}

public static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException{
    Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
    theUnsafe.setAccessible(true);
    return  (Unsafe) theUnsafe.get(null);
}


public static void main(String[] args) throws Exception{
    String str0 = "abc";
    String str1 = "abc";

    /**
     * 操作虽多,只为了将字符串str0的第一个元素修改为'c'
     */
    setStringCharAt(str0, 0, 'c');
    
    System.out.println(str0 + str1);
}

This procedure by declaring the two variables str0, str1, we modify the first character str0, and then output the two strings, some people may feel that the result is cbcabc, but it is not.

We first need to note that these two variables are assigned using a string literal, for string literals, Java is a means of optimization - the two variables point to the same runtime constant pool of reference, so in fact the two variables the value references are references to the constant pool, we modify the value of an array of strings by unsafe, may not only be affected by the current variables may affect the hundreds of thousands. In summary, it is clear that the result is cbccbc.

From these aspects, invariance Java strings to avoid many potential risks, as well as to simplify the complexity of the entire Java language.

Guess you like

Origin blog.csdn.net/lidelin10/article/details/102767711