create a new Integer object that holds the value 1? - java

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

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.

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.

Related

Default data type of the constants printed in System.out.print();

System.out.println(2147483647 + 1); //prints -2147483648
I know 2147483647 is the max value of integer data type. My question is why is this result calculated for Integer type, and why was it not considered for Long or double?
Because...
System.out.println(127+1); //prints 128
here why is 127 not considered for Byte data type, resulting in the result to be -128?
Fundmentally, you seem to not fully understand literals. A number without a decimal point or suffix is always an int, regardless of it's magnitude. This can be further complicated by implicit widening when assigning to larger primitive datatypes (e.g. int may be implicitly widened to long).
So now we know that your two literals are ints. int + int is always int. It doesn't matter whether the result will overflow or not.
If you know or suspect that the constants will exceed the range of int, add the suffix L (i.e. 2147483647L and 1L) to explicitly declare that these are longs. long + long = long, so the result will not overflow in this case.
println is overloaded with several inputs, your paramters are of type int so method will be called
public void print(int i) {
write(String.valueOf(i));
}
Every number in java sorce code is by default an integer. If you like to have an other type like long, you need to extend your number with an 'L' (e.g. 23409L) or you have to cast it. Only at initialization from a variable the compiler make the cast for you.
In many cases you can give byte or short also to methodes, even if they request for an integer parameter. But this only works because of java's conversions and promotions mechanism.
Because of all this functionalities some programmer mess up with the real data types they have at one point of the code.
For more infos visit the oracle documentation:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

Why does comparing Integers by reference (==) work?

In Herbert Schildt's "Java: The Complete Reference, 9th Edition", there's an example that kinda baffles me. Its key point that i can't comprehend could be summed up to the following code:
class Test {
public static void main (String args[]) {
Integer i1 = 6;
Integer i2 = 6;
Integer i3 = 6;
Integer i4 = (args.length + 1) * 6;
if (i1 == i2) System.out.println("WTF");
if (i3 == i4) System.out.println("Super WTF!!!");
}
}
To my surprise, the result of compiling and executing such code using JDK 8 update 40 is as follows:
WTF
Super WTF!!!
All the Java books, manuals and other informational resources that i've seen state that the equality operator (==), when used to compare objects, simply matches their reference values. So, if two object variables refer to distinct instances, then the == operator returns false, even if the internal contents of those objects are the same. Which is quite different from the behavior expressed by the example above.
While checking SO for similar questions, i found a somewhat related one, which is about comparing String objects using ==. There, an interesting feature of Java called interning was mentioned. Apparently, all the string literals and compile-time string constants are sort of "cached" by JVM, so that, for example, multiple String references initialized with the same string literals actually point to the same object.
But here we deal with numeric values and Integer objects. Also, one of the variables, i4, is initialized using a number of command line arguments supplied to the program, which is definitely a run-time information. Yet, == still finds it equal to i3.
So, given all the above, how exactly is the equality operator supposed to work in Java? Does it, or does it not, inspect the objects' contents when comparing them?
Thanks!
Integer objects are cached as mentioned by the Javadocs of Integer#valueOf(int):
This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
The statement Integer i4 = (args.length + 1) * 6; calls Integer#valueOf(int) which returns the cached instance. On the other hand, if you use Integer i4 = new Integer((args.length + 1) * 6);, the reference equality will return false.
I think the example shows us how java int pool is working. So in the i4 case if you provided no arguments on runtime the result is 6. Now the int pool kicks in and uses the i1 value which is part of the -128 to to 127 int pool. So on an object level they really equal and that's what == is all about.
When you autobox an int, you're internally calling Integer.valueOf(int), which according to the documentation may return cached values. So it makes perfect sense that you're seeing reference equality.
More generally, you should never assume two references are distinct unless you explicitly constructed them. And for the record, string interning is available at runtime as well, through the String.intern() method.

vectors in java contains only objects?

