有问这种问题. 当然2个. 两个都是"avc",一个在String pool里面,一个是new出来的. s 是引用不是对象.
String pool不是只对无名称String对象有效吗?
因为s是reference类型所以它只是存在栈里的指针 s指向存储在堆里的"avc"
String(String original) 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。 也就是说"avc" 和这个 s 不是一个对象 String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。 全是JDK API 里的 多看看吧 不要光看方法怎么用
两个吧,一个"avc",一个指向"avc"的引用!
2 个,一个"avc",一个指向"avc"的引用!
/** * Initializes a newly created {@code String} object so that it represents * the same sequence of characters as the argument; in other words, the * newly created string is a copy of the argument string. Unless an * explicit copy of {@code original} is needed, use of this constructor is * unnecessary since Strings are immutable. * * @param original * A {@code String} */ public String(String original) { int size = original.count; char[] originalValue = original.value; char[] v; if (originalValue.length > size) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); } else { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; } this.offset = 0; this.count = size; this.value = v; } 这是JDK中的实现。可以看到传进来的参数就已经是一个String对象了。 然后再根据构造函数生成一个新的对象,所以在这个过程中会存在两个对象。 original和新生成的对象。
/** * Initializes a newly created {@code String} object so that it represents * the same sequence of characters as the argument; in other words, the * newly created string is a copy of the argument string. Unless an * explicit copy of {@code original} is needed, use of this constructor is * unnecessary since Strings are immutable. * * @param original * A {@code String} */ public String(String original) { int size = original.count; char[] originalValue = original.value; char[] v; if (originalValue.length > size) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); } else { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; } this.offset = 0; this.count = size; this.value = v; } 这是JDK中的实现。可以看到传进来的参数就已经是一个String对象了。 然后再根据构造函数生成一个新的对象,所以在这个过程中会存在两个对象。 original和新生成的对象。
肯定是两个。区别在于:内存里面有一个字符串内存池。池里面是装String s = "hello";这种对象的。 而通过:String s = new String("hello");的是内存池外的。但是String s = new String("hello");这里会有一个无引用的对象,就会成为垃圾。所以使用时会推荐用这种方式String s = "hello";。 再如下: String s1 = "hello"; String s2 = "hello"; 这两条语句只会创建一个对象,为什么? 因为第一条语句已经在内存池中创建了一个hello,当第二个创建时会看内存池有没有hello,假如有了就不用创建了。所以只创建了一个对象。 如有不对请指正
当然2个.
两个都是"avc",一个在String pool里面,一个是new出来的.
s 是引用不是对象.
s指向存储在堆里的"avc"
初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
也就是说"avc" 和这个 s 不是一个对象
String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
全是JDK API 里的 多看看吧 不要光看方法怎么用
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
这是JDK中的实现。可以看到传进来的参数就已经是一个String对象了。
然后再根据构造函数生成一个新的对象,所以在这个过程中会存在两个对象。
original和新生成的对象。
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param original
* A {@code String}
*/
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
这是JDK中的实现。可以看到传进来的参数就已经是一个String对象了。
然后再根据构造函数生成一个新的对象,所以在这个过程中会存在两个对象。
original和新生成的对象。
2.如果string pool中不存在"avc",则答案为创建2个对象,在string pool和堆中分别创建一个,s是指向堆中的"avc"的
"avc"
和
new String("avc")代表同一字符序列
new String("avc")是"avc"的拷贝副本
一个在栈中
一个(NEW出来的)在堆中
'avc'是一个,是常量
还有一个是s对象
两个对象。 第一个是“avc" . 第二个是String(Sring) 构造函数new出来的.
一个存在于内存中,一个在String 连接池中
那么总共是2个对象
是两个对象没错,一个是池里面的“avg”,一个是堆里面new的。
栈存引用,堆存对象,数据段存常量!
为什么会有人认为放在pool里的常量会是一个对象呢?
一个是匿名字符串对象"avc"
一个是字符串对象s
实例化字符串对象s的时候用的指向了"avc"
(2) "认为栈有对象"--错误,JVM管理的内存有一块区域叫做Java栈,是为了方法运行的时候开辟必要的局部数据区和操作数栈的。这个里面存储的也是指向堆中的对象引用。不可能有对象本身。
(3) "认为常量池中的字符串字面值是对象"-- 错误,常量池里面记录的字面值只是一串字符Unicode码的编码字节。而不是对象。在Class文件的字节流中,常量池中的字符都是用UTF-8编码的。我已经在#54楼讲的很清楚了,2个字符串对象,全部在堆中,只是创建时间不同。一个叫inner String对象——对应于常量池中的字符串字面值,这个对象在第一次常量池解析的时候就已经创建,至于常量池解析在什么时候发生,不同的虚拟机实现不同,有的在类静态变量初始化之前,有的在执行方法指令时同时边解析边执行。一个是new指令创建的String对象。在执行new指令的时候在堆中创建的。希望大伙去真正去看看JVM规范或者具体的JVM实现方面的书,不要凭空想想就行了。
你就想着女孩子有多少个nai就行了
申明了2个对象 1个是"aaa"
另外1个是指向"aaa"的对象 s
两个常量池是有区别,但是运行时的常量池中还是对象本身(对象的实例变量所存储的空间),对象本身永远都存储在堆中。常量池中CONSTANT_String_info常量表项的入口地址中存有指向堆中对象的引用(地址)。还有一点,"avc"只是常量池中的一个字面值(字符串Unicode编码的字节流),怎么可能是对象呢。不过JVM会自动为这个字符串常量创建一个inner对象,请问:这个对象你认为在堆中,还是在常量池中。
还有Java运行时的常量池应该在方法区中的,方法区中的数据是没有对象的。这个问题答案是2个,但不是因为引用s是一个对象,也不是因为"avc"是一个对象,更不是有些人说的栈中有对象。这种解释只能越来越迷糊,对象到底在哪?????
而通过:String s = new String("hello");的是内存池外的。但是String s = new String("hello");这里会有一个无引用的对象,就会成为垃圾。所以使用时会推荐用这种方式String s = "hello";。
再如下:
String s1 = "hello";
String s2 = "hello";
这两条语句只会创建一个对象,为什么?
因为第一条语句已经在内存池中创建了一个hello,当第二个创建时会看内存池有没有hello,假如有了就不用创建了。所以只创建了一个对象。
如有不对请指正
一个是java虚拟机对字符串"avc"创建了一个inner对象
还有就是在堆中创建了一个inner对象的副本new String("avc")对象s 只是一个引用 不是一个对象