10

To create a new Integer object that holds the value in java 1 which one of the following is right and what exactly is the difference in the following methods as all print the value?

Method 1 :

 Integer p = new Integer(1);

Method 2 :

Integer p = 1;

Method 3 :

Integer p = new Integer("1");

Using method three I got the following warning :

Note: HelloWorld.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details
noogler
  • 167
  • 1
  • 2
  • 16
  • 3
    Method 4: `Integer p = Integer.valueOf(1);` – Jacob G. Apr 18 '18 at 16:39
  • 1
    Some background: If you use `Integer.valueOf(int value);`, then class `Integer` can return previously created `Integer`-objects that have the same value (this works since `Integer`s are immutable). – Turing85 Apr 18 '18 at 16:41
  • 1
    @JacobG. Why would I use valueOf method while creating the object the first time and could you please also explain why that is a better method than any of the mentioned ways. Thanks – noogler Apr 18 '18 at 16:44
  • @noogler Check [Jonathan's answer](https://stackoverflow.com/a/49904957/7294647) – Jacob G. Apr 18 '18 at 16:46
  • 1
    @Jacob While your method is certainly correct, I do not see a reason to prefer method 4 over method 2. It generates same result due to autoboxing. – Dorian Gray Apr 18 '18 at 17:12

2 Answers2

14

You skipped the intended solution:

Integer p = Integer.valueOf(1);

This pattern is known as Factory method pattern. One may ask what the benefit of this method is. Luckily, the implementation of class Integer is open-source, so let's take a look:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

There seems to be some kind of Integer-value cache. If one requests an Integer with a value within the cache-range, Java does not create a new object, but returns a previously created one. This works because Integers are immutable. One can even control the upper cache limit with the system property java.lang.Integer.IntegerCache.high=....

And why do the other two methods of creating an Integer generate a warning? Because they were set deprecated with Java 9.

Integer#Integer(int value):

Deprecated. It is rarely appropriate to use this constructor. The static factory valueOf(int) is generally a better choice, as it is likely to yield significantly better space and time performance. [...]

Integer#Integer(String s):

Deprecated. It is rarely appropriate to use this constructor. Use parseInt(String) to convert a string to a int primitive, or use valueOf(String) to convert a string to an Integer object. [...]

And just for completeness, here is the part for Integer.valueOf(int i):

Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.


EDIT 1: Thanks to @VGR mentioning that

Integer p = 1;

is equivilant to

Integer p = Integer.valueOf(1);

This, however, is only true for int-values between -128 and 127. The behaviour is defined in JLS §5.1.7:

[...] If the value p being boxed is the result of evaluating a constant expression (§15.28) of type boolean, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.


EDIT 2: Thanks to @DorianGray, who brought the following to my attention.

While not in the JLS, the version of javac I am using (9.0.4) does compile the boxing down to Integer.valueOf(...); as it is shown in this answer by Adam Rosenfield.

Turing85
  • 18,217
  • 7
  • 33
  • 58
  • It is worth mentioning that `Integer p = 1;` is functionally identical to this. – VGR Apr 18 '18 at 17:12
  • @VGR added. Thanks for the wink =) – Turing85 Apr 18 '18 at 17:18
  • Actually `Integer p = 1` is always equivalent to `Integer p = Integer.valueOf(1)`, it is just a shorter notation. – Dorian Gray Apr 18 '18 at 17:24
  • I still see the reference to the range of int. – Dorian Gray Apr 18 '18 at 17:27
  • @TobiasWeimer Yes, not every `int`-value is cached. Only the ones between `-128` and `127` are guaranteed to be chached (as the documentation says, and as is defined in the JLS). Or do I misunderstand your statement? – Turing85 Apr 18 '18 at 17:30
  • I was talking about the fact that `Integer p = 1` is always evaluated as `Integer p = Integer.valueOf(1)` - thats how autoboxing is implemented. They are both using the same cache and are identical in behavior. – Dorian Gray Apr 18 '18 at 17:33
  • @TobiasWeimer do you have some spec on that? If so, I would gladly add this to my answer. – Turing85 Apr 18 '18 at 17:36
  • Well, interesting, that behaviour is not specified in the JLS link you posted, so I have to correct myself that my statement is not generally true and implementation specific to the VM. I found a diacussion in https://stackoverflow.com/questions/408661/what-code-does-the-compiler-generate-for-autoboxing about that. – Dorian Gray Apr 18 '18 at 17:55
  • @TobiasWeimer Added. Thanks for the reference! – Turing85 Apr 18 '18 at 18:03
  • 1
    Note that even for the values in the -128 and 127 range, the specification does not mandate that `valueOf` will be used. It only says that whatever is used under the hood will return canonical instances. But when you are about to implement a compiler interoperating with the other compilers, you have no choice but to implement it exactly that way, as everything else would break the specification’s guaranty. And now that the constructors are “Deprecated, for removal”, generating code using them would imply generating code that may break in the future. So `valueOf` is the only remaining option. – Holger Jan 11 '22 at 16:49
3

Method 4, Integer p = Integer.valueOf(1); is the recommended way. The JavaDoc says:

Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

Jonathan Rosenne
  • 2,159
  • 17
  • 27
  • If taking the question as it is written, `Integer.valueOf(1)` is *not* the right solution, as it is *not* guaranteed to create, I quote, "new Integer object". – lexicore Apr 18 '18 at 17:01
  • 1
    @lexicore while being true, what reason could there be to create a new `Integer`-object if another one with same value already exists? `Integer`s are immutable. – Turing85 Apr 18 '18 at 17:02
  • @Turing85 Practically - probably none. For a quiz question it might be significant. – lexicore Apr 18 '18 at 17:09
  • 2
    @lexicore well... weird quiz I would say ;) especially since both C'tors are set deprecated (which is the closest Oracle will ever get to "deleting" some public method or switching it to `private`) =). – Turing85 Apr 18 '18 at 17:11
  • @Turing85 Not that I were surprized by weird quizes. But the question really looks like a quiz question to me. – lexicore Apr 18 '18 at 17:15
  • 1
    @lexicore there is no “right solution” for creating a “new Integer object”, as the deprecation and planned removal of the public constructors is precisely to stop offering a way for creating a “new Integer object”. – Holger Jan 11 '22 at 16:57