String question

S

stef

Hello,

Silly question, but if - internally speaking- the java compiler
replace the "String" class with "StringBuffer",
what is the real purpose of "String" ? (except shorter keyword and,
may be, when who do static stuff like String s ="hello "+"world")

thanks...
 
R

Roedy Green

Silly question, but if - internally speaking- the java compiler
replace the "String" class with "StringBuffer",
what is the real purpose of "String" ? (except shorter keyword and,
may be, when who do static stuff like String s ="hello "+"world")

see http://mindprod.com/jgloss/immutable.html

for the advantages of immutable Strings.

Strings are immutable, StringBuilders are mutable.

String s = "hello" + "world";

is covertly converted by the compiler to:

String s = "helloworld";


at compile time, so there is no run time concatenation.

However

String s = hello + world;

is effectively the same as:

StringBuilder temp = new StringBuilder();
temp.append( hello );
temp.append( world );
s = temp.toString();
 
R

Roedy Green

StringBuilder temp = new StringBuilder();
temp.append( hello );
temp.append( world );
s = temp.toString();

I wonder if it would be worth it for a compiler to try to guess a good
initial value for StringBuilder by computing the pieces first,
gathering their lengths and summing them for these hidden String
builds.
 
T

Thomas Fritsch

Roedy Green wrote:
[...]
String s = hello + world;

is effectively the same as:

StringBuilder temp = new StringBuilder();
temp.append( hello );
temp.append( world );
s = temp.toString();
To be a bit more exact, it is the same as:

String s = (new StringBuilder(hello)).append(world).toString();
 
L

Lasse Reichstein Nielsen

stef said:
Silly question, but if - internally speaking- the java compiler
replace the "String" class with "StringBuffer",

It doesn't, so the rest of the question is moot.
what is the real purpose of "String" ? (except shorter keyword and,
may be, when who do static stuff like String s ="hello "+"world")

The place where the compiler might use StringBuffer (or StringBuilder
in Java 5+) is in concatenations. I.e., in the above, it might create
code equivalent to:
String s = new StringBuilder("hello ").append("world").toString();
(In this particular case it'll probably just concatenate the two
literal strings at compile time, though).

/L
 
T

Thomas Fritsch

Eric said:
Thomas said:
Roedy Green wrote:
[...]
String s = hello + world;

is effectively the same as:

StringBuilder temp = new StringBuilder();
temp.append( hello );
temp.append( world );
s = temp.toString();

To be a bit more exact, it is the same as:

String s = (new StringBuilder(hello)).append(world).toString();


Is that a recent change? I seem to recall seeing
something more like

String s = (new StringBuilder())
.append(hello).append(world).toString();

... which is closer to Roedy's description. (Of course, in
Days Of Yore it was StringBuffer instead of StringBuilder.)
Doing "javap -c ..." with Java 1.5 and 1.6 I get:
String s =
(new StringBuilder(String.valueOf(hello))).append(world).toString();

With Java 1.4 I get:
String s =
(new StringBuffer(String.valueOf(hello))).append(world).toString();
 
R

Roedy Green

Is that a recent change? I seem to recall seeing
something more like

String s = (new StringBuilder())
.append(hello).append(world).toString();

... which is closer to Roedy's description. (Of course, in
Days Of Yore it was StringBuffer instead of StringBuilder.)

Here are three decompilations with Javap from JDK 1.6.0_07 which
should settle the matter. The important point is concatenation makes
no attempt to optimise the size of the StringBuilder, even for the
simplest cases.

Showing building a String with StringBuilder.

final StringBuilder sb = new StringBuilder( 1024 );
sb.append( "<table class=\"borderless\" summary=\"" );
sb.append( title );
sb.append( " art print\"><tbody>\n" );

11: new #13; //class java/lang/StringBuilder
14: dup
15: sipush 1024
18: invokespecial #14; //Method
java/lang/StringBuilder."<init>":(I)V
21: astore 6
23: aload 6
25: ldc #15; //String <table class=\"borderless\" summary=\"
27: invokevirtual #16; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: pop
31: aload 6
33: aload_1
34: invokevirtual #16; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
37: pop
38: aload 6
40: ldc #17; //String art print\"><tbody>\n
42: invokevirtual #16; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

-------------------------------

two literals with concatenation, and no estimate for StringBuilder
size.

return "PostScript " + "(&iexcl;) exclamdown";

// combined at compile time
1326: ldc #89; //String PostScript (&iexcl;) exclamdown
1328: areturn

-------------------------------------------

concatenation involving literals, variables and constants:

return "needs Java " + version + " or later, version " +
JRE_FULL_VERSION + " recommended";

creates a StringBuilder with default size.
Note that even though JRE_FULL_VERSION is a public static final
String, the concatenations of literas before and after are NOT done at
compile time.

