Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
试图理解Java字符串实现_Java_String_Size_Primitive Types - Fatal编程技术网

试图理解Java字符串实现

试图理解Java字符串实现,java,string,size,primitive-types,Java,String,Size,Primitive Types,我正在研究String的openjdk实现,以及私有的、每个实例的成员如下所示: public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** The offset i

我正在研究String的openjdk实现,以及私有的、每个实例的成员如下所示:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{
    /** The value is used for character storage. */
    private final char value[];

    /** The offset is the first index of the storage that is used. */
    private final int offset;

    /** The count is the number of characters in the String. */
    private final int count;

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    [...]
}
公共最终类字符串
实现java.io.Serializable、Comparable、CharSequence
{
/**该值用于字符存储*/
私有最终字符值[];
/**偏移量是所使用存储的第一个索引*/
私人最终整数偏移;
/**计数是字符串中的字符数*/
私人最终整数计数;
/**缓存字符串的哈希代码*/
private int hash;//默认值为0
[...]
}
但我知道Java对字符串使用引用和池,以避免重复。我天真地期待一个pimpl习惯用法,其中字符串实际上只是一个impl的引用。到目前为止我还没看到。有人能解释一下,如果我输入字符串x,Java将如何知道如何使用引用吗;我的一个班级的成员


附录:这可能是错误的,但如果我在32位模式下,我应该计数:4个字节用于引用“value[]”,4个字节用于偏移量,4个字节用于计数,4个字节用于类字符串的所有实例的哈希?这意味着在我的一个类中写入“String x;”会自动为我的类的“权重”增加至少32个字节(这里我可能错了)。

Java始终使用对任何对象的引用。没有办法不使用引用。至于字符串池,这是由编译器为字符串文本实现的,并在运行时通过调用。很自然,
String
的大多数实现都忽略了它是否处理常量池引用的实例。

Java字符串是不可变的。这意味着实现可以对内部表示做很多事情,而不会破坏任何应用程序代码

请注意,Java在Oracle的JDK实现中被定义为本机的。本机代码可以访问对象的所有字段,并且可以更改水下的引用。因此,实现者所要做的就是将引用和偏移量更改为字符串被插入的位置。当然,这破坏了类的不变性,因此这意味着intern()更新最好是线程安全的


在对新生成的字符串调用
intern()
时,可以检查字段发生了什么。如果什么也没有发生,则可能是引用本身包含内存位置。Java语言规范没有定义如何实现引用。

偏移量/计数字段与池/
intern()问题有点正交。当您有以下情况时,会出现偏移和计数:

String substring = myString.substring(5);
实现此方法的一种方法如下:

String substring = myString.substring(5);
  • 使用
    myString.length()-5
    元素分配一个新的
    char[]
  • 将所有元素从索引索引5复制到
    myString.length()
    从myString复制到新的
    char[]
  • 子字符串
    是用这个新的
    char[]
    • substring.charAt(i)
      直接进入
      chars[i]
    • substring.length()
      直接进入
      chars.length
如您所见,这种方法是O(N)——其中N是新字符串的长度——需要两个分配:新字符串和新字符[]。因此,
子字符串
通过恢复原始字符[]工作,但有一个偏移量:

  • substring.offset
    =
    myString.offset+newOffset
  • substring.count
    =
    myString.count-newOffset
  • 使用
    myString.chars
    作为
    子字符串的chars数组
    
    • substring.charAt(i)
      转到
      chars[i+substring.offset]
    • substring.length()
      转到
      substring.count

请注意,我们不需要创建新的char[],更重要的是,我们不需要将旧char[]中的char复制到新的char[](因为没有新的char)。所以这个操作只是O(1),只需要一个分配,即新字符串的分配。

接受的答案和其他答案都过时了。在Java7更新6之后,Java中的字符串不再使用偏移量,也不会针对子字符串优化进行调优。相反,每个子字符串都会创建字符串的新副本

如果要使用原始字符串实现,则必须使用CharSequence


有关详细信息:

String a=“a”;字符串b=新字符串(“a”);使用两种不同的记忆模型。弗兰克,你必须明白事情并不是那么简单。您的类不是
字符串
实例的所有者。实例本身,甚至更重要的是,后台的
char[]
,正在被共享,以便重新使用内存。@LouisWasserman通常即使这样也不会结束计算,因为必须考虑内存对齐,这会将计数增加到8的最接近倍数。
String x
引入了一个花费四个字节的空引用。还不存在实际的
String
值,所以这就是全部成本。@MarkoTopolnik memory model=pooled vs.not pooled(我想)字符串就是字符串。不管它是否合并,对字符串的性质都没有影响,只会影响到它的存储位置和可以围绕它进行的优化。pimpl习惯用法?我猜你来自C++背景,你还不知道不同的java对象模型是C++的。java不仅仅是拼写错误的C++,它是一种非常不同的语言。我敦促您阅读本文,以便更详细地了解Java是什么样子的!我是个C++的家伙。我有一些Java方面的经验,但我觉得这相当令人不安。
所以这个操作只是O(N),只需要一次分配,