替换字符串中特定索引处的字符?


382

我正在尝试替换字符串中特定索引处的字符。

我正在做的是:

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

这给出了一个错误。有什么方法可以做到这一点?


12
我意识到这已经死了,但是值得注意的是,它永远不允许在Java中分配函数调用的结果。没有诸如C(?)和C ++的引用之类的东西。
ApproachingDarknessFish

1
VB中的@ValekHalfHeart,您使用括号访问数组的索引,这可能就是为什么我从Java启动时感到困惑的原因:D
dpp 2013年

@ApproachingDarknessFish我不确定您的意思是“禁止在Java中分配函数调用的结果”。当然可以吗double r = Math.sin(3.14)?它与这个问题有什么关系?谢谢。
flow2k

1
@ flow2k哦天哪,老的评论,所以我不能编辑,但是这是一个错字,应该说,“这是绝不允许分配 Java中的函数调用的结果”。即,您可以编写“ foo = bar();” 但绝不会“ bar()= foo;”。
接近

感谢您对@ApproachingDarknessFish的澄清。我认为将某些东西分配给函数的结果会很奇怪-是否有实际上允许这样做的语言?我想知道用例是什么。
flow2k

Answers:


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方法不会修改字符串,而只会返回一个新字符串?
dpp

1
佩塔尔先生,​​这有点复杂。那是最好的方式吗?啊,我以前听说过StringBuilder,这有什么区别吗?会给我一个更简单的方法吗?
dpp

158

将String转换为char [],用索引替换字母,然后将数组转换回String。

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

1
喜欢这个解决方案。我最终将第三行更改为myNameChars [index] = character.toCharArray()[0]; 为了简化。不错的解决方案。
戴尔

2
它看起来比另一个丑陋的用户好得多myName.substring(0,4)+'x'+myName.substring(5);
user924

它要简单得多
Shiva Acharjee

19

String是Java中的不可变类。似乎对其进行修改的任何方法总是返回带有修改的新字符串对象。

如果要操作字符串,请考虑StringBuilderStringBuffer在需要线程安全的情况下考虑。


12

我同意Petar Ivanov的观点,但最好采用以下方式实施:

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的方法,但是我永远不推荐使用它,因为它不安全,不可靠并且可以被视为作弊:您可以使用反射来修改charString对象包含的内部数组。反射允许您访问通常隐藏在当前作用域中的字段和方法(私有方法或其他类的字段...)。

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

您可以覆盖一个字符串,如下所示:

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

请注意,字符串myName出现在两行以及第二行的两侧。

因此,即使字符串在技术上可能是不可变的,但实际上,您可以通过覆盖它们将它们视为可编辑的。


我没有拒绝您的回答,但我必须承认“覆盖”一词有问题(尽管我认为我们同意后面的概念)。对象本身保持不变。您只需使变量引用另一个对象即可。顺便说一句,您很有趣地提到在示例中至少创建了四个String实例。
C.Champagne

0

我应该注意的第一件事是这charAt是一种方法,使用等号向其赋值将不会执行任何操作。如果字符串是不可变的,则要charAt更改字符串对象的方法必须接收包含新字符的参数。不幸的是,字符串是不可变的。要修改字符串,我需要使用Petar Ivanov先生建议的StringBuilder。


-7

这会工作

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

输出:domaxokz


1
尽管我强烈反对这种在StackOverFlow网站上允许他人“编辑”工作的方法。完全不公平:/
Diabolus Infernalis 2012年

2
语法错误。即使更正,例如我想用“ x”替换第一个“ o”,第二个“ o”也将替换。
dpp 2012年

2
这将取代所有的字符是相同的charAt 4
Shripad铢

1
问题:myName.replace(myName.charAt(5),'x')会给您dxmanxkz,这可能不是必需的。
达伍德·伊本·卡里姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.