I have this question,
vectors in java only accept objects right? but this piece of code compiles just fine
Vector myv=new Vector();
myv.addElement(1);
myv.addElement(1);
does it encapsulate it as an object of Integer? and if it does, why do this statement
System.out.println(myv.elementAt(0)==myv.elementAt(1));
gives true ?!!! they're supposed to be two distinct objects...?
at the same time this statement throws an error, which ensures that the element is an object.
int x=myv.elementAt(0);
can someone explain this for me? thank you.
The 1 is auto-boxed into an Integer.
To learn more about Autoboxing and -unboxing, see Oracle's Docu: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
On why they are the same: Autoboxing ints to Integers uses a cache. For numbers < 128 (I think) the same Integer-Object will be returned each time instead of a new one being created. So your code essentially inserts the same object twice into the Vector, and for this reason the identity comparison using == returns true.
As you don't use generics with your Vector, myv.elementAt(0) will return an Object, which cannot be cast to an int. If you used generics, i.e. Vector<Integer> myv = new Vector<>(), then elementAt would return an Integer which would be auto-unboxed to an int.
That works because java auto boxes and auto unboxes these type for you.
But note that this doesn't work for sure in every scenario.
Let's take this example:
Integer i = 1234;
Integer z = 1234;
System.out.println("i: "+i);
System.out.println("z: "+z);
System.out.println("== : "+(i == z));
System.out.println("equals: "+i.equals(z));
It will produce the following output:
i: 1234
z: 1234
== : false
equals: true
DEMO
In fact, from this answer you can see that it works only for integers between -128 and +127
In fact, this behaves as expected:
Integer i = 123;
Integer z = 123;
System.out.println("i: "+i);
System.out.println("z: "+z);
System.out.println("== : "+(i == z));
System.out.println("equals: "+i.equals(z));
and produces:
i: 123
z: 123
== : true
equals: true
DEMO
Here is something pretty funny about Java, it caches integers between -128 and 127 (for auto-/un-boxing) and any reference to integers in that range all refer to the same object (since == here is comparing Objects). This can cause quite a few bugs when people don't thing through the == method comparing Objects, rather than values.
So you will get true for comparing "integers" (autoboxed) between -128 - 127. If you do the same thing with 128, it'll say false.
Check it out:
import java.util.Vector;
public class Vect {
public static void main(String[] args) {
Vector v = new Vector();
v.addElement(127);
v.addElement(127);
v.addElement(128);
v.addElement(128);
System.out.println(v.elementAt(0) == v.elementAt(1));
System.out.println(v.elementAt(2) == v.elementAt(3));
}
}
Will give you:
$ java Vect
true
false
This is called autoboxing. When the Java compiler encounters an integer, float or double value in a place where an object is expected, it automatically creates a wrapper object.
The code generated by the compiler for your code is equivalent to
Vector myv=new Vector();
myv.addElement(Integer.valueOf(1));
myv.addElement(Integer.valueOf(1));
The valueOf() method caches Integer instances for the values from -128 to 127 (IIRC), with the result that both values will be replaced by the same object.
Try the same with a lager value, like 1000. Then the objects will be different.
This is a feature of compiled code and auto-boxing.
Generics in Java are a compile-time issue. javac uses them to check that you use the types correctly, but the compiled byte code that's produced doesn't know anything about the generic types. Generics are implemented with type erasure in Java was mainly for backward compatibility. (That's also why raw types still exist in Java.)
It means that an Vector<E> will look like a plain, raw Vector at runtime - it's just a plain Vector that contains objects. Since primitives are not objects, you can't store primitive types in such an Vector.
There are wrapper classes for each of the primitive types (int -> Integer, long -> Long, short -> Short, boolean --> Boolean, etc.) so is possible to make it such that a Vector<int> would use auto-boxing to store ints in Integer objects, which could be stored in a Vector. ...but the designers of the Java language didn't decide to take auto-boxing that far.
Java's Vector is a generics, it means it can accept any kind of data to store. You have to specify the type of data to hold with a syntax like Vector<String>. Replace String for the kind of object you want the Vector to hold.
The reason that it gives true is because it is autoboxed into the Integer class automatically; when compares two Integers, it does the same way as the built-in type int.
EDIT: The autoboxing comparation works with the int values in the range [-128;+127].

Weird equality behavior in java [duplicate]

This question already has answers here:
Weird Integer boxing in Java
(12 answers)
Closed 8 years ago.
Take a look at following code:
Long minima = -9223372036854775808L;
Long anotherminima = -9223372036854775808L;
System.out.println(minima==anotherminima); //evaluates to false
System.out.println(Long.MIN_VALUE);
Long another= 1L;
Long one = 1L;
System.out.println(another == one); //evaluates to true
I am not able to understand this behavior..? I was hoping the first eval to be true as well..
And that is what I am expecting..
There is a caching technique used by the JVM for some range of autoboxing value. As specified in the spec ( http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 )
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
Ideally, boxing a given primitive value p, would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. The implementation may cache these, lazily or eagerly. For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part. This would allow (but not require) sharing of some or all of these references.
This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.
So 1L is in this cached values and then the autoboxing give the exact same reference, but in the case of the number outside of this range (like the Long.MIN_VALUE) it isn'T cached and thus a different instance/reference is given.
In any case, when comparing object you should always use .equals()
Just a guess here, but it could be that 1L is in the constant pool, and thus the reference equality evaluates to true (just like how sometimes, even by Strings, == will evaluate to true), while that other huge number isn't. Not sure how to check which constants are in the pool at initiation.
Edit: Java has a cache of certain constant objects (including the wrapper classes for primitives, and String). Thus, if you write
String st1 = "A";
if "A" is in the constant pool, Java won't create a new String object- it will just create a reference to the already existing one. So if you then did
String st2 = "A";
System.out.println(st1 == st2);
It would print out true.
Now, not all Integer, Long, Short, etc... are cached (there are way too many), but the lower values are. So I would assume that 1L is. That means that in your question, both another and one refer to the same object, and thus it returns true even for reference equality.
First of all you should use long instead of Long. Secondly == between Integer, Long etc will check for reference equality. You may check the 5.1.7 Boxing Conversion. Alo 1L is in the constant pool so the second case is returning true.
On a side note you should use .equals for comparing the long.
From the Oracle docs:
If the value p being boxed is true, false, a byte, or a char in the
range \u0000 to \u007f, or an int or short number between -128 and 127
(inclusive), then let r1 and r2 be the results of any two boxing
conversions of p. It is always the case that r1 == r2.
Ideally, boxing a given primitive value p, would always yield an
identical reference. In practice, this may not be feasible using
existing implementation techniques. The rules above are a pragmatic
compromise. The final clause above requires that certain common values
always be boxed into indistinguishable objects. [...]
This ensures that in most common cases, the behavior will be the
desired one, without imposing an undue performance penalty, especially
on small devices. Less memory-limited implementations might, for
example, cache all char and short values, as well as int and long
values in the range of -32K to +32K.
Adding on to this answer, everything from -128 to 127 is cached into an instance in permanent java memory, meaning that those numbers (almost) always have reference equality, because new instances are not created for them. Outside of the cache, a new instance is created every time the number is used, so they are not equal referentially. Read more here and here
problem:
(minima==anotherminima)
You are comparing the memory location of the object not its values thus it returns false.
If you want to compare two long wrapper class you need to call compareTo
From jls
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f,
or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results
of any two boxing conversions of p. It is always the case that r1 == r2.
Now if you use -128 and 127 to initialized the Long wrapper class it will result to boxing conversion which will have the same reference.
You should use long instead of Long. Note that Long is a class and so you must use equals() to compare instances of it. On the other hand, if you use long instead, you can compare with == because these are primitives.

Java JUnit assertEquals with Long

assertEquals( new Long(42681241600) , new Long(42681241600) );
I am try to check two long numbers but when i try to compile this i get
integer number too large: 42681241600
error. Documentation shows there is a Long,Long assertEquals method but it is not called.
You want:
assertEquals(42681241600L, 42681241600L);
Your code was calling assertEquals(Object, Object). You also needed to append the 'L' character at the end of your numbers, to tell the Java compiler that the number should be compiled as a long instead of an int.
42681241600 is interpreted as an int literal, which it is too large to be. Append an 'L' to make it a long literal.
If you want to get all technical, you can look up §3.10.1 of the JLS:
An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1). The suffix L is preferred, because the letter l (ell) is often hard to distinguish from the digit 1 (one).
You should also generally consider using Long.valueOf since this may allow some optimisation:
Long val = Long.valueOf(1234L);
From the J2SDK:
public static Long valueOf(long l)
Returns a Long instance representing
the specified long value. If a new
Long instance is not required, this
method should generally be used in
preference to the constructor
Long(long), as this method is likely
to yield significantly better space
and time performance by caching
frequently requested values.
append an "L" at the end of your number, like:
new Long(42681241600L)
in Java, every literal number is treated as an integer.

Categories