Substituir um caractere em um índice específico em uma string?


382

Estou tentando substituir um caractere em um índice específico em uma string.

O que estou fazendo é:

String myName = "domanokz";
myName.charAt(4) = 'x';

Isso dá um erro. Existe algum método para fazer isso?


12
Sei que isso foi respondido até a morte, mas vale a pena notar que nunca é permitido atribuir o resultado de uma chamada de função em java. Não existem referências a C (?) E C ++.
ApproachingDarknessFish

11
@ValekHalfHeart em VB, você usa parênteses para o índice de acesso de uma matriz, que pode ser a razão por que estou confuso quando eu estava começando em Java: D
DPP

@ApproachingDarknessFish Não sei o que você quer dizer com "nunca é permitido atribuir o resultado de uma chamada de função em java". Certamente você pode fazer double r = Math.sin(3.14)? Como isso se relaciona com esta questão? Obrigado.
flow2k

11
@ flow2k Oh caramba, comentário de idade, então eu não posso editar, mas isso é um erro de digitação, ele deve dizer que "nunca é permitido para atribuir para o resultado de uma chamada de função em Java". Ou seja, você pode escrever "foo = bar ();" mas nunca "bar () = foo;".
ApproachingDarknessFish

Obrigado pelo esclarecimento @ApproachingDarknessFish. Eu acho que seria estranho atribuir algo ao resultado de uma função - existem linguagens que realmente permitem isso? Gostaria de saber qual seria o caso de uso.
flow2k

Respostas:


566

String são imutáveis ​​em Java. Você não pode mudá-los.

Você precisa criar uma nova string com o caractere substituído.

String myName = "domanokz";
String newName = myName.substring(0,4)+'x'+myName.substring(5);

Ou você pode usar um StringBuilder:

StringBuilder myName = new StringBuilder("domanokz");
myName.setCharAt(4, 'x');

System.out.println(myName);

3
Ah, você quer dizer como o replacemétodo que não modifica a string, mas apenas retorna uma nova string?
DPP

11
Isso é meio complicado Sr.Petar. Essa é a melhor maneira de fazer isso? Ah, eu já ouvi falar do StringBuilder antes, isso faz alguma diferença? Isso me dará um método mais fácil?
DPP

158

Transforme a String em um caractere [], substitua a letra pelo índice e depois converta a matriz novamente em uma String.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);

11
Adoro esta solução. Acabei alterando a terceira linha para ser myNameChars [index] = character.toCharArray () [0]; para simplificação. Ótima solução.
Dale

2
parece muito melhor do que o outro mais feio ummyName.substring(0,4)+'x'+myName.substring(5);
user924

É muito mais simples
Shiva Acharjee 14/03

19

Stringé uma classe imutável em java. Qualquer método que parece modificá-lo sempre retorna um novo objeto de string com modificação.

Se você deseja manipular uma string, considere StringBuilderou StringBuffercaso exija segurança de thread.


12

Concordo com Petar Ivanov, mas é melhor se implementarmos da seguinte maneira:

public String replace(String str, int index, char replace){     
    if(str==null){
        return str;
    }else if(index<0 || index>=str.length()){
        return str;
    }
    char[] chars = str.toCharArray();
    chars[index] = replace;
    return String.valueOf(chars);       
}

21
e o que torna sua solução melhor?
dpp

6

Como respondido anteriormente aqui, as Stringinstâncias são imutáveis . StringBuffere StringBuildersão mutáveis ​​e adequados para esse fim, independentemente de você precisar ser seguro ou não.

Existe, no entanto, uma maneira de modificar uma String, mas eu nunca a recomendaria porque é insegura, não confiável e pode ser considerada trapaça: você pode usar a reflexão para modificar a charmatriz interna que o objeto String contém. O Reflection permite acessar campos e métodos normalmente ocultos no escopo atual (métodos ou campos particulares de outra classe ...).

public static void main(String[] args) {
    String text = "This is a test";
    try {
        //String.value is the array of char (char[])
        //that contains the text of the String
        Field valueField = String.class.getDeclaredField("value");
        //String.value is a private variable so it must be set as accessible 
        //to read and/or to modify its value
        valueField.setAccessible(true);
        //now we get the array the String instance is actually using
        char[] value = (char[])valueField.get(text);
        //The 13rd character is the "s" of the word "Test"
        value[12]='x';
        //We display the string which should be "This is a text"
        System.out.println(text);
    } catch (NoSuchFieldException | SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

4

Você pode substituir uma sequência, da seguinte maneira:

String myName = "halftime";
myName = myName.substring(0,4)+'x'+myName.substring(5);  

Observe que a seqüência myNameocorre nas duas linhas e nos dois lados da segunda linha.

Portanto, mesmo que as strings possam ser tecnicamente imutáveis, na prática, você pode tratá-las como editáveis, substituindo-as.


Não reduzi a sua resposta, mas devo admitir que tenho um problema com o termo "substituir" (embora eu ache que concordamos com o conceito por trás). O objeto em si permanece inalterado. Você acabou de fazer sua variável referenciar outro objeto. A propósito, é interessante mencionar que você cria pelo menos quatro instâncias de String no seu exemplo.
C.Champagne

0

A primeira coisa que eu deveria ter notado é que charAté um método e atribuir valor a ele usando sinal de igual não fará nada. Se uma sequência for imutável, o charAtmétodo, para fazer alterações no objeto, deverá receber um argumento contendo o novo caractere. Infelizmente, a string é imutável. Para modificar a string, eu precisava usar o StringBuilder, conforme sugerido pelo Sr. Petar Ivanov.


-7

isso vai funcionar

   String myName="domanokz";
   String p=myName.replace(myName.charAt(4),'x');
   System.out.println(p);

Saída: domaxokz


11
embora eu deteste fortemente esse método de permitir a "editabilidade" do trabalho de outras pessoas neste site StackOverFlow. completamente injusto: /
Diabolus Infernalis

2
Erro de sintaxe. E mesmo se corrigido, digamos que eu queira substituir o primeiro 'o' por 'x', o segundo 'o' também será substituído.
dpp

2
Isso irá substituir todos os caracteres que é o mesmo que charAt 4.
Shripad Bhat

11
Problema: myName.replace(myName.charAt(5),'x')você fornecerá o dxmanxkzque provavelmente não é necessário.
Dawood ibn Kareem
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.