9: new #17; //class java/lang/StringBuilder
12: dup
13: invokespecial #18; //Method
java/lang/StringBuilder."<init>":()V
16: ldc #19; //String needs Java
18: invokevirtual #20; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: aload_0 [ version is a parm passed to this method ]
22: invokevirtual #20; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: ldc #21; //String or later, version
27: invokevirtual #20; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: getstatic #22; //Field
com/mindprod/htmlmacros/SunJDKandJREVersions.JRE_FULL_VERSION:Ljava/lang/String;
33: invokevirtual #20; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: ldc #23; //String recommended
38: invokevirtual #20; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: invokevirtual #24; //Method
java/lang/StringBuilder.toString:()Ljava/lang/String;
44: areturn

The append method chosen returns a pointer to the StringBuilder, so
you don't have to manually dup it at each stage. invokeVirtual
consumes it..

so I would say that:

return "needs Java " + version + " or later, version " +
JRE_FULL_VERSION + " recommended";

compiles effectively to:

StringBuilder temp = new StringBuilder( /* default size */ );
// temp in on stack, not stack frame.
return temp.append( "needs Java " )
..append ( version )
..append ( " or later, version " )
..append( JRE_FULL_VERSION )
..append( " recommended")
..toString();
 
M

Mark Space

Roedy said:
I wonder if it would be worth it for a compiler to try to guess a good
initial value for StringBuilder by computing the pieces first,
gathering their lengths and summing them for these hidden String
builds.

Why guess when you can profile? What if the compiler added some extra
variables:

class Something {
private static int temp$$totals = 16;
private static int temp$$runs = 1;

void myMethod() {
StringBuilder temp = new StringBuilder( temp$$totals/temp$$runs );
temp.append( "Hello " );
temp.append( "world!\n" );
String s = temp.toString();
if( s.length() + temp$$totals > 0 ) {
temp$$totals += s.length();
temp$$runs++;
}
}
}

That would be a neat addition to JIT compiled code. Alternately you
could use the maximum value for s.length() instead of the average if you
really wanted an aggressive StringBuilder. Or something in between the
average value and the maximum.

average + (maximum - average) * 0.8f; // or so.
 
M

Mike Schilling

Lasse said:
It doesn't, so the rest of the question is moot.


The place where the compiler might use StringBuffer (or
StringBuilder
in Java 5+) is in concatenations. I.e., in the above, it might
create
code equivalent to:
String s = new StringBuilder("hello ").append("world").toString();
(In this particular case it'll probably just concatenate the two
literal strings at compile time, though).

Yes. So a better example might be:

return "The answer is: " + value;

which would generate bytecode equivalent to:

return new StringBuilder("The answer is:
").append(value).toString();
 
A

Arne Vajhøj

Lasse said:
It doesn't, so the rest of the question is moot.


The place where the compiler might use StringBuffer (or StringBuilder
in Java 5+) is in concatenations. I.e., in the above, it might create
code equivalent to:
String s = new StringBuilder("hello ").append("world").toString();
(In this particular case it'll probably just concatenate the two
literal strings at compile time, though).

So true.

I fear we have another myth being born.

Arne
 
L

Lew

Winifred said:
It could generate

String s = "Hello" + :"World";

as

String s = ("Hello".concat("World")).intern();

That would be really silly, but not so far as I can see illegal.

These are labeled *loathe-time* constants in the JLS, so, yes, it would be
cheap.

--
Lew


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[Zionism, fascism, genocide, racism, ethnic cleansing, terrorism,
war crimes, Khasars, Illuminati, NWO]

As famed violinist Lord Yehudi Menuhin told the French newspaper
Le Figaro in January 1988:

"It is extraordinary how nothing ever dies completely.
Even the evil which prevailed yesterday in Nazi Germany is
gaining ground in that country [Israel] today."

For it to have any moral authority, the UN must equate Zionism
with racism. If it doesn't, it tacitly condones Israel's war
of extermination against the Palestinians.

--- Greg Felton,
Israel: A monument to anti-Semitism
 
M

Mike Schilling

Lew said:
These are labeled *compile-time* constants in the JLS, so, yes, it
would be illegal.

But "compile-time constant" is a description of behavior, not
implementation.
 
L

Lew

Mike Schilling said:
But "compile-time constant" is a description of behavior, not
implementation.

The behavior that it describes is that the concatenation occurs at
compile time. That's why it's called a "compile-time" constant. Thus
it precludes a run-time implementation.

From the JLS:
"This is a " + // actually a string-valued constant expression,
"two-line string" // formed from two string literals
And:
We call a variable, of primitive type or type String, that is final and
initialized with a compile-time constant expression (§15.28) a constant
variable. Whether a variable is a constant variable or not may have
implications with respect to class initialization (§12.4.1), binary
compatibility (§13.1, §13.4.9) and definite assignment (§16).

In order to fulfill the semantic requirements of a compile-time
constant, the evaluation pretty much has to happen, well, at compile
time.
 

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

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,113
Latest member
Vinay KumarNevatia
Top