índice
Pergunta da entrevista 1: diferença de String, StringBuffer, StringBuilder
Pergunta da entrevista 2: String a = new String ("kexin"); Vários objetos são gerados
-
Código fonte
-
Parte de inicialização
Implementadas Serializable, Comparable, CharSequence três interfaces, ou seja, serialization, compareTo e CharSequence, a terceira herdou principalmente alguns métodos comuns, length, charAt, subSequence, etc., subSequence é semelhante a subString, o efeito é o mesmo, o tipo de valor de retorno é diferente , Basicamente, não use
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
// 存储空间,字符数组形式
private final char value[];
// hashcode缓存,String常用于比较,每次计算太过麻烦,这样节省时间
private int hash;
// 序列号(尚未理解)
private static final long serialVersionUID = -6849794470754667710L;
-
método
cópia de
//内部方法,将String的字符数组value整个复制到dst字符数组中,在dst数组的dstBegin位置开始拷贝
void getChars(char dst[], int dstBegin) {
System.arraycopy(value, 0, dst, dstBegin, value.length);
}
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
Comparado
public boolean equals(Object anObject) {
//如果对象引用地址相同
if (this == anObject) {
return true;
}
//这个是?存疑
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;
}
Comparação (deixe a ser adicionado)
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
Cortar
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
//生成新对象
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
Substituir (deixar para ser adicionado)
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = value.length;
int i = -1;
char[] val = value; /* avoid getfield opcode */
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
//替换
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
return new String(buf, true);
}
}
return this;
}
Também pode ser visto a partir do código-fonte acima que quaisquer alterações no objeto String não afetarão o objeto original e quaisquer operações de alteração relacionadas irão gerar novos objetos.
-
JVM
-
crio
Há um conceito aqui, chamado Flyweight. Meu entendimento é compartilhar os elementos existentes no pool constante e reduzir o custo de memória
. Existem duas maneiras de criar:
1. String a = "a";
Ao criar, o jvm julgará primeiro Se "a" já existe no pool de constantes, se existir, será citado diretamente; se não existir, a string será instanciada e, em seguida, entre aspas.
Finalmente, o endereço de referência de "a" no pool de constantes de string é armazenado na pilha
2.String b = new String ("A");
Primeiro, um novo objeto de string é colocado no heap e o heap é armazenado no endereço de referência de pool constante "A", o endereço de referência de pool constante é obtido como acima.
Finalmente, a pilha é armazenada O endereço de referência do objeto string no heap.
Portanto, é impossível que duas strings idênticas existam no pool constante. Esta é uma manifestação da imutabilidade das strings.
-
Piscina constante
Existem dois tipos de pools de constantes, pool de constantes estáticas e pool de constantes de tempo de execução.
Compilar pool de constantes estáticas de tempo já colocado antes da constante de execução, como String a = "1"; String a1 = "1" + "2";
execute Conjunto de constante de tempo de execução gerado apenas em variáveis de tempo de execução - como String b = new String ("1"); String b1 = "1" + b;
Nota:
(1): pares JVM String str = "abc" Os objetos são colocados no pool constante no tempo de compilação, e String str3 = str1 + str2 só pode ser conhecido em tempo de execução. O novo objeto também é feito em tempo de execução.
(2): A emenda literal "+" é realizada durante a compilação, e a string emendada é armazenada no pool de strings; e a operação de emenda "+" da referência de string é realmente realizada em tempo de execução, a string recém-criada Armazene em uma pilha.
O conjunto de constantes estáticas, no arquivo de classe, armazena as informações de string, classe e método, etc., que ocupam a maior parte do espaço de memória da classe.
Conjunto de constantes de tempo de execução. Depois que o jvm conclui a operação de carregamento de classe, ele colocará o conjunto de constantes de classe na área do método. , De modo geral, o pool constante se refere ao pool constante na área do método
estagiário
O método interno é um método nativo. O método interno consultará se a string atual existe no pool de constantes de string. Se existir, ele retornará diretamente a string atual; se não existir, colocará a string atual no pool de constantes e, em seguida, Retorna.
-
+ e anexar
O + em String é interpretado como a criação de um objeto StringBuffer, chamando o método append (), chamando toString () e, finalmente, destruindo o objeto StringBuffer no processo de compilação,
como String A = "11" + "22" + Str1 + "33" ; Este processo é interpretado como String A = new StringBuffer ("1122"). Append (Str) .append ("33"). ToString () em tempo de compilação;
portanto, quando a operação + precisa ser realizada no loop, na verdade Irá consumir muito desempenho na criação e destruição de StringBuffer, é melhor criar manualmente um StringBuffer em vez de String
-
Pergunta da entrevista 1: diferença de String, StringBuffer, StringBuilder
Uma das perguntas mais frequentes em entrevistas
(1) pode ser imutável, String é modificada com final, estaticamente imutável e as outras duas são variáveis em comprimento. É por isso que anexar às vezes é usado em vez de +. Anexar é expandido na base original e + é O
thread String (2) recém-criado é seguro? O string é imutável (pode ser entendido como uma constante) e não haverá conflitos causados por vários threads alterando um recurso ao mesmo tempo, por isso é considerado seguro.
StringBuffer usa synchronized para adicionar bloqueios de sincronização, thread safe, StringBuffer não existe, então não é seguro para thread
(3) Eficiência de execução, relativamente falando, StringBuilder> StringBuffer> String, análise específica da situação específica
(4) Cada recurso, uma pequena quantidade de dados String é flexível e mutável, uma grande quantidade de dados StringBuffer multiencadeado de segurança de thread, uma grande quantidade de dados StringBuilder de thread único é mais rápido
-
Pergunta da entrevista 2: String a = new String ("kexin"); Vários objetos são gerados
No estágio de carregamento da classe, um objeto "kexin" é gerado e colocado no heap.
No estágio de execução, um objeto a
é gerado, então há dois
Porção dopada acima do entendimento pessoal, bem-vindo para discutir e me corrigir
Referências
https://blog.csdn.net/yulungggg/article/details/81039655
https://blog.csdn.net/qq_34490018/article/details/82110578
https://www.cnblogs.com/xiaoxi/p/6036701.html