Alguns problemas com a piscina constante

Várias piscinas constantes

piscina constante de classe

  • diagrama de estrutura de arquivo de classeInsira a descrição da imagem aqui
  • Depois que a classe java é compilada, gere.class文件

Citado
class文件 além de conter as versões da classe, campos, métodos e informações de descrição da interface, há uma mensagem 常量池(constant pool table), para armazenar várias gerações do compilador 字面量(Literal)e 符号引用(Symbolic References).
Literal : conceito constante, como textoStrings "abc", valores constantes declarados como finais, etc..
Referência de símbolo :Um conjunto de símbolos para descrever o alvo referenciado. O símbolo pode ser qualquer forma de quantidade literal, desde que possa ser usado para localizar o alvo sem ambigüidade. (A distinção entre referência direta: referência direta é geralmente um ponteiro local para uma área de método, um deslocamento relativo ou um identificador que pode localizar indiretamente o destino).
As referências de símbolo geralmente incluem os três tipos de constantes a seguir:

  • Nomes totalmente qualificados de classes e interfaces
  • Nome do campo e descritor
  • Nome e descritor do método

Autoconhecimento de imagem
Insira a descrição da imagem aqui

  • Class DataExiste na área do método (a implementação da área do método 1.8 é um metaespaço, que anteriormente era uma geração permanente).

Pool de constantes de string

  • 字符串常量池, Também conhecida como 字符串字面量池(String Literal Pool), 字符串池(String Pool), 全局字符串池.
    O carregamento da classe está completo, após verificação, após a fase de preparaçãoNa instância do objeto de string de caracteres gerado pela pilha , e então estesEndereço de referência da instância do objeto stringSalvar em 字符串池.
  • Em HotSpot VMLane, a 字符串池função implementada é uma StringTableclasse, que é uma tabela hash, que é armazenada 驻留字符串(na parte de aspas duplas) da referência ,Em vez da própria instância de string residente, a própria instância ainda está no heap. Portanto, esses são exemplos dessa string StringTabledepois que a referência recebeu o equivalente de 驻留字符串identidade. Esta StringTableem cada HotSpot VMapenas uma instância é compartilhada por todas as classes.
  • O pool de constantes de string está no heap (na área do método antes de 1.7)

Pool constante de tempo de execução

  • Quando a classe é carregada na memória, o conteúdo jvmé class常量池armazenado no pool de constantes de runtime, ou seja, cada classe possui um pool de constantes de runtime. class常量池Os dados serão analisados e carregados no pool de constantes de tempo de execução.

classO pool de constantes armazena literais e referências de símbolo e, após a análise , as referências de símbolo são substituídas por referências diretas. O processo de análise irá consultar o pool de constantes de string, que é o acima StringTable, para garantir que a string referenciada pelo pool de constantes em tempo de execução seja consistente com a string referenciada no pool de strings global.

  • O conjunto de constantes de tempo de execução está na área do método.

Alguns problemas com o pool de constantes de string

	@Test
    public void test() {
    
    
        String str1 = "abc";
        String str2 = new String("def");
        String str3 = "abc";
        String str4 = str2.intern();
        String str5 = "def";
        System.out.println(str1 == str3); //true
        System.out.println(str2 == str4);//false 
        System.out.println(str4 == str5);//true
    }
  • "abc"A instância no heap já existe quando a classe é carregada e a referência "abc"no StringTableé retornada diretamente .
  • new String("def")O espaço de memória é recém-aplicado e uma nova instância de string é criada.O valor é "def"retornado ao endereço. "def"O mesmo já existe StringTable.
  • "abc"Na StringTableverdade, o retorno direto StringTableem uma referência.
  • intern(): Se StringTablenão houver referência à string, adicione-a. "def"A referência retornou .
  • "def"Na StringTableverdade, o retorno direto StringTableem uma referência.
@Test
    public void test() {
    
    
		//此行代码执行的底层执行过程是 
        //创建临时StringBuilder的append方法将"2"和"2"拼接在一块,然后调用toString方法new出"22"
        //在StingTable中会有"22"的引用
        String str1 = new String("2") + new String("2");
        String str2 = "22";
        System.out.println(str1 == str2); //false
    }
@Test
    public void test() {
    
    
        String str1 = "a";
        String str2 = "b";
        String str3 = "ab";
        //同样通过StringBuilder append,new String("ab"),会在StringTable中添加引用
        String str4 = str1 + str2;
        //编译时常量,在编译后直接能计算出拼接后的字符串值,不需要再运行时创建临时StringBuilder对象。
        //返回StringTable中的"ab"引用
        String str5 = "a" + "b";
        System.out.println(str3 == str4); // false
        System.out.println(str3 == str4.intern()); // true
        System.out.println(str3 == str5);// true
    }

Caso especial

public static final String A; // 常量A
    public static final String B; // 常量B

    static {
    
    
        A = "ab";
        B = "cd";
    }

    public static void tes() {
    
    
        // 将两个常量用+连接对s进行初始化
        String s = A + B;
        String t = "abcd";
        System.out.println(s == t);//false
    }

Embora A e B sejam definidos como constantes, eles não são atribuídos imediatamente. Antes de o valor de s ser calculado, quando eles são atribuídos e qual valor é atribuído, todas são variáveis. Portanto, antes de A e B serem atribuídos, suas propriedades são semelhantes a uma variável. Então s não pode ser determinado em tempo de compilação, mas só pode ser criado em tempo de execução.

Acho que você gosta

Origin blog.csdn.net/qq_42007742/article/details/106887644
Recomendado
Clasificación