String question #2

  • Follow


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 " + "(&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();
 
-- 

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)


Reply: