Is "String s = "abc";" equal to "String s = new String("abc");"?

B

Bruce Sam

In my opinion,"String s = "abc";" has only created a reference s not a
object."String s= new String("abc");" has created a new object and its
reference is s.Is it right?If I'm right,I still have a question.When I
can use first one not need the second one?
 
M

Michael Borgwardt

Bruce said:
In my opinion,"String s = "abc";" has only created a reference s not a
object."String s= new String("abc");" has created a new object and its
reference is s.Is it right?

Not really. Both declare a reference, and while the first doesn't
explicitly *create* an object at runtime, there still *is* an Object.
It's part of the constant pool of the class and created when the
class is loaded.
 
K

kaeli

In my opinion,"String s = "abc";" has only created a reference s not a
object."String s= new String("abc");" has created a new object and its
reference is s.Is it right?If I'm right,I still have a question.When I
can use first one not need the second one?

It is my understanding that if you don't specify the "new" keyword, if
another string object already has a reference to the value "abc", a new
object is not created (no more memory is allocated) - instead, it points to
the same spot in memory. If nothing does, it does create a new object (memory
allocation). If you specify the new keyword, a new object is always created
(memory allocation), regardless.
Mostly the difference is seen with the equals method and '=='.

See this page for a better explanation:
http://www.jchq.net/certkey/0502certkey.htm

--
 
C

Chris Smith

kaeli said:
It is my understanding that if you don't specify the "new" keyword, if
another string object already has a reference to the value "abc", a new
object is not created (no more memory is allocated)

It's a little different than that. There is a pool of String objects
maintained by the JVM. Some String objects are in that pool, and others
are not. When you say:

String a = "abc";

then the JVM arranges for "abc" to be in that pool, and then produces a
reference to it when executing that code. When you write:

String a = new String("abc");

then the JVM still arranges for "abc" to be in that pool, and still
provides a reference to it, but that reference is then passed into a
constructor to create a NEW String object that's NOT in the pool and
copies the first one. It's that second String object which ends up
being assigned to the reference.

This is different from your statement above. If a String object exists
that contains the same contents -- abc -- but the object is NOT in the
pool (if, for example, it was read from a file or database), then the
literal "abc" will resolve to a new String object that's different from
that existing one.

It's also a little imprecise to says that the pooled String objects are
created by the code above. Instead, it's better to say that the code
above ensures that at some point, the JVM will arrange for the String
object to have been created when that code executes. However, that
object will be created only once, regardless of how many times the code
is executed, or even how many times the literal "abc" appears in the
code.

Mostly the difference is seen with the equals method and '=='.

Yes. Use of '==' is, in fact, the only direct way to see the
difference. Indirectly, of course, you could observe the memory usage
of the application after a large number of repetitions of the code.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
M

Mike Schilling

Michael Borgwardt said:
Not really. Both declare a reference, and while the first doesn't
explicitly *create* an object at runtime, there still *is* an Object.
It's part of the constant pool of the class and created when the
class is loaded.

The second creates two objects, since the constant String "abc" and the
results of "new String()" must be distinct.
 
M

Mike Schilling

Chris Smith said:
Yes. Use of '==' is, in fact, the only direct way to see the
difference. Indirectly, of course, you could observe the memory usage
of the application after a large number of repetitions of the code.

At an intermediate level of directness, you could create a thread that locks
"abc" and observe that a different thread can lock the new-ed String.
 
M

Michael Borgwardt

Mike said:
The second creates two objects, since the constant String "abc" and the
results of "new String()" must be distinct.

But the literal isn't created when the line is executed, it's created when
the class is loaded.
 
T

Tony Morris

This is incorrect.
A String literal involves the runtime creation of an object.
In fact, two of the same String literals that are in different scopes may
create have separate objects created.
Here's the challenge for the reader: prove this beyond doubt (it can be
done).
there still *is* an Object.

The 'constant pool' is an abstract concept that should not be thought of as
a physical thing - it simply does not physically exist.
The second creates two objects, since the constant String "abc" and the
results of "new String()" must be distinct.

Specifically, the object created by the new operator must not exist anywhere
else at that time.
 
T

Tony Morris

Michael Borgwardt said:
But the literal isn't created when the line is executed, it's created when
the class is loaded.

The literal, being a constant (JLS 15.28), is "created" at compile-time.
The object that is used is created at runtime.
 
M

Michael Borgwardt

Tony said:
The literal, being a constant (JLS 15.28), is "created" at compile-time.

Actually, at the time the source code is written.
The object that is used is created at runtime.

I meant "the object represented by the literal".
 
M

Michael Borgwardt

Tony said:
This is incorrect.
A String literal involves the runtime creation of an object.

Thus, "explicitly".
In fact, two of the same String literals that are in different scopes may
create have separate objects created.
Here's the challenge for the reader: prove this beyond doubt (it can be
done).

Actually, I can prove beyond doubt that it's incorrect. The JLS section 3.10.5 says:

