import java.util.Stack;
public class StackIntro {
public static void main(String[] args){
Stack clapper = new Stack();
for( int i=0; i<11; i++){
clapper.push(i);
}
while(!clapper.isEmpty()){
System.out.print ( clapper.pop() ); //FILO
System.out.print ( ',' );
if(clapper.size()==1){
System.out.print(clapper.pop()); //FILO
System.out.println("...");
}
}
System.out.println("Lift-off.");
clapper.removeAllElements();
}
}
So basically I just wanted to see how numbers go in and out of a stack. The FILO comment shows this. I was told that I should actually change line 8 :
clapper.push(i); //previous
clapper.push(new Integer(i)); //new
I don't understand what this would accomplish, or the difference between the two.
Although due to autoboxing both lines of code result in an Integer object with value 1 being pushed on the stack, the two lines do not have exctly the same effect.
Autoboxing uses the Integer cache, which is required by the JLS for values from -128 to 127, such that the resulting Integer instance is the same instance for any value in that range.
However, invoking the int constructor creates a new Integer instance every time it's called.
Consider:
Integer a = 1; // autoboxing
Integer b = 1; // autoboxing
System.out.println(a == b); // true
Integer c = new Integer(1);
Integer d = new Integer(1);
System.out.println(c == d); // false
This distinction may cause different behaviour in your program if you use == (object identity) when comparing values pushed and popped to/from the stack instead of equals().
This would not accomplish much, very possibly not anything at all.
The idea is that clapper.push(T) accepts an object, but i is not an object, it is a primitive, so the compiler will automatically box it into an Integer object before passing it to clapper.push().
Auto-boxing was not a feature of java from the beginning, so there may still exist some old-timers who are uncomfortable with it. But that should be entirely their own problem. Java has come a long way since then. Auto-boxing is taken for granted, we do not even give it any thought anymore.
Passing i and having the compiler auto-box it is exactly the same as as passing new Integer(i).
Related
Why can't Byte and Number/Integer be compared? I have attached my source code. See the comments. Also why I have to cast 88 into byte, isn't it done automatically with auto-boxing and auto-unboxing?
package com.practice;
public class Generics<T extends Number>
{
T ob;
public Generics(T i)
{
ob = i;
}
T getObj()
{
return ob;
}
boolean compare(Generics<?> o)
{
if (this.ob == o.ob)
{
return true;
}
else
{
return false;
}
}
public static void main(String[] args)
{
Generics<Number> num = new Generics<>(88);
// Generics<Byte> Byte = new Generics<>(88); //why this does not
// compile?
Generics<Byte> Byte = new Generics<>((byte) 88);
Generics<Integer> integer = new Generics<>(88);
System.out.println(num.compare(integer)); // this is true!!
System.out.println(num.compare(Byte)); // why False?
System.out.println(integer.compare(Byte)); // Why false?
}
}
Why I have to cast 88 into byte, isn't it done automatically with auto-boxing and auto-unboxing?
By default, a numeric literal (like 88) is an int. The auto-boxing does happen but the compiler boxes it into an Integer and not a Byte because, as I just told, it's an int.
Generics<Number> num = new Generics<>(88);
Generics<Integer> integer = new Generics<>(88);
Since, an Integer IS-A Number both of the above work just fine.
Generics<Byte> Byte = new Generics<>(88); // why this does not compile?
Now, in case of Generics<Byte>, the constructor becomes Generics(Byte i), which fails because an Integer cannot be assigned to a Byte as there's no inheritance between them. They both extend Number and are sibling classes.
Generics<Byte> Byte = new Generics<>((byte) 88);
So, to pass in a Byte and satisfy the compiler, the (byte) cast is required. Now the auto-boxing happens again but from a byte to Byte this time.
Regarding equality, your compare() method implementation is flawed because it only compares references this.ob == o.ob and not their values.
System.out.println(num.compare(integer)); // this is true!!
System.out.println(num.compare(Byte)); // why False?
System.out.println(integer.compare(Byte)); // Why false?
This however worked for integer comparison num.compare(integer) because you chose a small value 88 which falls in the range of values (-128 to +127) cached and shared by the JVM among auto-boxed Integer instances. If you run your program again with a larger value like 888, it will print false for the same comparison.
So, to fix your compare() method, you'll need to sort of unbox their numeric values.
return (this.ob.floatValue() == o.ob.floatValue());
PS: The equals() method wouldn't help here. Check the source code to know why :)
List<Integer> stack1 = new ArrayList<>();
List<Integer> stack2 = new ArrayList<>();
//some add operation
......
//some add operation
if(stack1.remove(index1) == stack2.get(index2-1))
stack2.remove(--index2);
The code above works wrong.
While the code below works right.
List<Integer> stack1 = new ArrayList<>();
List<Integer> stack2 = new ArrayList<>();
//some add operation
......
//some add operation
int i = stack1.remove(index1);
int j = stack2.get(index2-1);
if(i == j)
stack2.remove(--index2);
The former code works that even if the 'if' sentence in latter code judges true, it judges false, which makes me confused.
The stack elements are Integer objects. In the first case you compare them for identity, in the second case you compare the values.
Try this
if(stack1.remove(index1).equals(stack2.get(index2-1)))
In Java, the == comparator on Object references don't test that the values of the Objects are equivalent. It tests that the references refer to the same Object. In the first case, you're checking if the Integer reference from stack1 and Integer reference from stack2 both refer to the same Integer object.
To test Objects for value equivalence, you generally use the object.equals(otherObject) method.
In the second case, Java does a sneaky thing called autoboxing where it converts an Object to its primitive type, i.e. from Integer to int. The == comparison on primitives is what you'd expect.
See https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html from more info on autoboxing.
In the first case you're using the '==' operator on two Integer objects. That check evaluates to 'true' only if the the two object references point to the same object (same memory location). In the second case you're using '==' operator on two primitive integers. That check evaluates to true if the value of the primitives is the same, even if they reside in different memory locations.
I know the concept of String pool in PermGen area of heap. So when we do something like
String firstString = "Stack";
String secondString = "Stack";
both references firstString and secondString point to the same object in the pool. But I tried the same for a variable of type int.
int firstInt = 5;
int secondInt = 5;
if(firstInt == secondInt) {
System.out.println("Both point to same allocated memory");
} else {
System.out.println("Both point to different allocated memory");
}
and the result is Both point to same object and when i tried
Integer firstInteger = new Integer(2);
Integer secondInteger = new Integer(2);
if(firstInteger == secondInteger) {
System.out.println("Both point to same object");
} else {
System.out.println("Both point to different object");
}
output is Both point to different object
I tried the same for char and the result is similar. So my question do we have pools for all primitive types like int, char? And when we actually create objects with same content using new () as in the second case mentioned above is the object cloned and stored in same pool area or is it outside the pool?
There is so much misconception in your post, it is hard even to start explaining. Get some decent book. For now, some facts that might help you:
String is not a primitive type,
there are no pools of primitive types, because there cannot be a reference to a primitive type (the answer saying that they are only kept on the stack is plain wrong!)
if you use new, you bypass pools anyway; so executing new String("ala") will always create a new String object; you cannot change the semantics of new;
if you want to use available pools, use factory methods on objects (like Integer.valueOf), they will - to some extent - pool instances (it is not viable or beneficial to pool all possible values of Integers, Floats etc.).
Primitives are not objects. They can be stored directly in the generated code.
In your second code block, you're testing equality of value, not that two objects are the same.
int firstInt = 5;
int secondInt = 5;
if(firstInt == secondInt)
{
System.out.println("Both point to same object");
// NO - neither point to an object -- their alues are the same.
}
You can share the same Integer object among multiple references by explicitly using Integer.valueOf(int), which may return the same object for multiple calls.
If you try
if (Integer.valueOf(2) ==Integer.valueOf(2))
you will get true.
With the Integer firstInt = new Integer(2) you create a new local variable that is != to another local variable created with Integer secondInt = new Integer(2). Same goes for String type.
The reason behind this is that == checks equality of the variables. Variables could be different (== results in false) even though they point to two objects that are "the same". The same in this context means obj1.equals(obj2) returns true.
If you want object representation of primitve types and also StringS to be stored in PermGen then do not use new keyword, i.e. Integer firstInt = 2;, String firstString= "whatevs"; beacause the keyword new creates an object on the heap.
Sometimes, to answer advanced questions it is enough to look through source code. For instance, here is the code of Integer#valueOf(int i) method:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Values IntegerCache#low and IntegerCache#high could be changed via vm options:
The size of the cache may be controlled by the -XX:AutoBoxCacheMax=<size> option.
I believe this is a very valid question that needs to be answered. For any future readers, the way the == operation works for Object types and primitive types are different.
Primitive types(int, char, double, long....) are evaluated by their values.
Whereas Primitive Wrappers (Integer, Double, String ....) are actually objects and not just values.
So when we use Integer class as
Integer number = new Integer(10)
A new Object is created in the memory which is not the case for primitive data types.
The == evaluation checks the memory, as well as the value for the Object types and for primitive types, checks the value only.
For example, look at this code:
Integer myInt = new Integer(5);
int i1 = myInt.intValue();
int i2 = myInt;
System.out.println(i1);
System.out.println(i2);
As you can see, I have two ways of copying my integer value from the wrapper to the primive:
I can use unboxing,
OR
I can use the method Integer#intValue().
So what's the need of having a method when there is already unboxing?
Unboxing was introduced in Java 5. The wrappers (including this method) have been there since the original release.
A link to the Javadoc
In that time (1996) we did need the intValue() method and as Oracle guarantees backward backwards compatibility... up to a certain level (it is not always 100% on major releases).
The method has to stay in.
In addition to Frank's answer which gives a good historical perspective there is still a need to use the intValue() today in some situations.
Be aware of the following pitfall that shows that you cannot regard an Integer as an int:
Integer i1 = new Integer(5);
Integer i2 = new Integer(5);
//This would be the way if they were int
System.out.println(i1 == i2); //Returns false
//This is the way for Integers
System.out.println(i1.intValue()==i2.intValue()); //Returns true
System.out.println(i1.equals(i2)); //Returns true
Returns
false
true
true
What is the difference between them?
l is an arraylist of Integer type.
version 1:
int[] a = new int[l.size()];
for (int i = 0; i < l.size(); i++) {
a[i] = l.get(i);
}
return a;
version 2:
int[] a = new int[l.size()];
for (int i = 0; i < l.size(); i++) {
a[i] = l.get(i).intValue();
}
return a;
l.get(i); will return Integer and then calling intValue(); on it will return the integer as type int.
Converting an int to Integer is called boxing.
Converting an Integer to int is called unboxing
And so on for conversion between other primitive types and their corresponding Wrapper classes.
Since java 5, it will automatically do the required conversions for you(autoboxing), so there is no difference in your examples if you are working with Java 5 or later. The only thing you have to look after is if an Integer is null, and you directly assign it to int then it will throw NullPointerException.
Prior to java 5, the programmer himself had to do boxing/unboxing.
As you noticed, intValue is not of much use when you already know you have an Integer. However, this method is not declared in Integer, but in the general Number class. In a situation where all you know is that you have some Number, you'll realize the utility of that method.
The Object returned by l.get(i) is an instance of the Integer class.
intValue() is a instance method of the Integer class that returns a primitive int.
See Java reference doc...
http://docs.oracle.com/javase/6/docs/api/java/lang/Integer.html#intValue()
Java support two types of structures first are primitives, second are Objects.
Method that you are asking, is used to retrieve value from Object to primitive.
All java types that represent number extend class Number. This methods are in someway deprecated if you use same primitive and object type since [autoboxing] was implemented in Java 1.5.
int - primitive
Integer - object
Before Java 1.5 we was force to write
int i = integer.intValue();
since Java 1.5 we can write
int i = integer;
Those methods are also used when we need to change our type from Integer to long
long l = integer.longValue();
Consider this example:
Integer i = new Integer(10);
Integer j = new Integer(10);
if (!(i == j)) {
System.out.println("Surprise, doesn't match!");
}
if (i.intValue() == j.intValue()) {
System.out.println("Cool, matches now!");
}
which prints
Surprise, doesn't match!
Cool, matches now!
That proves that intValue() is of great relevance. More so because Java does not allow to store primitive types directly into the containers, and very often we need to compare the values stored in them. For example:
oneStack.peek() == anotherStack.peek()
doesn't work the way we usually expects it to work, while the below statement does the job, much like a workaround:
oneStack.peek().intValue() == anotherStack.peek().intValue()
get(i) will return Integer object and will get its value when you call intValue().In first case, automatically auto-unboxing happens.
They are exactly the same. As other posters have mentioned, you can put either the Integer object or the int primitive into the array. In the first case, the compiler will automatically convert the Integer object into a primitive. This is called auto-boxing.
It's just a convenience method for getting primitive value from object of Number: http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Number.html
Consider the code:
Integer integerValue = Integer.valueOf(123);
float floatValue = integerValue.floatValue();
The last line is a convenient method to do:
float floatValue = (float)(int)integerValue;
Since any numeric type in Java can be explicitly cast to any other primitive numeric type, Number class implements all these conversions. As usual, some of them don't make much sense:
Integer integerValue = Integer.valueOf(123);
int intValue = integerValue.intValue();
int intValue2 = (int)integerValue;
int intValue3 = integerValue;