如何将字符串转换为字符数组而不复制对象?

7

我有一个字符串,需要将其作为字符数组遍历。 当然,常规方法是使用 toCharArray()

String str = "Hello";
char[] charArr = str.toCharArray();

现在,toCharArray()的源代码如下。
public char[] toCharArray() {
    // Cannot use Arrays.copyOf because of class initialization order issues
    char result[] = new char[value.length];
    System.arraycopy(value, 0, result, 0, value.length);
    return result;
}

因此,Java正在创建一个新的char[]类型内存对象,并将字符串对象复制到这个新对象中。

我的问题是是否可能在不复制数组的情况下使用字符串作为char[]。 我的意图是节省内存空间。 如果不可能,请问原因是什么?

提前致谢!


4
将一个可变 char[] 数组的直接引用交给一个本应该是不可变的对象将是一个非常糟糕的想法,特别是如果所涉及到的不可变对象是 String 类型的话,因为它必须履行安全相关的角色。 - Holger
2
如果你想节省内存空间,不要请求 char[] 数组。你没有解释为什么你认为需要它。 - Holger
我需要一个数组,以便可以通过索引进行迭代。然而,我没有意识到的是,Nicolas Filotto指出字符串只是一个存储在char[]数组中的类。唉!初学者的错误 :) - Jordan Epstein
3个回答

15
不,不可以直接操作字符串的底层char[]数组,除非你想避免使用反射带来的微妙错误。通过反射操作字符串的char[]数组容易导致bug。你可以使用charAt方法获取字符串中的单个字符,但如果你真的需要一个char[]数组,那么就应该调用toCharArray方法。

如果这不行,有什么原因吗?

第一个原因是封装性。数组是一个私有的实现细节。
第二个原因是不可变性。 String是不可变的,但是数组永远都不是。因此,如果你修改了底层的char数组,字符串将被改变,这会让依赖于正常不可变性的开发人员感到惊讶。

1
此外,字符串池中对同一字符串的其他引用也将具有相同的变异字符串,从而导致更大的混淆。 - Pokechu22
1
@Pokechu22: 更糟糕的是,安全策略(权限、代码来源、用户名)都以字符串形式存储,因此允许更改它们将削弱整个安全模型。 - Holger

4

以下是一种不使用 toCharArray() 也可以将 String 转换为 char 数组的方法:

for (int i = 0; i < str.length(); i++) {
    char c = str.charAt(i);
}

1
好吧,这并不是OP所问的“它”……例如,如果OP只有一个接受无法修改的char[]的方法,那么这并没有任何帮助。 - Jon Skeet
这些生成的字符存储在哪里? - Suresh Atta
1
我有一个字符串,需要将其作为字符数组遍历。这是OP的主要请求,我建议帮助遍历字符串,如果不符合OP的期望,他需要修改问题。 - Nicolas Filotto
这实际上正是我想要的!这指出了我没有意识到的一点,即String类只是将其内容存储在一个名为value[]的char数组中。使用str.charAt(int index)只是简单地返回value[index]。 - Jordan Epstein

3

既然你希望返回数组,那么没有办法不创建新的数组而得到数组。

这是最干净的方法。即使你自己创建一个函数并做一些技巧,最终也会创建新的数组。

继续使用你当前的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接