-----------------------
# Literal strings within the same class (§8) in the same package (§7)
represent references to the same String object (§4.3.1).
# Literal strings within different classes in the same package represent references
to the same String object.
# Literal strings within different classes in different packages likewise
represent references to the same String object.
-----------------------

The 'constant pool' is an abstract concept that should not be thought of as
a physical thing - it simply does not physically exist.

The Java Virtual Machine Specification disagrees:

-----------------------
4.1 The ClassFile Structure

A class file consists of a single ClassFile structure:


ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1]; <----------------------
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
 
T

Tony Morris

Tony said:
This is incorrect.
A String literal involves the runtime creation of an object.

Thus, "explicitly".
In fact, two of the same String literals that are in different scopes may
create have separate objects created.
Here's the challenge for the reader: prove this beyond doubt (it can be
done).

Actually, I can prove beyond doubt that it's incorrect. The JLS section
3.10.5 says:

-----------------------
# Literal strings within the same class (§8) in the same package (§7)
represent references to the same String object (§4.3.1).
# Literal strings within different classes in the same package represent
references
to the same String object.
# Literal strings within different classes in different packages likewise
represent references to the same String object.
-----------------------



This is (yet another) an ambiguity in the JLS.
The challenge remains - it can be proven, without a doubt.
 
J

John C. Bollinger

Tony said:
Actually, I can prove beyond doubt that it's incorrect. The JLS section
3.10.5 says:

-----------------------
# Literal strings within the same class (§8) in the same package (§7)
represent references to the same String object (§4.3.1).
# Literal strings within different classes in the same package represent
references
to the same String object.
# Literal strings within different classes in different packages likewise
represent references to the same String object.
-----------------------



This is (yet another) an ambiguity in the JLS.
The challenge remains - it can be proven, without a doubt.

The ambiguity, I suppose, being a question of time. The JLS is
ambiguous about whether those invariants are required to hold for any
two strings chosen at any two points during program execution, or
whether it only applies to program state any particular time. The
observable behavior of Sun's recent implementations of the String intern
pool is that otherwise unreferenced Strings are eventually discarded.
Thus if I write

public class StringTest {
static void printHashOne() {
// Print identity hash for locally-scoped "abc"
System.out.print("Identity hashcode 1: ");
System.out.println("abc".identityHashCode());
}
static void printHashTwo() {
// Print identity hash for locally-scoped "abc"
System.out.print("Identity hashcode 2: ");
System.out.println("abc".identityHashCode());
}
static void doSomethingElse() {
/* implementation left as an exercise to the reader */
}
public static void main(String[] args) {
printHashOne();
doSomethingElse();
printHashTwo();
}
}

then it is possible that the two identity hashes printed by one run of
the program will be different. (It depends on how long doSomethingElse()
runs, how many GC cycles take place, whether or not doSomethingElse
references an equal String literal or other equal interned String,
etc.). The doSomethingElse() method can be implemented in a way that
pretty reliably exhibits the different object identities for "abc" on
Sun's 1.3 and 1.4 VMs.


John Bollinger
(e-mail address removed)
 
M

Mike Schilling

Michael Borgwardt said:
But the literal isn't created when the line is executed, it's created when
the class is loaded.

Quibble accepted. But the second form does create a String that the first
does not.
 
M

Michael Borgwardt

John said:
The ambiguity, I suppose, being a question of time. The JLS is
ambiguous about whether those invariants are required to hold for any
two strings chosen at any two points during program execution, or
whether it only applies to program state any particular time. The

Ah, this issue:
http://www.javaworld.com/javaworld/javaqa/2003-12/01-qa-1212-intern.html

observable behavior of Sun's recent implementations of the String intern
pool is that otherwise unreferenced Strings are eventually discarded.
Thus if I write

public class StringTest {
static void printHashOne() {
// Print identity hash for locally-scoped "abc"
System.out.print("Identity hashcode 1: ");
System.out.println("abc".identityHashCode());
}
static void printHashTwo() {
// Print identity hash for locally-scoped "abc"
System.out.print("Identity hashcode 2: ");
System.out.println("abc".identityHashCode());
}
static void doSomethingElse() {
/* implementation left as an exercise to the reader */
}
public static void main(String[] args) {
printHashOne();
doSomethingElse();
printHashTwo();
}
}

then it is possible that the two identity hashes printed by one run of
the program will be different.

Only when the class has bean unloaded inbetween and loaded again. That's
rather more than the "different scopes" that Tony said were required.
 
J

John C. Bollinger

Michael said:

Yep, that's it.

Only when the class has bean unloaded inbetween and loaded again. That's
rather more than the "different scopes" that Tony said were required.

Yes, you're right, and so my example was oversimplified for the case of
String literals. And as you say, "different scopes" is not a sufficient
condition for literals, although it _is_ sufficient for interned Strings
not representing a literal in any currently loaded class.


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top