2
static final String = "something";

I was wondering if such a declaration has some kind real sense in Java. I've found it thousands of time within the code but studying and playing with strings I've learnt that does not matter how many times you declare a String object: if some class before yours declared this string this is pooled and reused (I'm talking about String created without explicit constructor invocation)

public class StringCompare {   
    private void toCompare(String h) {
        String x = "hello";
        System.out.println( x == h);
    }

    public void compare() {
        String h = "hello";
        toCompare(h);
    }      
}

This code, in fact, prints true when calling compare so the 2 variables are referencing the same object. Said that a final variable can't be redefined, the static word is completely useless in this case. Am I missing the point?

Couple of more things:

1 - Why explicit call to String constructor won't cause the String to be pooled? Same code above using a new String("hello") print false.

2 - Is the pooling behaviour reserved to Strings? There are some other immutable objects (like BigInteger) but I think these are not pooled ... why?

Thanks, Carlo

Carlo Bertuccini
  • 19,615
  • 3
  • 28
  • 39
  • The word "static" is for the Class to access instead of the Instance – madhairsilence Oct 03 '14 at 09:55
  • 3
    I have to say you have a rather odd definition of "completely useless". – NPE Oct 03 '14 at 09:56
  • Your question is all over the place, your concerns about static and final have nothing to do with the difference between a literal and `new String`; and the existence of the string pool is yet - largely - another concern. – Mark Rotteveel Oct 03 '14 at 09:56
  • @MarkRotteveel I concern about the pool and the static word when a variable that reference a pooled object is declared final. I don't think my question is "all over the place", I was just trying to understand what deeply happens within a pooled immutable object/string – Carlo Bertuccini Oct 03 '14 at 10:28
  • 1
    A static (final) is a constant. That is: you assign a label to that string, so that you can access it from all over your program and that you can be sure you always use the right value. That it might be the same string object as a literal may be nice from memory conservation, but that is not why you use a static final constant. – Mark Rotteveel Oct 03 '14 at 10:39
  • @MarkRotteveel I wasn't completely clear in my question. When used as public constants (in a class with private constructor and all field declared public) I agree, but I often found these as constants declared within a class with private access (so the usage is restricted to the class) -- however thanks for your comment – Carlo Bertuccini Oct 03 '14 at 11:41
  • Even as private constants have the same value, but then the use is limited to the class (and instances of that class). – Mark Rotteveel Oct 03 '14 at 11:49

5 Answers5

4

There are a few reasons why developers use this pattern, even though your analysis of the runtime behavior and its use the string pool is correct.

  1. It communicates the developers intent more cleanly. Specifically the string now has a name that is hopefully more clear than the constant, and it communicates the runtime behaviour that not everybody is aware of (or they forget from time to time).
  2. If the developer wants to change the value within the source file, and it has been used in multiple places then there is only one place to make that change.
  3. Once the decision to use a variable has been made, the keyword static will mean that the memory usage is lower. That is, there is only one field used to store the ref rather than one field per instance of the object.

As for your follow on questions:

  1. Q: Why explicit call to String constructor won't cause the String to be pooled? Same code above using a new String("hello") print false.

Because the string pool is only used for string literals, as described by the JLS and invoking a constructor is not classified as a string literal.

  1. Q: Is the pooling behaviour reserved to Strings?

The string pool is only used for string literals, but there is of course other caches for different use cases. The most obvious one that jumps to mind is the int cache used to optimize auto boxing of ints.

Chris K
  • 11,622
  • 1
  • 36
  • 49
  • Thanks for answering. As far as point 1 for readability/intent I agree: the question was concerning the runtime env -- I still don't understand the decision of pooling only literals, I will look into JLS there is probably some reason behind this decision – Carlo Bertuccini Oct 03 '14 at 10:38
  • @CarloBertuccini Back when the JLS was created, the string pool was stored in perm gen.. which back then was on the heap, but never garbage collected. Interning strings created by constructors could then blow the heap. Now a days those predicates are no longer true, however interning does have a cost and the current language design lets developers control when they want strings interned and when they do not. – Chris K Oct 03 '14 at 10:41
  • @CarloBertuccini digging further you will also come across the constant pool within a java class file; which you will have to delve into the JVM spec to find. Back in the day that was the scope of string literals, and the automatic interning of strings. It gave a synergy of design that worked with a purely interpreted language. – Chris K Oct 03 '14 at 10:43
2

Even if the static doesn't give you a memory benefit in this case, you can still access the field in a static way, so you don't need an instance. For example, you frequently use some URIs, so you create the following class:

public class Uris
{
    public static final String GOOGLE = "http://google.com";
    public static final String BBC = "http://bbc.co.uk";
}

Using static, you can just use Uris.GOOGLE instead of new Uris().GOOGLE.

Konrad Höffner
  • 11,100
  • 16
  • 60
  • 118
1

The static means that for each new object created for that class, the String construction & pooling only has to happen once, ever. This is a small saving in computation.

Stewart
  • 17,616
  • 8
  • 52
  • 80
1

it is because String ="hello" or String h are not creating any object in heap these all are stored inString constant pool where as new String("hello"); create a new object in heap and so address will be different

check details here

Community
  • 1
  • 1
Rustam
  • 6,485
  • 1
  • 25
  • 25
0
String x = "hello";
String h = "hello";

are two String literals. They are in common pool(part of String pool). There are referring same reference. Then == check the reference you will get true

If you use String x = new String("hello"), it will create a new String object x. of course referring new reference. Now compare reference give you false.

Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115