字符串和字符数组之间的区别

12

这些声明与彼此有何不同之处?

String s="MY PROFESSION";
char c[]="MY PROFESSION";

每种情况下的内存分配情况如何?


8
如果后者甚至不存在,你如何比较这两个呢? - Dariusz
一个字符串是一个复合对象,它包含一个字符数组和一些其他字段。 - Hot Licks
一个String是一个自带许多字符串操作方法的类的实例。Java有许多与字符串相关的特殊语言功能(例如你两次使用的字符串文字)。而另一方面,字符数组缺乏那些方法,是可变的,且具有更小的内存占用量。除非你有一个非常特殊的问题需要字符数组,否则始终使用String。 - John Smith
7个回答

14

为了修正编译错误,请使用以下char[]语句中的一个进行替换

String s = "MY PROFESSION";
char c1[] = "MY PROFESSION".toCharArray();
char c2[] = { 'M', 'Y', ' ', 'P', 'R', 'O', 'F', 'E', 'S', 'S', 'I', 'O', 'N' };
StringBuilder sb = new StringBuilder("MY PROFESSION");
StringBuffer sbu = new StringBuffer("MY PROFESSION");

下一节将以上述语句进行比较。

字符串常量

String s="MY PROFESSION";

字符数组

 char c1[]="MY PROFESSION".toCharArray();
 char c2[]={'M', 'Y', ' ', 'P', 'R', 'O', 'F', 'E', 'S', 'S', 'I', 'O', 'N'};
  • c1 中保存了 String 底层数组的副本(通过 System.arraycopy 实现)并存储在堆空间中
  • c2 在栈帧中动态构建,通过加载单个字符常量实现
  • c1c2 是可变的,即可以修改 Array 的内容。例如:c2[0]='B'
  • 数组的大小/长度是固定的,无法追加

StringBuilder / StringBuffer

StringBuilder sb = new StringBuilder("MY PROFESSION");
StringBuffer sbu = new StringBuffer("MY PROFESSION");
  • 两者都是可变的(sbsbu)。 sb.replace(0, 1, 'B');
  • 两者都存储��堆(heap)中。
  • 大小/长度可以被修改。 sb.append( '!');
  • StringBuffer的方法是同步的,而StringBuilder的方法不是。

4
第一个编译通过,第二个没有。
一个char[]就是这样:一个类型为char的原始数字数组。它只提供了一个length属性和一种方法来获取和设置给定索引处的字符。
String是一个对象,属于java.lang.String类型,具有大量用于操作字符串的实用方法。内部使用char数组。
另一个重要特点是String是不可变的。您可以将String传递给任何方法,并确保该方法不会更改String的内容。而对于char数组则不是这样。
关于内存,一个String消耗更多的字节,但通常不应该指导您的设计决策:通常,不应该使用char数组。

1
如果您看到了文档
     String str = "abc";

is equivalent to:

     char data[] = {'a', 'b', 'c'};  //  not 'abc'
     String str = new String(data);

此外,Java中的字符串文字非常特殊。 String 在内部由一个 character 数组支持。

1

字符数组是可变的,也就是说,你可以通过覆盖该字符的内存位置来替换字符数组中的字符。

字符串是不可变的,也就是说,要“替换”字符串中的一个字符,必须构建一个新的字符串,并将所需字符放入其中(从旧字符串中复制未更改的部分)。

虽然这看起来很简单,但它对于在线程之间(和对象之间)共享的能力产生了深远的影响。一个字符串可以在线程之间安全地共享,无需额外的检查来查看字符串是否正在更改(这可能会给线程提供不一致的读取字符串)。

其他优化也是可能的,由于字符串不能发生变化,因此你可以重写相等操作以进行“值相等”。这意味着“字符串工厂”可以返回缓存的相同字符串副本,即使请求两个不同的字符串对象,因为这两个对象的行为变得不可能不同。


0
这个声明有什么不同之处?
你的第一行代码产生了一个String实例。而你的第二行代码是无效的,也许你的意思是:
char[] c = {'M', 'Y', ' ', 'P', 'R', 'O', 'F', 'E', 'S', 'S', 'I', 'O', 'N'};

它创建了一个用这些字符填充的char[]

那么它的内存分配呢?

将字符串存储为String在内存方面与将其存储为char[]略有不同。它们有相似之处:都是对象,并具有通常的对象开销。

然而,String在内部持有一个char[],因此自然地String会消耗更多的内存。此外,String具有3个int字段(offsetcounthash),而char[]只有一个int字段length

例如,将"MY PROFESSION"存储为String

  • 3个int字段: 12字节
  • char[]字段: 8字节
    • int字段: 4字节
    • 对象开销: 8字节
    • 13个字符: 26字节
  • 对象开销: 8字节

总计约66字节。我说“约”是因为其中一些取决于虚拟机。相应长度为10的char[]仅消耗38字节,如您所见。这里的内存差异非常微不足道,所以您不必担心它(并且只需使用String!)。随着要存储的字符串越长,差距变得更加微不足道。


0

char 是一种原始类型。 String 是一个类,其中实际数据在内部存储为字符数组。

char c[]="MY PROFESSION";

会导致编译错误。

字符数组是内存中连续存储字符的区域,这些字符按顺序存储。

查看此线程以获取更多详细信息。


0

char是一种原始类型,而String是一个类。 指定数量的字符串数组和字符串都是字符的集合。


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