【问题标题】:Difference between a string and an array of characters字符串和字符数组的区别
【发布时间】:2013-08-17 12:25:48
【问题描述】:

这些声明彼此有何不同?

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

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

【问题讨论】:

  • 如果后者根本不存在,你如何比较这两者?
  • String 是一个复合对象,它包含一个 char 数组以及一些其他字段。
  • a String 是一个带有大量字符串操作的类(的一个实例)。 Java 有很多与字符串相关的特殊语言特性(例如,您使用过两次的字符串文字)。另一方面,char 数组缺少这些方法,是可变的并且具有较小的内存占用。除非您遇到需要 char 数组的非常特殊的问题,否则始终使用 String。

标签: java


【解决方案1】:

要纠正编译错误,请替换为以下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 通过加载单个字符常量在堆栈帧中动态构建
  • c1 & c2 是可变的,即 Array 的内容可以修改。 c2[0]='B'
  • 数组的大小/长度是固定的(不能追加)

StringBuilder / StringBuffer

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

【讨论】:

    【解决方案2】:

    第一个编译。第二个没有。

    char[] 就是这样:一个 char 类型的原始数字数组。它提供的只是一个length 属性,以及一种在给定索引处获取和设置字符的方法。

    字符串是java.lang.String 类型的对象,它有很多有用的方法来操作字符串。在内部,它使用 char 数组。

    String 的另一个重要特性是它是不可变的。您可以将 String 传递给任何方法,并确保此方法不会更改 String 的内容。 char 数组不是这种情况。

    关于内存,String 会消耗更多字节,但这通常不应该指导您的设计决策:通常,使用 char 数组不是您应该做的。

    【讨论】:

      【解决方案3】:

      如果你看到docs,

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

      更多String literals are very special in java

      String 在内部由 character 数组支持。

      【讨论】:

        【解决方案4】:

        字符数组是可变的,换句话说,您可以通过覆盖字符的内存位置来替换字符数组中的字符。

        字符串是不可变的,换句话说,要“替换”字符串中的一个字符,您必须构建一个新的字符串,其中包含所需的字符(从旧字符串中复制不变的部分)。

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

        其他优化也是可能的,因为字符串不能变异,您可以将相等操作重新连接为“按值相等”。这意味着“字符串工厂”可以返回相同字符串的缓存副本,即使请求两个不同的字符串对象也是如此,因为这两个对象不可能有不同的行为。

        【讨论】:

          【解决方案5】:

          char 是原始类型。 String 是一个将实际数据内部存储为字符数组的类

          char c[]="MY PROFESSION";
          

          会报编译错误。

          字符数组是内存中连续存储字符的地方。

          查看此Thread 了解更多详情。

          【讨论】:

            【解决方案6】:

            此声明如何相互区分?

            您的第一行生成一个String 实例。您的第二行根本无效;也许你的意思是:

            char[] c = {'M', 'Y', ' ', 'P', 'R', 'O', 'F', 'E', 'S', 'S', 'I', 'O', 'N'};
            

            创建char[] 填充这些字符。

            它的内存分配情况如何?

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

            然而,String 拥有char[] 内部,所以String 自然会消耗更多内存。此外,String 有 3 个int 字段(offset、count 和hash),而char[] 有一个int 字段length。

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

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

            这大约是 66 字节。我说“关于”是因为其中一些取决于 VM。如您所见,长度为 10 的对应 char[] 仅消耗 38 个字节。这里的内存差异可以忽略不计,因此您不必担心(只需使用String!)。您尝试存储的字符串越长,它就变得越不重要。

            【讨论】:

              【解决方案7】:

              char 是原始类型,而 String 是类。 由指定数量的字符串组成的数组,字符串是一串字符。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-01-29
                • 1970-01-01
                • 1970-01-01
                • 2014-05-20
                • 1970-01-01
                相关资源
                最近更新 更多