Заменить символ по определенному индексу в строке?

382

Я пытаюсь заменить символ по определенному индексу в строке.

Что я делаю, это:

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

Это дает ошибку. Есть ли способ сделать это?

ДПП
источник
12
Я понимаю, что на это ответили до смерти, но стоит отметить, что никогда не разрешается присваивать результат вызова функции в Java. Нет таких вещей, как ссылки на C (?) И C ++.
Приближается к
1
@ValekHalfHeart в VB, вы используете круглые скобки для доступа к индексу массива, что может быть причиной того, что я запутался, когда начинал в Java: D
dpp
@ApproachingDarknessFish Я не уверен, что вы подразумеваете под "никогда не разрешается присваивать результат вызова функции в Java". Конечно, вы можете сделать double r = Math.sin(3.14)? Как это связано с этим вопросом? Спасибо.
flow2k
1
@ flow2k О господи, старый комментарий , так что я не могу изменить , но это опечатка, он должен сказать , что «он никогда не разрешается назначать в результате вызова функции в Java». Т.е. вы можете написать "foo = bar ();" но никогда "bar () = foo;".
Приближается к
Спасибо за разъяснение @ApproachingDarknessFish. Я думаю, что было бы странно присваивать что-то результат функции - есть ли языки, которые на самом деле позволяют это? Интересно, какой будет вариант использования.
flow2k

Ответы:

566

Строка неизменна в Java. Вы не можете их изменить.

Вам нужно создать новую строку с замененным символом.

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

Или вы можете использовать StringBuilder:

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

System.out.println(myName);
Петар иванов
источник
3
Ах, вы имеете в виду как replaceметод, который не будет изменять строку, а просто вернет новую строку?
ДПП
1
Это довольно сложно, мистер Петар. Это лучший способ сделать это? Ах, я слышал о StringBuilder раньше, это имеет какое-то значение? Это даст мне более простой метод?
ДПП
158

Превратите строку в символ [], замените букву на индекс, затем преобразуйте массив обратно в строку.

String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);
16dots
источник
1
Люблю это решение. В итоге я изменил 3-ю строку на myNameChars [index] = character.toCharArray () [0]; для упрощения. Хорошее решение.
Дейл
2
это выглядит намного лучше, чем другой, более уродливыйmyName.substring(0,4)+'x'+myName.substring(5);
user924
Это намного проще
Шива Ачарджи
19

Stringнеизменный класс в Java. Любой метод, который, кажется, изменяет его, всегда возвращает новый строковый объект с модификацией.

Если вы хотите манипулировать строкой, подумайте StringBuilderили StringBufferв случае, если вам требуется безопасность потоков.

без имени
источник
12

Я согласен с Петром Ивановым, но было бы лучше, если бы мы реализовали его следующим образом:

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
и что делает ваше решение лучше?
dpp
6

Как ранее ответили здесь, Stringслучаи являются неизменными . StringBufferи StringBuilderявляются изменяемыми и пригодными для таких целей, независимо от того, нужно ли вам использовать потокобезопасность или нет.

Однако есть способ изменить String, но я бы никогда не рекомендовал его, потому что это небезопасно, ненадежно и его можно рассматривать как мошенничество: вы можете использовать отражение, чтобы изменить внутренний charмассив, содержащийся в объекте String. Отражение позволяет получить доступ к полям и методам, которые обычно скрыты в текущей области (частные методы или поля из другого класса ...).

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();
    }
}
C.Champagne
источник
4

Вы можете перезаписать строку следующим образом:

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

Обратите внимание, что строка myNameвстречается на обеих строках и на обеих сторонах второй строки.

Поэтому, хотя строки могут быть технически неизменными, на практике вы можете рассматривать их как редактируемые, перезаписывая их.

CodeMed
источник
Я не отклонил ваш ответ, но должен признать, что у меня есть проблема с термином «перезаписать» (хотя я думаю, что мы согласны с концепцией, лежащей в основе). Сам объект остается неизменным. Вы просто делаете вашу переменную ссылающейся на другой объект. Кстати, вам интересно упомянуть, что вы создали как минимум четыре экземпляра String в вашем примере.
C.Champagne
0

Первое, на что я должен был charAtобратить внимание - это метод, и присвоение ему значения с помощью знака равенства ничего не даст. Если строка неизменна, charAtметод, чтобы внести изменения в строковый объект, должен получить аргумент, содержащий новый символ. К сожалению, строка неизменна. Чтобы изменить строку, мне нужно было использовать StringBuilder, как предложил г-н Петар Иванов.

ДПП
источник
-7

это будет работать

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

Выход: domaxokz

Diabolus Infernalis
источник
1
хотя я категорически против того, чтобы этот метод позволял редактировать работу других на этом сайте StackOverFlow. совершенно несправедливо: /
Diabolus Infernalis
2
Ошибка синтаксиса. И даже если исправить, скажем, я хочу заменить первое «o» на «x», второе «o» также будет заменено.
ДПП
2
Это заменит весь символ , который так же , как Шар 4.
Shripad Бхат
1
Проблема: myName.replace(myName.charAt(5),'x')даст вам dxmanxkz, что, вероятно, не то, что требуется.
Дауд ибн Карим