Imutabilidade de string, análise de código-fonte de cache longo e perguntas da entrevista

Imutabilidade de string, análise de código-fonte de cache longo e perguntas da entrevista

Todos estão familiarizados com String e Long. Agora vamos dar uma olhada na implementação do código-fonte subjacente de String e Long em combinação com cenários de trabalho reais. Veja se há algum ponto que precisamos prestar atenção ao usá-los e resumir a que essas APIs são aplicáveis. Cenas.

One: String

1.1. Imutabilidade

Frequentemente vemos essas perguntas na entrevista: Fale brevemente sobre a diferença entre String, StringBuilder e StringBuffer. Dentre elas, a String é diferente das outras duas, uma vez que o valor da String é inicializado não pode ser alterado, se for modificado, será uma nova classe. Vamos dar uma olhada no seguinte trecho de código: Embora "ssssss" seja gerado no final, parece que o valor de String foi modificado.

String str = "aaa";
str = "ssssss";
System.out.println(str);

Na verdade, podemos ver intuitivamente por meio de Debug que o valor de String não foi modificado.
Imutabilidade da corda
Imutabilidade da corda
A princípio, o endereço de memória apontado por str é 527 e, após uma rodada de atribuição, o endereço de memória apontado por str torna-se 529. Em outras palavras, a atribuição aparentemente simples de str = "ssssss" na verdade aponta a referência de str para a nova String.

Agora vamos olhar o motivo do código-fonte de String

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
    
    /** The value is used for character storage. */
    private final char value[];
}    

Podemos ver no código-fonte da String:

  1. String é modificado por final, indicando que a classe String nunca será herdada, ou seja, nenhum método de operação em String será sobrescrito por herança ;
  2. Os dados armazenados em String são um valor de array char. Descobrimos que o valor também é modificado por final, o que significa que uma vez que o valor é atribuído, o endereço de memória é absolutamente impossível de modificar e a permissão do valor é privada, absolutamente inacessível de fora e String não abriu a atribuição de valor Método, então, uma vez que o valor é gerado, o endereço da memória não pode ser modificado ;

Os dois pontos acima são a razão da imutabilidade de String. Ele aproveita ao máximo as características da palavra-chave final. Se você quiser ser imutável ao personalizar a classe, também pode imitar essas duas operações de String.

1.2, julgamento de igualdade

Temos duas maneiras de julgar igualdade, equals e equalsIgnoreCase. Quando o último for considerado igual, o caso será ignorado. Se você for solicitado a escrever a lógica para julgar a igualdade de duas Strings, como escrevê-la, vamos dar uma olhada no código-fonte de iguais:

public boolean equals(Object anObject) {
    
    
    // 判断内存地址是否相同
    if (this == anObject) {
    
    
        return true;
    }
    // 待比较的对象是否是 String,如果不是 String,直接返回不相等
    if (anObject instanceof String) {
    
    
        String anotherString = (String)anObject;
        int n = value.length;
        // 两个字符串的长度是否相等,不等则直接返回不相等
        if (n == anotherString.value.length) {
    
    
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // 依次比较每个字符是否相等,若有一个不等,直接返回不相等
            while (n-- != 0) {
    
    
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

Como pode ser visto no código-fonte de iguais, a lógica é muito clara e o código equivalente é escrito completamente com base na estrutura subjacente de String. Isso também nos fornece uma maneira de pensar: se alguém pergunta como julgar se os dois são iguais, podemos começar a partir da estrutura subjacente dos dois, para que possamos pensar rapidamente em uma ideia prática e método, assim como a String subjacente A estrutura de dados é a mesma do array char. Ao julgar a igualdade, apenas compare os caracteres no array char um por um para ver se eles são iguais.

Dois: Longo

2.1, cache

Estamos mais preocupados com o problema de cache de Long. Long implementou um mecanismo de cache que armazena em cache todos os valores Long de -128 a 127. Se for um valor Long neste intervalo, ele não será inicializado, mas Retire do cache, o código-fonte de inicialização do cache é o seguinte:

private static class LongCache {
    
    
    private LongCache(){
    
    }
    // 缓存,范围从 -128 到 127,+1 是因为有个 0
    static final Long cache[] = new Long[-(-128) + 127 + 1];

    // 容器初始化时,进行加载
    static {
    
    
        // 缓存 Long 值,注意这里是 i - 128 ,所以再拿的时候就需要 + 128
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

Três: perguntas da entrevista

3.1. Por que é recomendado usar mais o método valueOf e menos o método parseLong ao usar Long?

Como o próprio Long tem um mecanismo de cache que armazena Longs no intervalo de -128 a 127, o método valueOf obterá o valor do cache. Se o cache for atingido, ele reduzirá a sobrecarga de recursos. O método parseLong não tem esse mecanismo.

3.2. Por que todo mundo diz que String é imutável?

Se String e o array char que contém os dados forem modificados pela palavra-chave final, eles serão imutáveis. Para obter detalhes, consulte o acima.

Três: Resumo

String e Long são usados ​​com frequência em nosso trabalho.No processo de entrevista, o examinador também gosta de fazer algumas perguntas práticas para verificar nossa proficiência.

Acho que você gosta

Origin blog.csdn.net/weixin_38478780/article/details/107762049
Recomendado
Clasificación