This question already has answers here:
int vs Integer comparison Java [duplicate]
(2 answers)
Closed 7 years ago.
public class Application {
public static void main(String[] args) {
Integer a = new Integer(10);
Integer b = new Integer(10);
int x = new Integer(10);
int y = new Integer(10);
int p = 10;
int q = 10;
System.out.println(a == b);
System.out.println(a == x);
System.out.println(x == p);
System.out.println(b == q);
System.out.println(y == q);
System.out.println(x == y);
}
}
The above code produces the output:
false
true
true
true
true
true
Please explain the process of primitive type getting compared to a reference type using == ?
how int x = new Integer(10); getting evaluated internally?
Integer a = new Integer(10);
Integer b = new Integer(10);
a==b ---> Reference variable a is compared to the reference variable b. Not the object they point to. And those two reference variables are indeed, different. Hence, false. Use .equals() to compare objects.
a==x ---> auto-unboxing. x contains the value 10. during comparison, Integer is compared to int. When wrapper is compared to premitive, auto-unboxing occurs. a becomes an int. And so, effectively 10 is compared to 10. Hence true.
x==p,b==q,y==q,x==y --> Same. Auto-unboxing, taking effect. Hence all true.
Whenever Java compares a wrapper class variable with a primitive variable, it unboxes the wrapper class variable into a primitive, and then compares them.
Compile this with SDK previous to Java 5, and I doubt if it would compile at all. Java introduced this feature from Java 5. If I can remember correctly..
When you compare the primitive int with its wrapper class Integer, the wrapper is unboxed to its primitive value. That is why you are getting true always except first condition.
In the first condition, your are checking the reference equality of two different objects, which will be false obviously.
== for classes compares references. When you make 2 objects with the same values you should use .equals() because 2 object the are instantiated with new will have different references. When using int it compares the values because they are primitives and passing in new Integer() into an int is creating a primitive int.
Related
When we assign objects of the same type to one another, the new object stores the address of the object that's being assigned to it. For instance, if I have my own class named CLA then the following code will produce 11 as the output:
public class CLA{
int val;
public static void main(String...args){
CLA ob1 = new CLA();
ob1.val = 10;
CLA ob2 = ob1;
ob1.val++;
System.out.printf("%d", ob2.val);
}
}
because ob2 would refer to ob1 and consequently show ob1's val.
However, the same doesn't happen for Wrapper classes. When I assign an Integer object to another, the operation simply behaves like we're dealing with values and not objects. As opposed to the above code, the output of the below code is 10:
Integer x = 10; //auto-boxed as new Integer(10)
Integer y = x;
x++;
System.out.printf("%d", y.intValue());
Why does this happen?
Do wrapper class objects get unboxed while being assigned to another object, so as to pass the value instead of the address??
When you do x++, it is the same as x = x + 1 so it is actually a new instance of Integer assigned to x but y still points to the old instance which value is 10.
Keep in mind that wrapper instances are immutable.
For an Integer x, the expression x++ can be understood like x = new Integer(x.intValue() + 1);. Its not exactly the same, but helps for understanding.
So, it doesn't modify the Integer object with the value 10 that x pointed to before the x++, it creates a new Integer object with the value 11 independent of the original 10 Integer, and assigns this 11 Integer to x.
But there's nothing in the x++ expression that would make y point to a different Integer instance. So y still points to the original 10.
That's the difference to the CLA example where you don't introduce a new instance with ob1.val++, but modify the single instance. If the Integer class had a public field value, then x.value++ would show the behaviour you expected - but the value field is (for good reason) private - not accessible to the outside.
I have a basic doubt, we can increment reference of Integer class object, while not reference of any other class(D class has 1 Integer data member and one parameterized constructor).
Integer x=new Integer(10); x++;
D d=new D(10); d++;
here both x and d are reference still we are able to increment Integer reference while not any other reference. I am missing something very basic, please help me out.
Integer x=new Integer(10); x++;
Here java compiler will do the un-boxing of the object, which converting the Integer object into primitive int. Then the increment operation will be performed. This is only defied for java primitives, the auto-boxing is converting primitive to wrapper object and reverse of it is call un-boxing. This is what is happening here.
The auto-boxing or un-boxing which is an automatic conversion, it is defined for java primitives only. So it can not be performed on other objects. Remember, the object are not just memory references like C or C++ that we can increment them.
This is because of Autoboxing for wrapper classes which was introduced from jdk 1.5. Internally java will convert the integer reference to int and increment it. You can't increment the objects.
Java has no way of overloading operators for arbitrary classes. Thus, D d; d++ is just not available. You can do:
public class D {
private int value;
public D( int v ){
value = v;
}
public void increment(){
value++;
}
}
Now you can do
D d = new D(10);
d.increment();
and d's value will be 11.
According to Oracle Java Documentation, The automatic conversion of primitive data types into its equivalent wrapper type is known as autoboxing and opposite operation is known as unboxing. Whenever we use object of wrapper class in an expression, automatic unboxing and autoboxing is done by JVM.
Integer object;
object = 100; //Autoboxing of int
++object;
When we perform an increment operation on Integer object, it is first unboxed, then incremented and then again reboxed into Integer type object. You can also take a look at How java auto boxing/unboxing works?
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 7 years ago.
May I know how == works here?
public class App {
public static void main(String[] args) {
String s1 = new String("str");
String s2 = new String("str");
System.err.println("why it,s "+String.valueOf(s1==s2));
int i1 = new Integer(10);
int i2 = new Integer(10);
System.err.println("why it,s "+String.valueOf(i1==i2));
}
}
When I am comparing references of two different String with the same values, then == says that they are not equal, but when I am comparing references of two integers with the same values, then == says that they are equal. Why is it so?
Ok, a more meaningful compare would be
public class App{
public static void main(String[] args) {
String s1 = new String("str");
String s2 = new String("str");
System.err.println("why it,s "+String.valueOf(s1==s2));
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
System.err.println("why it,s "+String.valueOf(i1==i2));
}
}
int is primitive, and == will just compare the value. Integer is an object, and == for objects is only true if it points to the same place in memory, otherwise it will be false. For primitives (int, boolean, etc...) == will test the value.
int i = Integer(10) is really int i = (Integer(10)).intValue(), java just does it automagically.
Edited to add more explanation:
Java has 2 types of types. Primitive types and Class types. A primitive type is just the value of the type: an int primitive type is just that, and int. There are not methods or anything, it just is an int.
If you say int a = 4, a is a primitive variable that points to a memory address that contains an int. That's it.
A Class type is a java object, so Integer is a class type. It represents an integer value, so Integer a = new Integer(4) would create an integer object, and a would point to a memory location that contains the object that new... created.
What's different?
Good question. In the latter example (new Integer(4)) this is an integer and some other stuff, stuff like a toString() method and some other stuff.
So, a recap:
A primitive is a value stored in memory somewhere.
A class is an object stored in memory somewhere, and in the case of Integer it represents an int but it has some other stuff associated with it (i.e. the `toString() method).
Now, == is a test for equivalency. So int == int checks to see if the primitive value is the same, since that is the only information that a primitive type has.
== for objects does mean something. Since an object points to a more than just a 4 or 8 or -1, the == only returns true if the object variables point to the same place in memory. If it does not, then you get false.
So:
int i = 1;
int j = 1;
Integer k = new Integer(1)
Integer l = new Integer(1)
Integer m = k;
Integer n = new Integer(k)
i == j -> true
k == l -> false
k == k -> true
k == l -> true
n == m -> false
n.intValue() == m.intValue() -> true (intValue returns a primitive type)
Now, .equals is a test to see if two objects are equal, which means different things for different objects.
For an Integer, a.equals(b) is true if the intValue()s are the same for a and b. However, a == b is true if a and b point at the same object in memory
Now, thing about an object that has 2 integers in it (like an x,y coordinate).
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
static void number(int x){
x=42;
}
public static void main(String[] args) {
int x =17;
number(x);
System.out.println(x);
why is the value printed out still 17 and not 42? Thanks!
The line
number(x);
passes the value of x into number. Nothing that links back to x is passed at all. Inside number, the x argument you've declared is not in any way linked to the x variable in main; it just receives the value that you passed into number. Assigning to the argument (x = 42) just changes the value of the argument, not the variable in main.
This is called pass-by-value, meaning that whenever you pass a variable into a method, the value of that variable is passed, not anything about the variable itself. Exactly the same thing happens here:
x = 17;
y = x;
y = 42;
System.out.println(x); // 17
System.out.println(y); // 42
y = x just takes the value of x and puts it in y. There's no ongoing link between x and y.
So how would you change it? The usual approach is have number return a new value:
int number(int val) {
return val * 2;
}
Then in main:
x = 17;
x = number(x);
System.out.println(x); // 43
Sometimes, people get confused by pass-by-value when it involves object references. Variables directly contain primitives like int, but they don't directly contain objects; they contain object references. So consider:
List<String> l1 = new LinkedList<String>();
Now, l1 contains a value that is a reference to the linked list object. Now suppose we do this:
List<String> l2 = l1;
What happened there? Do we have one list, or two?
The answer is, of course, one: The value we copied from l1 to l2 is the reference to the list, which exists elsewhere in memory.
Key points in summary:
When you pass a "variable" into a method, it's the value of the variable that gets passed (always — Java is purely pass-by-value [some other languages have something called pass-by-reference, where a reference to the variable is passed, but Java doesn't have that)
The same thing happens when you assign a variable to another variable
Object references are values that tell the JVM where the object is in memory
Java is pass by value So when you passes x which is defined in main() to number() method ,only the value is copied to function parameter x and no address is passed unlike C pointers.So the value you get is 17 because it is not changed.
Considering Java. How are these 2 different and why?
public void languageChecks() {
Integer a = 5;
Integer b = new Integer(5);
change(a); // a doesn't get incremented. value is 5
change(b); // b does. value is now 6
}
public void change(Integer a) {
a++;
}
The only difference is that
Integer b = new Integer(5);
guarantees a new object is created. The first will use an instance from a cache (see Integer.valueOf()).
Both are immutable and the references to both are passed by value (as is everything in Java). So change() has no effect on either.
I'd always been taught a++ was just shorthand for a = a + 1 in which case a local variable is created named a and immediately thrown away when the method returns. There're no methods on Integer that change the value (it's immutable), and likewise no operations on primitive ints that change their value.
Neither call to change() affects the values passed in, because of auto-boxing/unboxing.
public void change(Integer a) {
// This unboxes 'a' into an int, increments it and throws it away
a++;
}
The above code seems to imply that a++ changes the value of a, since it's an object, not a primitive. However, ++ is not overloaded by Integer, so it unboxes it to be able to apply the ++operator on its int. To me the compiler shouldn't allow this.