Can some one explain me how the internal behavior when we add two Integer objects in java? (like it is unbox Object into primitives and then add two integers and finally boxed it in to Integer object)
Integer sum = new Integer(2) + new Integer(4);
It's compiled into this:
Integer sum = Integer.valueOf(new Integer(2).intValue()+new Integer(4).intValue());
You can verify this by looking at the byte code disassembly obtained with javap -c.
Here is the part that corresponds to new Integer(2).intValue(), leaving int 2 on the stack:
0: new #2; //class java/lang/Integer
3: dup
4: iconst_2
5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
8: invokevirtual #4; //Method java/lang/Integer.intValue:()I
Here is the part that corresponds to new Integer(4).intValue(), leaving int 4 on the stack:
11: new #2; //class java/lang/Integer
14: dup
15: iconst_4
16: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
19: invokevirtual #4; //Method java/lang/Integer.intValue:()I
And here the sum 2+4 is calculated with iadd, the sum is boxed into an Integer by a call to Integer.valueOf, and the result is stored in the first local variable (astore_1):
22: iadd
23: invokestatic #5; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
26: astore_1
creation of two Integer instances.
Auto-unboxing of those two instances.
new int that holds the result.
Auto-boxing the result into Integer sum instance.
Related
I'm having a problem initializing array of HashSet
int N = 100;
HashSet<Integer> []array = new HashSet[N];
for (HashSet<Integer> set:array){
set = new HashSet<Integer>();
}
But the array contains only null. (Also error when HashSet []array = .... )
But when running with:
for(int i = 0; i < N; i++){
array[i] = new HashSet<Integer>();
}
All is well.
Why does the first code isn't working? Is it my mistake?
Thank you
You never actually assign initialized instances to elements of the array. Instead you iterate over the elements of the array with a variable that gets assigned to a new object in your loop, then is never used. In a case like this the enhanced for...each syntax is not appropriate, use the traditional for loop instead.
two 'for' is different in Java, look the java code & bytecode ..
Example:
public class T{
public static void main(String[] args){
String[] data = new String[10];
System.out.print("");
for(String str:data){
str="1";
}
System.out.print("");
for(int i=0;i<data.length;i++){
data[i]="1";
}
}
}
$>javac -classpath . T.java
$>javap -c T
Compiled from "T.java"
public class T extends java.lang.Object{
public T();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 10
2: anewarray #2; //class java/lang/String
5: astore_1
6: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #4; //String
11: invokevirtual #5; //Method java/io/PrintStream.print:(Ljava/lang/String;)V
14: aload_1
15: astore_2
16: aload_2
17: arraylength
18: istore_3
19: iconst_0
20: istore 4
22: iload 4
24: iload_3
25: if_icmpge 44
28: aload_2
29: iload 4
31: aaload
32: astore 5
34: ldc #6; //String 1
36: astore 5
38: iinc 4, 1
41: goto 22
44: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
47: ldc #4; //String
49: invokevirtual #5; //Method java/io/PrintStream.print:(Ljava/lang/String;)V
52: iconst_0
53: istore_2
54: iload_2
55: aload_1
56: arraylength
57: if_icmpge 71
60: aload_1
61: iload_2
62: ldc #6; //String 1
64: aastore
65: iinc 2, 1
68: goto 54
71: return
}
from line 25--44 and line 57--71:
aload : Retrieves an object reference from a local variable and pushes it onto the operand stack.
aaload : Retrieves an object reference from an array of objects and places it on the stack.
astore : Take object or reference store to local variable.
aastore : Take reference type value store to array.
so,first can't store array , didn't using initializing array.
An enhanced for loop, does not use the actual instances in the array( and as well, collection), but rather copies them in the loop control variable.
This should not be a problem with non-null values, since they point to the same object. Problems arise, if the values are null, and re-assigning values to the control variable, would not change the actual value. So in this case, always use regular for loops.
The same would be true, to arrays of primitive types, since coping them, and changing the copied variable, will not affect the original variable.
Simply use new Set[n] instead of new HashSet[n] , to get it working
Set<Integer>[] list = new Set[n];
for(int i=0;i<n;i++)
list[i] = new HashSet<>();
You need to create an array that contains HashSet
so, you need to initialize the array and then initialize the HashSet
which I have provided in the below code
int N = 100;
Set<Integer>[] array = new Set[n];
for(int i = 0; i < n; i++) {
array[i] = new HashSet<Integer>();
}
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Goolge comes up with a lot of comparisions but not on what I am looking for:
What is better if I want to iterate through a splitted String
String[] flagArr = flags.split(";");
for (String f: flagArr) {
// some stuff
}
OR
for (String f: flags.split(";")) {
// some stuff
}
With the second pice of code I wonder if the compiler is smart enough to do the split only once
You can check the generated bytecode, but I'm pretty sure they'll both do the same thing. Why would the second one be any different?
EDIT: As you can see, both ways only call split() once.
The bytecode for the first one:
public class javatesting.JavaTesting extends java.lang.Object{
public javatesting.JavaTesting();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String 1;2;3
2: astore_1
3: aload_1
4: ldc #3; //String ;
6: invokevirtual #4; //Method java/lang/String.split:(Ljava/lang/String;)
[Ljava/lang/String;
9: astore_2
10: aload_2
11: astore_3
12: aload_3
13: arraylength
14: istore 4
16: iconst_0
17: istore 5
19: iload 5
21: iload 4
23: if_icmpge 41
26: aload_3
27: iload 5
29: aaload
30: astore 6
32: aconst_null
33: astore 6
35: iinc 5, 1
38: goto 19
41: return
}
And the bytecode for the second one:
public class javatesting.JavaTesting extends java.lang.Object{
public javatesting.JavaTesting();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String 1;2;3
2: astore_1
3: aload_1
4: ldc #3; //String ;
6: invokevirtual #4; //Method java/lang/String.split:(Ljava/lang/String;)
[Ljava/lang/String;
9: astore_2
10: aload_2
11: arraylength
12: istore_3
13: iconst_0
14: istore 4
16: iload 4
18: iload_3
19: if_icmpge 37
22: aload_2
23: iload 4
25: aaload
26: astore 5
28: aconst_null
29: astore 5
31: iinc 4, 1
34: goto 16
37: return
}
It doesn't matter at all. Don't waste time with such type of optimization.
EDIT: If you ever want to care about such thing than you might use the second option since the array with the splits will exist only inside the for loop scope.
If you really want to see the difference in bytecode, use javap -c. Compiled with the Eclipse compiler, the first version (with a local variable in the source code) gives this:
public static void test(java.lang.String);
Code:
0: aload_0
1: ldc #16; //String ;
3: invokevirtual #18; //Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
6: astore_1
7: aload_1
8: dup
9: astore 5
11: arraylength
12: istore 4
14: iconst_0
15: istore_3
16: goto 27
19: aload 5
21: iload_3
22: aaload
23: astore_2
24: iinc 3, 1
27: iload_3
28: iload 4
30: if_icmplt 19
33: return
}
And the second:
public static void test(java.lang.String);
Code:
0: aload_0
1: ldc #16; //String ;
3: invokevirtual #18; //Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
6: dup
7: astore 4
9: arraylength
10: istore_3
11: iconst_0
12: istore_2
13: goto 24
16: aload 4
18: iload_2
19: aaload
20: astore_1
21: iinc 2, 1
24: iload_2
25: iload_3
26: if_icmplt 16
29: return
}
As you can see (if you can read this), the first variant does use an extra local variable slot (astore_1/aload_1 at the beginning). However (a) even if the bytecode was interpreted, the overhead of this would be negligible (it's just copying the reference) and (b) any JIT compiler will be able to optimize this, whether you have done some static bytecode optimization beforehand or not: local variable (1) is never subsequently used.
Local variables in the source code are mainly used for clarity, and for being able to re-use intermediate results. Fundamentally, the second variant (without an explicit local variable) will not let you re-use the result of split further down in your method (or even directly within the loop), whereas you could when naming your local variable in the code.
With the second pice of code I wonder if the compiler is smart enough
to do the split only once
The only difference between your two methods is the explicit declaration of a local variable in the source code.
In both cases, for (String f: flags.split(";")) { } is syntactic sugar (except that neither local variables are accessible) equivalent to :
int _hidden_i = 0;
for (String[] _hidden_arr=flags.split(";"); _hidden_i<_hidden_arr.length; _hidden_i++){
String f = _hidden_arr[_hidden_i];
// some stuff
}
The points to note are that:
With this notation, _hidden_i is never exposed, so you can never allocate something into _hidden_arr[_hidden_i].
Even a naive source-to-bytecode compiler knows that both _hidden_arr and _hidden_i will never be used again, so it doesn't copy them for further use.
What would have been fundamentally different would have been:
for (var i = 0; i < flags.split(";").length; i++) {
String f = flags.split(";")[i];
}
In the for(;;) notation, the first part is always executed once. The second expression is always executed before entering the loop block (to test whether or not to run it). The last is always executing after running the loop block (unless break is used).
You would generally want to avoid method calls that are potentially heavy in the second part, especially when it's always going to be the same result.
I think the compiler will optimize that. It might depend on the Java provider you hae chosen (sun, ibm, etc...) but this is so simple I would be surprised if every compiler did not.
Perhaps create a really large flags string and do some simple performance testing?
But, since this is easy, why not just do your first option....
I'm quite certain the the split will be done only one. Internally this code will be translated into a loop with an iterator, so the compiler will do the split once, create the resulting collection, then create the iterator over that collection.
The iterator would not be pointing to the right place if the split were to be repeated.
Try this:
public double calculateRunTime()
{
long startTime = System.currentTimeMillis();
split();
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
I was curious about how the JVM works. Does the JVM acknowledge method accesibility rules like 'private' protected or is that only done at compile time?
For example, is it possible at around line37 to do some bytecode manipulation and call a protected method, say test3? Normally the compiler would not let me call that method because it is declared protected. But I was curious if that protected rule is enforced at runtime?
u.test1();
// Is it possible at runtime, to call 'test3' through bytecode manipulation
// #line37
package org.berlin.algo.basic.test;
public class RunX {
private String zzz = "rrrrr";
public void test1() {
// Note: I am intentionally use 'new' here as part of my test, not a
// good practice I know but allowed by the language.
Object x = new String("Test1 -----[1.1] " + zzz);
x = new String("Test1 --- [1.2]" + x.toString());
System.out.println(x);
this.test2();
this.test3();
}
/**
* Here, I noticed that the compiler removed my 'test2' code block.
* Does that always happen?
*/
private void test2() {
Object x = new String("Test2#line21--->>> [2.1]");
System.out.println(x);
}
protected void test3() {
Object x = new String("Test3#line27 {Will the JVM enforce the 'protected' method rule for test3? --->>> [3.1]");
x = new String("Test3#line28--->>> [3.2]");
System.out.println(x);
}
public static void main(final String [] args) {
System.out.println("Running");
RunX u = new RunX();
u.test1();
// Is it possible at runtime, to call 'test3' through bytecode manipulation
// #line37
System.out.println("Done");
}
} // End of the Class //
/*
JVM bytecode: javap -v RunX
Compiled from "RunX.java"
public class org.berlin.algo.basic.test.RunX extends java.lang.Object
SourceFile: "RunX.java"
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // org/berlin/algo/basic/test/RunX
const #2 = Asciz org/berlin/algo/basic/test/RunX;
...
...
const #84 = Asciz SourceFile;
const #85 = Asciz RunX.java;
{
public org.berlin.algo.basic.test.RunX();
Code:
Stack=2, Locals=1, Args_size=1
0: aload_0
1: invokespecial #10; //Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #12; //String rrrrr
7: putfield #14; //Field zzz:Ljava/lang/String;
10: return
LineNumberTable:
line 3: 0
line 5: 4
line 3: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this Lorg/berlin/algo/basic/test/RunX;
public void test1();
Code:
Stack=5, Locals=2, Args_size=1
0: new #21; //class java/lang/String
3: dup
4: new #23; //class java/lang/StringBuilder
7: dup
8: ldc #25; //String Test1 -----[1.1]
10: invokespecial #27; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
13: aload_0
14: getfield #14; //Field zzz:Ljava/lang/String;
17: invokevirtual #30; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: invokevirtual #34; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: invokespecial #38; //Method java/lang/String."<init>":(Ljava/lang/String;)V
26: astore_1
27: new #21; //class java/lang/String
30: dup
31: new #23; //class java/lang/StringBuilder
34: dup
35: ldc #39; //String Test1 --- [1.2]
37: invokespecial #27; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
40: aload_1
41: invokevirtual #41; //Method java/lang/Object.toString:()Ljava/lang/String;
44: invokevirtual #30; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
47: invokevirtual #34; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
50: invokespecial #38; //Method java/lang/String."<init>":(Ljava/lang/String;)V
53: astore_1
54: getstatic #42; //Field java/lang/System.out:Ljava/io/PrintStream;
57: aload_1
58: invokevirtual #48; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
61: aload_0
62: invokespecial #54; //Method test2:()V
65: aload_0
66: invokevirtual #57; //Method test3:()V
69: return
LocalVariableTable:
Start Length Slot Name Signature
0 70 0 this Lorg/berlin/algo/basic/test/RunX;
27 43 1 x Ljava/lang/Object;
protected void test3();
Code:
Stack=3, Locals=2, Args_size=1
0: new #21; //class java/lang/String
3: dup
4: ldc #66; //String Test3#line27 {Will the JVM enforce the 'protected' method rule for test3? --->>> [3.1]
6: invokespecial #38; //Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
10: new #21; //class java/lang/String
13: dup
14: ldc #68; //String Test3#line28--->>> [3.2]
16: invokespecial #38; //Method java/lang/String."<init>":(Ljava/lang/String;)V
19: astore_1
20: getstatic #42; //Field java/lang/System.out:Ljava/io/PrintStream;
23: aload_1
24: invokevirtual #48; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
27: return
LocalVariableTable:
Start Length Slot Name Signature
0 28 0 this Lorg/berlin/algo/basic/test/RunX;
10 18 1 x Ljava/lang/Object;
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=1
0: getstatic #42; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #72; //String Running
5: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: new #1; //class org/berlin/algo/basic/test/RunX
11: dup
12: invokespecial #76; //Method "<init>":()V
15: astore_1
16: aload_1
17: invokevirtual #77; //Method test1:()V
20: getstatic #42; //Field java/lang/System.out:Ljava/io/PrintStream;
23: ldc #79; //String Done
25: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
LocalVariableTable:
Start Length Slot Name Signature
0 29 0 args [Ljava/lang/String;
16 13 1 u Lorg/berlin/algo/basic/test/RunX;
}
*/
To the JLS!
15.12.4 Runtime Evaluation of Method Invocation
At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated. Third, the accessibility of the method to be invoked is checked. Fourth, the actual code for the method to be executed is located. Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.
The wording of the JLS indicates that the accessibility would be checked at runtime.
The JVM does acknowledge these. They can be overridden, by calling setAccessible(true) as Prashant Bhate does, but by default they are enforced. (See http://download.oracle.com/javase/6/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible%28boolean%29.)
By the way, you write that "the compiler doesn't encode type method visibility rules into the Java bytecde file"; but it does. In addition to the above, it has to encode these, for a number of reasons. For example:
you can compile a class A that references class B even if you only have the compiled version of class B.
you can inspect a method's visibility via reflection (the getModifiers() method).
private methods aren't virtual -slash- can't be overridden by subclasses.
If you want to call this method from outside current class you could call private & protected methods using reflection.
Method m = RunX.class.getDeclaredMethod("test3");
m.setAccesible(true);
m.invoke(u);
however you can call this protected (and also private) method directly from main() without any issues.
Oli mentioned it rightly that ultimately you can do anything if you come to extent of byte code manipulation (if done correctly !!!).
Although I will like answer your question of accessibility honor at runtime in Java. If you have any doubts then please go ahead and use reflection to call the private method of one class from other class and you will get your answer. Java creates the function table of class at runtime when loading it and allow the refererence to the functions in limit of accessibility rule. However Java provides facility where you can call the private methods via reflection using setAccessible(true) on the method reference before invoking it.
Say i have the following line in my program:
jobSetupErrors.append("abc");
In the case above where jobSetupErrors is a StringBuilder(), what i see happen is:
New String Object is created and assigned value "abc"
value of that String object is assigned to the existing StringBuilder object
If that is correct, and I add 1 more line ...
jobSetupErrors.append("abc");
logger.info("abc");
In the above example are we creating String object separately 2 times?
If so, would it be more proper to do something like this?
String a = "abc";
jobSetupErrors.append(a);
logger.info(a);
Is this a better approach? Please advise
In the above example are we creating
String object separately 2 times?
No, because in Java String literals (anything in double-quotes) are interned. What this means is that both of those lines are referring to the same String, so no further optimization is necessary.
In your second example, you are only creating an extra reference to the same String, but this is what Java has already done for you by placing a reference to it in something called the string pool. This happens the first time it sees "abc"; the second time, it checks the pool and finds that "abc" already exists, so it is replaced with the same reference as the first one.
See http://en.wikipedia.org/wiki/String_interning for more information on String interning.
To help find out, I wrote a class like the following:
class Test {
String a = "abc" ;
StringBuilder buffer = new StringBuilder() ;
public void normal() {
buffer.append( "abc" ) ;
buffer.append( "abc" ) ;
}
public void clever() {
buffer.append( a ) ;
buffer.append( a ) ;
}
}
If we compile this, and then run javap over it to extract the bytecode:
14:09:58 :: javap $ javap -c Test
Compiled from "Test.java"
class Test extends java.lang.Object{
java.lang.String a;
java.lang.StringBuilder buffer;
Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2; //String abc
7: putfield #3; //Field a:Ljava/lang/String;
10: aload_0
11: new #4; //class java/lang/StringBuilder
14: dup
15: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V
18: putfield #6; //Field buffer:Ljava/lang/StringBuilder;
21: return
public void normal();
Code:
0: aload_0
1: getfield #6; //Field buffer:Ljava/lang/StringBuilder;
4: ldc #2; //String abc
6: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
9: pop
10: aload_0
11: getfield #6; //Field buffer:Ljava/lang/StringBuilder;
14: ldc #2; //String abc
16: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: pop
20: return
public void clever();
Code:
0: aload_0
1: getfield #6; //Field buffer:Ljava/lang/StringBuilder;
4: aload_0
5: getfield #3; //Field a:Ljava/lang/String;
8: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: pop
12: aload_0
13: getfield #6; //Field buffer:Ljava/lang/StringBuilder;
16: aload_0
17: getfield #3; //Field a:Ljava/lang/String;
20: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: pop
24: return
}
We can see 2 things.
First, the normal method is using the same String instance for both of those calls (indeed it is the same literal as is set to the a member variable of this class in the initialisation block)
And secondly, the clever method is longer than the normal one. This is because extra steps are required to fetch the property out of the class.
So the moral of the story is that 99% of the time, Java does things the right way on it's own, and theres no need in trying to be clever ;-) (and javap is a really cool tool for when you want to know exactly what's going on)
1.
static final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);
2.
System.out.println("Efficiently stored String");
Will Java compiler treat both (1 and 2) of these in the same manner?
FYI: By efficiently I am referring to runtime memory utilization as well as code execution time. e.g. can the 1st case take more time on stack loading the variable memFriendly?
This is covered in the Java Language Spec:
Each string literal is a reference
(§4.3) to an instance (§4.3.1, §12.5)
of class String (§4.3.3). String
objects have a constant value. String
literals-or, more generally, strings
that are the values of constant
expressions (§15.28)-are "interned" so
as to share unique instances, using
the method String.intern.
You can also see for yourself using the javap tool.
For this code:
System.out.println("Efficiently stored String");
final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);
javap gives the following:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String Efficiently stored String
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc #3; //String Efficiently stored String
13: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
public static void main(String[] args) {
System.out.println("Hello world!");
String hola = "Hola, mundo!";
System.out.println(hola);
}
Here is what javap shows as the disassembly for this code:
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #22; //String Hello world!
5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: ldc #30; //String Hola, mundo!
10: astore_1
11: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14: aload_1
15: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
Looks like the second string is being stored, whereas the first one is simply passed to the method directly.
This was built with Eclipse's compiler, which may explain differences in my answer and McDowell's.
Update: Here are the results if hola is declared as final (results in no aload_1, if I'm reading this right then it means this String is both stored and inlined, as you might expect):
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #22; //String Hello world!
5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: ldc #30; //String Hola, mundo!
10: astore_1
11: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14: ldc #30; //String Hola, mundo!
16: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
19: return
In this case, the compiler will handle both the same.
Anytime a String is defined at compile time, Java will optimize the storage of Strings.
If a string is defined at runtime, Java has no way of doing the same optomization.
The code you have is equivilant because string literals are automatically interned by the compiler.
If you are really concerned about String performance and will be reusing the same strings over and over you should take a look at the intern method on the string class.
http://java.sun.com/javase/6/docs/api/java/lang/String.html#intern()