案例1:
String str = "StackOverFlow"; String str1 = "StackOverFlow"; if(str==str1){ System.out.println("equal");//prints equal }
案例2:
String str = "StackOverFlow"; String str1=str.intern(); if(str==str1){ System.out.println("equal");//prints equal }
跟进问题:
我想知道第一种情况是JVM在内部调用intern()
并将str
的引用分配给str1
?
第一种情况下两个引用如何相等?
第一种情况是否意味着无论何时声明像String str = "StackOverFlow";
这样的字符串,它都会添加到字符串池中,与intern()
方法相同?
String str = "StackOverFlow";
和intern()
使用的字符串池是否在堆外分配?如果确实在哪里?
对于问题4,答案如下:
在Java 6及更早版本中,实习字符串也存储在永久代中。在Java 7中,实习字符串存储在主对象堆中。
以下是文档说明的内容:
在JDK 7中,永久性中不再分配实习字符串 生成Java堆,而是在main中分配 Java堆的一部分(称为年轻和老一代) 与应用程序创建的其他对象。这种改变会 导致更多数据驻留在主Java堆中,并且数据中的数据更少 永久世代,因此可能需要堆大小 调整。大多数应用程序只会看到相对较小的差异 由于此更改导致堆使用,但加载的应用程序更大 许多课程或大量使用
String.intern()
方法都会看到 更显着的差异。
此处的详细信息:
Java 6中的String.intern()
Java 7中在那些美好的旧时代,所有实习字符串都存储在PermGen中 - 堆的固定大小部分主要用于存储加载的类 和字符串池。除了明确的实习字符串,PermGen字符串 pool还包含程序中先前使用的所有文字字符串 (这里使用的重要词 - 如果一个类或方法永远不会 加载/调用,其中定义的任何常量都不会被加载。
The biggest issue with such string pool in Java 6 was its location – the PermGen. PermGen has a fixed size and can not be expanded at
运行时。您可以使用-XX:MaxPermSize = 96m选项进行设置。就我而言 知道,默认的PermGen大小在32M到96M之间变化,具体取决于 该平台。你可以增加它的大小,但它的大小仍然是 固定。这种限制需要非常小心地使用String.intern - 你最好不要使用这种方法实习任何不受控制的用户输入。 这就是为什么Java 6时代的字符串池主要实现的原因 手动管理的地图。
String.intern()
Oracle工程师对字符串进行了非常重要的更改 Java 7中的池化逻辑 - 字符串池被重定位到堆中。 这意味着您不再受限于单独的固定尺寸 记忆区。所有字符串现在都位于堆中,与其他大多数字符串一样 普通对象,它允许您只管理堆大小 调整你的申请。从技术上讲,仅此一点就足够了 有理由重新考虑在Java 7程序中使用String.intern()。 但还有其他原因。
答案 0 :(得分:5)
引用是相同的,因为它们都是字符串文字。
intern()
str
不需要intern()
,因为它也是文字。当你需要使用equals()
(顺便说一下比final String str1 = "I am a literal";
final String str2 = new String(str1.toCharArray());
final boolean check1 = str1 == str2; // false
final boolean check2 = str1 == str2.intern(); // true
慢得多,所以不要使用它)时,你需要使用一个例子来构造一个带有byte或char数组的String
例如:
{{1}}
答案 1 :(得分:2)
1)我想知道对于第一种情况,JVM是否在内部调用intern()并将str的引用分配给str1?
嗯,是的,没有。
是内部调用intern()
方法 。但是,当运行该代码时,调用不会发生。实际上,当代码加载时会发生这种情况。然后,加载程序将引用保存到实习字符串。
但在这种情况下,加载过程只需要进行一次实习。这两个文字(在这种情况下)实际上将由正在加载的类中的单个“常量池条目”表示。 (Java编译器将在编译时发现类中的重复文字...并将其删除。)
2)第一种情况下两个引用如何相等?
因为这两个字符串已被实习。
3)第一种情况是否意味着每当你声明一个像String str =“StackOverFlow”这样的字符串时;它添加到字符串池中与intern()方法相同?
是...模数在运行包含声明的代码时不会发生实习。
4)
String str = "StackOverFlow";
和intern()
使用的字符串池是否在堆外分配?如果确实在哪里?
答案在某种程度上取决于系统。通常,字符串池在堆中。在某些系统上,堆被分成具有不同垃圾收集策略的区域或空间,并且字符串池在所谓的“permgen”空间中分配,该空间的大小独立于堆的其余部分。但这并非总是如此。
答案 2 :(得分:1)
我想知道对于第一种情况,JVM是否在内部调用intern()
没有
并将str的引用分配给str1?
是的,但是因为价值是文字,而不是因为实习。首先,.class文件中只有一个实例。
第一种情况下两个引用如何相等?
这不是另一个问题,只是同样的问题重申了。
第一种情况是否意味着每当你声明一个像String str =“StackOverFlow”这样的字符串时;它添加到字符串池中与intern()方法相同?
是的,但它是由编译器完成的,而不是intern()。
String str使用的字符串池是否为“StackOverFlow”;和intern()是在堆外部分配的吗?
没有
到底在哪里?
在加载类的常量池中,它位于堆中。
答案 3 :(得分:0)
有两种创建字符串对象的方法。
一个是
String str = "test-String"; // This string is created in string pool or returned from
string pool if already exists
第二个
String str = new String("test-string");// This string object will be created in heap memory and will be treated as any other object
当您使用new运算符创建的字符串实例上调用string.intern时...此字符串将在字符串池中创建或从池中返回(如果存在)。这是一种将字符串对象从堆移动到perm Gen(字符串池)
的机制