【问题标题】:How is Java String constructor implemented?Java String 构造函数是如何实现的?
【发布时间】:2020-03-16 12:31:54
【问题描述】:

我在翻Java String源代码,找到了一个CTOR,我有一些疑问:

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

我知道 Original 充当文字 String(带双引号),但无法理解 java/jvm 如何将 original.value 计算为 char 数组。这里的“价值”是什么?如果值为char数组那么.value函数/字段是如何计算的???

【问题讨论】:

  • “点值函数”是什么意思? original.value 只是原始字符串中char[] 类型的实例字段。
  • 在看String的源码的时候可以理解,JavaString class其实是用char数组实现的,也就是你看到的value,类的一个领域,没什么好惊讶的。
  • 你说得对,new String ("newstring"),这里我们正在尝试创建String 对象,但“newString”已经充当String 对象,如何???
  • "newstring"(以及所有其他字符串文字)充当String,因为它String
  • Kevin,只是想了解一下 JVM 是如何在内部将每个 String 文字作为 String 对象的???

标签: java string core


【解决方案1】:

是的,正如 cmets 中已经提到的,这非常简单。 由于您正在查看String 类本身——它可以访问自己的字段。这就是这个给定字符串所包含的字符实际存储的地方——在char数组中。这个方法只是简单的通过名字来引用字段,非常基础的交互。

【讨论】:

  • 正确!!!只是想了解JVM如何在内部将每个字符串文字作为字符串对象???
  • @AbhiS 一般而言,您应该在这里提出更具体的问题,诸如“这一切是什么”之类的一般性问题通常被认为过于宽泛或无关紧要。
【解决方案2】:

String 按设计包含 Unicode 文本,因此可以组合所有语言脚本。 为此,该实现包含一个数组(字段名称value),其中每个字符都是一个两字节的UTF-16 值。

您在 Java 类中遇到了唯一的 AFAIK 愚蠢点。

显示的复制构造函数是毫无意义的,因为字符串是不可变的对象, 它们可以通过简单的分配来共享。它是 C++ 继承的化石, 可能与字符串实习有关。

制作副本是没有意义的。这也适用于内部char 数组,它确实可以通过引用分配。 (不是很紧。)

所以下面展示了没有经验的java使用:

String s = new String(t);

在最新的 java 版本中,String 的值实际上可能是某种编码的字节数组,因此这些字符是延迟提供的。


关于字符串字面量:

字符串文字存储在名为常量池的 .class 文件中的数据结构中。存储为 UTF-8 字节。 JVM ClassLoader 确保字符串作为 String 加载。

final static String 常量的导入被复制到常量池中,原始类可能不再显示为从中导入的。 在其他类中保存字符串常量可能需要手动进行干净的构建,因为可能不再存在类依赖项。

【讨论】:

  • 基本上,我同意。但是虽然s=t 也意味着s==t 为真,s=new String(t) 的结果具有相同的比较现在为假的效果('==',而不是equals())。正如文档中所说:“[...] 除非需要原始的显式副本,否则不需要使用此构造函数 [...]” - 好的,我没有遇到过需要字符串的显式副本,只有在玩耍时使用 JNI,但提到了有限的用处,使整个事情变得不那么愚蠢。
  • @Iquadrat 我只能想象与String.#ntern() 结合使用,为国庆准备的东西@Esoteric public String(String original) ...
  • 文档中提到了intern():“[…] 因此,对于任何两个字符串st,当且仅当s.equals( t ) 为真时,s.intern() == t.intern() 为真。 […]" – 所以在我看来,将 new String()intern() 结合起来没有意义 – 或者我在这里错过了一些重要的点。
  • 它非常接近答案,但没有人给我答案,“只是想了解JVM如何在内部将每个字符串文字作为字符串对象???”
  • @AbhiS OK 添加了一个部分。由于 ClassLoader 使用由编译器存储在那里的字符串文字加载常量池,因此它与 JDK 源代码几乎没有关系。
【解决方案3】:

docs

初始化一个新创建的 String 对象,使其代表 与参数相同的字符序列;换句话说,新 创建的字符串是参数字符串的副本。除非明确 需要原件的副本,不需要使用此构造函数 因为字符串是不可变的。

从技术上讲,新字符串将获得originalvaluehash

这意味着这是另一个字符串的副本。

【讨论】:

    猜你喜欢
    • 2019-07-31
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    相关资源
    最近更新 更多