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...
|
|
0
|
|
|
|
Reply
|
stef.pellegrino (39)
|
7/23/2008 9:59:17 AM |
|
On Wed, 23 Jul 2008 02:59:17 -0700 (PDT), stef
<stef.pellegrino@gmail.com> wrote, quoted or indirectly quoted someone
who said :
>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();
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
|
|
0
|
|
|
|
Reply
|
see_website (4858)
|
7/23/2008 10:41:27 AM
|
|
On Wed, 23 Jul 2008 10:41:27 GMT, Roedy Green
<see_website@mindprod.com.invalid> wrote, quoted or indirectly quoted
someone who said :
>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.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
|
|
0
|
|
|
|
Reply
|
see_website (4858)
|
7/23/2008 10:55:11 AM
|
|
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();
--
Thomas
|
|
0
|
|
|
|
Reply
|
i.dont.like.spam (473)
|
7/23/2008 11:17:08 AM
|
|
stef <stef.pellegrino@gmail.com> writes:
> 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
--
Lasse Reichstein Holst Nielsen
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
|
|
0
|
|
|
|
Reply
|
lrn (235)
|
7/23/2008 11:29:46 AM
|
|
Thomas Fritsch wrote:
> 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.)
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
esosman2 (2945)
|
7/23/2008 1:03:13 PM
|
|
Eric Sosman wrote:
> Thomas Fritsch wrote:
>
>> 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();
--
Thomas
|
|
0
|
|
|
|
Reply
|
i.dont.like.spam (473)
|
7/23/2008 1:52:32 PM
|
|
On Wed, 23 Jul 2008 09:03:13 -0400, Eric Sosman
<esosman@ieee-dot-org.invalid> wrote, quoted or indirectly quoted
someone who said :
> 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 " + "(¡) exclamdown";
// combined at compile time
1326: ldc #89; //String PostScript (¡) 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();
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
|
|
0
|
|
|
|
Reply
|
see_website (4858)
|
7/23/2008 4:09:06 PM
|
|
Thomas Fritsch wrote:
> Eric Sosman wrote:
>> Thomas Fritsch wrote:
>>
>>> 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();
That's very odd. Using Java 1.6.0_05 on
String join(String hello, String world) {
return hello + world;
}
.... I got
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method
java/lang/StringBuilder.toString:()Ljava/lang/String;
18: areturn
.... which is to say
return
(new StringBuilder()).append(hello).append(world).toString();
Wondering whether the code varied with the types of the concatenated
operands, I tried it with String+String, String+int, and int+String
with the same result all three times. I wonder what gives us such
different outcomes.
--
Eric.Sosman@sun.com
|
|
0
|
|
|
|
Reply
|
Eric.Sosman (4228)
|
7/23/2008 4:25:43 PM
|
|
Roedy Green wrote:
> On Wed, 23 Jul 2008 10:41:27 GMT, Roedy Green
> <see_website@mindprod.com.invalid> wrote, quoted or indirectly quoted
> someone who said :
>
>> 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.
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.
|
|
0
|
|
|
|
Reply
|
markspace (954)
|
7/23/2008 4:33:34 PM
|
|
Lasse Reichstein Nielsen wrote:
> stef <stef.pellegrino@gmail.com> writes:
>
>> 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).
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();
|
|
0
|
|
|
|
Reply
|
mscottschilling (1976)
|
7/23/2008 5:41:46 PM
|
|
Lasse Reichstein Nielsen wrote:
> stef <stef.pellegrino@gmail.com> writes:
>
>> 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).
So true.
I fear we have another myth being born.
Arne
|
|
0
|
|
|
|
Reply
|
arne6 (9485)
|
7/23/2008 11:35:52 PM
|
|
On Wed, 23 Jul 2008 12:25:43 -0400, Eric Sosman <Eric.Sosman@sun.com>
wrote, quoted or indirectly quoted someone who said :
>> With Java 1.4 I get:
>> String s =
>> (new StringBuffer(String.valueOf(hello))).append(world).toString();
>
> That's very odd. Using Java 1.6.0_05 on
1.4 to 1.6_05 gave plenty of time for Sun to make a minor tweak like
that.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
|
|
0
|
|
|
|
Reply
|
see_website (4858)
|
7/24/2008 11:24:59 AM
|
|
Roedy Green wrote:
> On Wed, 23 Jul 2008 12:25:43 -0400, Eric Sosman <Eric.Sosman@sun.com>
> wrote, quoted or indirectly quoted someone who said :
>
>>> With Java 1.4 I get:
>>> String s =
>>> (new StringBuffer(String.valueOf(hello))).append(world).toString();
>> That's very odd. Using Java 1.6.0_05 on
>
> 1.4 to 1.6_05 gave plenty of time for Sun to make a minor tweak like
> that.
Yes, but the oddity is that Thomas Fritsch (attribution
snipped above) gets different generated code from "Java 1.6"
than "Java 1.6.0_05" gives me. I'm at a loss to understand
the different behavior.
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
esosman2 (2945)
|
7/24/2008 12:30:33 PM
|
|
Lasse Reichstein Nielsen wrote:
>> (In this particular case it'll probably just concatenate the two
>> literal strings at compile time, though).
It has to, by JLS 15.28, "Constant Expression".
<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313>.
--
Lew
|
|
0
|
|
|
|
Reply
|
Lew
|
7/25/2008 5:39:05 AM
|
|
Lew wrote:
> Lasse Reichstein Nielsen wrote:
>>> (In this particular case it'll probably just concatenate the two
>>> literal strings at compile time, though).
>
> It has to, by JLS 15.28, "Constant Expression".
> <http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313>.
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.
|
|
0
|
|
|
|
Reply
|
mscottschilling (1976)
|
7/25/2008 6:55:21 AM
|
|
Mike Schilling wrote:
> Lew wrote:
>> Lasse Reichstein Nielsen wrote:
>>>> (In this particular case it'll probably just concatenate the two
>>>> literal strings at compile time, though).
>> It has to, by JLS 15.28, "Constant Expression".
>> <http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313>.
>
> 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 *compile-time* constants in the JLS, so, yes, it would be
illegal.
--
Lew
|
|
0
|
|
|
|
Reply
|
Lew
|
7/25/2008 12:35:35 PM
|
|
Winifred Schilling wrote:
> Lew wrote:
>> Lasse Reichstein Nielsen wrote:
>>>> (In this particular case it'll probably just concatenate the two
>>>> literal strings at compile time, though).
>> It has to, by JLS 15.28, "Constant Expression".
>> <http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313>.
>
> 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
|
|
0
|
|
|
|
Reply
|
powerobsessedidiot (6)
|
7/25/2008 3:28:37 PM
|
|
Lew wrote:
> Mike Schilling wrote:
>> Lew wrote:
>>> Lasse Reichstein Nielsen wrote:
>>>>> (In this particular case it'll probably just concatenate the two
>>>>> literal strings at compile time, though).
>>> It has to, by JLS 15.28, "Constant Expression".
>>> <http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313>.
>>
>> 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 *compile-time* constants in the JLS, so, yes, it
> would be illegal.
But "compile-time constant" is a description of behavior, not
implementation.
|
|
0
|
|
|
|
Reply
|
mscottschilling (1976)
|
7/25/2008 4:44:20 PM
|
|
"Mike Schilling" wrote:
> 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.
=46rom 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 (=A715.28) a constant
> variable. Whether a variable is a constant variable or not may have
> implications with respect to class initialization (=A712.4.1), binary
> compatibility (=A713.1, =A713.4.9) and definite assignment (=A716).
In order to fulfill the semantic requirements of a compile-time
constant, the evaluation pretty much has to happen, well, at compile
time.
--
Lew
|
|
0
|
|
|
|
Reply
|
lew (2143)
|
7/25/2008 5:44:27 PM
|
|
|
19 Replies
37 Views
(page loaded in 0.384 seconds)
|