As the String is an object, you need to use the string.equals(string) method to confirm that the two strings are equal.
However, why do you use the == to check if two chars are equal, char1 == char2, rather than char1.equals(char2)?
Perhaps, this will help to understand the difference on == vs equals.
#Test
public void testCharacterEquals() {
//primitive type uses == operator for equals comparasion
char a1 = 'A';
char a2 = 'A';
if (a1 == a2) {
System.out.println("primitive type comparasion: it's equal");
}
//From Java doc; The Character class wraps a value of the primitive type char in an object. An object of type Character contains a single field whose type is char.
//Object type uses equals method for equals comparasion
Character character1 = 'A';
Character character2 = 'A';
if (character1.equals(character2)) {
System.out.println("object type comparasion: it's equal");
}
}
It depends on using a primitive type, char, int, etc. And using Objects like String. A primitive type like an int can be compared 1 == 1 and if you check 2 objects to each other ObjectA != ObjectB.
Check out this answer over here: Primitive vs Object type in Java
Or over here: https://chortle.ccsu.edu/java5/Notes/chap09C/ch09C_2.html
Quote:
A primitive data type uses a small amount of memory to represent a
single item of data. All data of the same primitive type are the same
size.
For example, primitive type int represents integers using 32 bits. All
variables of type int use 32 bits.
There are only eight primitive data types in Java: byte, short, int,
long, float, double, char, and boolean. A Java program cannot define
any other primitive data types.
An object is a large chunk of memory that can potentially contain a
great deal of data along with methods (little programs) to process
that data. There are thousands of object classes that come standard
with Java, and a programmer can easily create additional classes.
(Although there are thousands of standard classes, for this course you
only need become familiar with a dozen or so classes.)
Where 2 strings are 2 different objects. Therefor not the same object and not the same string. While the characters might be the same.
Basically Java has primitive types (int, char, short, long, byte ....)
and Reference Data types/ Objects composed of other primitives and Objects.
equals() is a method of all Java Objects. But char is not an Object type in Java, it is a primitive type, it does not have any method or properties, so to check equality they can just use the == equals operator.
You can also use a comparator if you want.
public static boolean compareChars(char c1, char c2){
int comp = Character.compare(c1, c2);
if(comp>0){
return false;
}else{
return true;
}
}
public static void main (){
boolean b1 = compareChars('A', 'A') //return true;
boolean b2 = compareChars('A', 'C') //return false;
}
Because char is a primitive type and does not implement equals, == compares char values directly in this case, where as String is an object. So for object comparison, the equality operator is applied to the references to the objects, not the objects they point to. Two references are equal if and only if they point to the same object, or both point to null.
If you want to compare strings (to see if they contain the same characters), you need to compare the strings using equals().
Hence, the operator == checks equality of values on primitive types, but it checks references equality for objects. If the two objects are referenced by equal references, a reference and an object are different in Java.
Related
I am given an instance of the object class (String, int, double, or boolean) from a database. I need to write a method that can compare this object to something else (String, int, double, or boolean) using binary operators (e.g. <=, !=, >, etc.). I will only run this method if the two objects are of the same type. My method looks like
public boolean comparison(Object a, Object b, String operator) {
int result = a.compareTo(b);
String a2 = a.getClass().getName();
//followed by if/else if blocks to return true or false
//depending on operator and result
}
I have designed the if/else if blocks to ensure that no binary operator will be used for incompatible types (e.g. >= for a String object). The problem is that I get a "can't find symbol error" when I try to compile because the object class doesn't have a compareTo() method. If this was python, there wouldn't actually be any issue because I would never be putting anything into the comparison function that didn't have a compareTo() method. However, because of java's formatting I'm forced to declare the input as 'Object' because I can't say specifically what type of object I have to compare at a given moment.
Is there some way I could override Java's restrictions and force it to trust me that Object a will always have a compareTo() method? Because right now, it seems like I'm going to have to downcast the objects into Strings, ints, doubles, or booleans, and then write 4 different new comparison functions for each data type.
Since the compareTo method is declared in the java.lang.Comparable<T> interface, the usage of Bounded Type Parameters can constrain your a and b arguments in order to accept only objects which implement the interface itself.
You can check the operator parameter in order to affect the boolean result.
If you wish, the usage of an enum value helps to avoid string mismatching.
For brevity, the code below doesn't take in account null values.
enum Operator {
GREATER_OR_EQUALS,
LESS_OR_EQUALS
}
public <T extends Comparable<T>> boolean comparison(T a, T b, Operator operator) {
int test = a.compareTo(b);
switch(operator) {
case GREATER_OR_EQUALS:
return test >= 0;
default:
return test <= 0;
}
}
The Java way is to first use the instanceof operator to then cast to an appropriate class:
if (a instanceof String && b instanceof String) {
String aAsString = (String) a;
int comparisonResult = a.compareTo(b);
compareTo() gives you a negative result if a < b, 0 when a == b and a positive result if a > b. So alone that int result tells you enough to decide what your potential comparison operations should result in. The numeric types int/Integer, ... have similar methods.
Of course this only works if your assumptions are really correct and the object is really a String or Boolean. And please note that boolean and Boolean are two somehow different types!
Casting variables in Java
The top answer summarizes what I wanted to do. The code successfully compiled when I said
int result;
if (a instanceof Comparable && b instanceof Comparable) {
result = ((Comparable) a).compareTo((Comparable) b);
}
I haven't tested it, but fantaghirocco's solution also seems like it could work.
I have an ArrayList of objects ArrayList<Object> arrList containing wrapper classes for the various primitives as well as an array of type Parameter Parameter[] parameters
Both have the same number of elements. I would like to loop through the elements of parameters and compare that their types are the same as those in arrList.
I realise there are many ways of comparing an int with Integer.lang.Integer such as simply casting the int to an Integer and then comparing but my Parameter[] has ints, booleans, floats etc and my ArrayList has Integers, Floats, Booleans etc, so I am not always sure what the value will be.
I don't think I really understand how primitives are represented. For example, I assumed the following statement would return true but it does not:
Boolean bool=true;
System.out.println(boolean.class==bool.getClass());
I have this the relevant bit of code:
for(int i=0; i<parameters.length; i++){
if(parameters[i].getType()==arrList.get(i).getClass()){
doSomething();
}
}
But the comparison always returns false even when it compares boolean.class to Boolean.getClass()
Thanks for any help/advice
You can use the static field TYPE that every wrapper class has. (source)
for(int i=0; i<parameters.length; i++){
if(parameters[i].getType()==arrList.get(i).getClass().getField("TYPE").get(null)){
doSomething();
}
}
You could also compare the lowercase class names but you would have to handle int and char as special cases.
Alternatively you could create a Map<Class, Class> between primitive classes and wrapper classes.
I suppose that conversions described in jls are sorted according the priority.
first has greate priority.
jls
Thus I solved that Boxing has greater priority than Unboxing. I decided to check this assumption.
research following code:
public class BoxingUnboxingPriority {
public static void main(String [] args){
int sn = 1000;
Integer isn1= new Integer(sn);
System.out.println(sn == isn1 );
}
}
out:
true
What is boxing? is just new Integer(primitiveInt)
I changed the code a bit
int sn = 1000;
Integer isn1= new Integer(sn);
Integer isn2= new Integer(sn);
System.out.println(isn1 == isn2 );
out:
false
Thus I made mistake.
Please clarify me this issue.
The relevant section:
15.21.1. Numerical Equality Operators == and !=
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
So:
Integer o = 1;
int i = 1;
boolean b = o == i;
...is equivalent to:
boolean b = o.intValue() == i;
Where both are of type Integer neither is a primitive numeric type - they are both object references.
When you use primitive with a Wrapper object, that wrapper object will be unboxed and then the operation will be applied.
In your first case, when you comparing sn with isn1, isn1 will be unboxed and the value will be compared. So you got true.
In second case, isn1, isn2 are two different object, so == operator will give false
I suppose that conversions described in jls are sorted according the priority.
That is incorrect. The JLS does not talk about "priorities" for conversions. It is not a recognized concept.
In fact, the conversions that can be applied are documented on a case by case basis for each operator, and so on. Thus JLS 15.21.1 says that == or != for numeric types results in "binary numeric promotion" of both operands. And JLS 5.6.2 says that binary numeric promotion consists of "unboxing conversion" (5.1.8) followed by "widening primitive conversion" (5.1.2) and finally "value set conversion" (5.1.3).
By contrast, JLS 15.21.3 says that when two references are compared using == or !=, no promotions or conversions take place.
(In fact, a common Java beginners mistake is to use == to compare two Integer objects rather than the equals(Object) method. And probably that is what "the question" you are looking at is trying to test your understanding of ...)
int sn=1000;
Integer isn1=new Integer(sn);
System.out.println(sn == isn1 );
will be converted to
System.out.println(sn == isn1.intValue());
while comparing primitive with wrapper the wrapper object first will be unboxed and then comparison.
wrapper object intValue() returns int so due to primitive comparison result true.
Integer isn1= new Integer(sn);
Integer isn2= new Integer(sn);
System.out.println(isn1 == isn2 );
// comparing two different object so false.
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.
This question already has answers here:
How can I properly compare two Integers in Java?
(10 answers)
Closed 5 years ago.
I have the following code:
public class Test {
public static void main(String[] args) {
Integer alpha = new Integer(1);
Integer foo = new Integer(1);
if(alpha == foo) {
System.out.println("1. true");
}
if(alpha.equals(foo)) {
System.out.println("2. true");
}
}
}
The output is as follows:
2. true
However changing the type of an Integer object to int will produce a different output, for example:
public class Test {
public static void main(String[] args) {
Integer alpha = new Integer(1);
int foo = 1;
if(alpha == foo) {
System.out.println("1. true");
}
if(alpha.equals(foo)) {
System.out.println("2. true");
}
}
}
The new output:
1. true
2. true
How can this be so? Why doesn't the first example code output 1. true?
For reference types, == checks whether the references are equal, i.e. whether they point to the same object.
For primitive types, == checks whether the values are equal.
java.lang.Integer is a reference type. int is a primitive type.
Edit: If one operand is of primitive type, and the other of a reference type that unboxes to a suitable primitive type, == will compare values, not references.
Integer objects are objects. This sounds logical, but is the answer to the question. Objects are made in Java using the new keyword, and then stored in the memory. When comparing, you compare the memory locations of the objects, not the value/properties of the objects.
Using the .equals() method, you actually compare the values/properties of objects, not their location in memory:
new Integer(1) == new Integer(1) returns false, while new Integer(1).equals(new Integer(1)) returns true.
ints are a primitive type of java. When you create an int, all that is referenced is the value. When you compare any primitive type in Java, all that is compared is the value, not the memory location. That is why 5 == 5 always returns true.
When you compare an Integer object to a primitive type, the object is cast to the primitive type, if possible. With an Integer and an int this is possible, so they are compared. That is why Integer(1).equals(1) returns true.
What you'll use new Integer(1) to create new object, it creates a totally different object each time even though it has the same value. The '==' checks if the objects are same, not data values. In your case, you could have checked the value as follows :
if(alpha.intValue() == foo.intValue()) {
//
}
Integer == int here auto boxing applied ( so Integer converted to int before comparision) so true.. but Integer == Integer here object comparison so as reference are different so false..
First example:
Using the == operator between objects checks for reference equality, and since you are comparing two different objects they do not equal.
Second example:
When using the == between a wrapper type (Integer, Long, etc.) and a numeric type (int, long, etc.) the wrapper type is unboxed and the equality check is done between the two primitive numeric types (I.e. between int and int). The unboxing is part of binary numeric promotion, read more here: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2