I am currently taking a java class in university. This is my first programming class and I've stumbled on something that I just cannot understand. As i learned, there are two ways of comparing variables. The first is using the ==, !=, <, > , =< , >= signs for PRIMITIVE variables such as int,double,etc. and the second way is to use the .equals() method for reference type. Now here is my question:
When I use the .getClass() method, I can compare two classes with the .equals() method and the == / != method. Since I can use the ==/!= signs, I'd suppose that the .getClass() method which returns the class of an object must return a primitive type. But searching on google the only thing I found out about this method in the java API is that it returns the class of an object. It doesn't tell me the variable type it returns. How exactly does this method work. What does it return? I tried to ask my teacher but she didn't know. Thank you!
You first need to know how == and != compare the two operands. The reason why == and != cannot be used to compare reference types is that they actually compare the memory addresses of the two reference type variables.
So if I have two strings:
String x = "Hello";
String y = x;
Since x and y share the same memory address after the second line is executed, x == y evaluates to true.
The same goes for the getClass() method. The getClass() method returns the class of the object as a Class<T> object. The question is, why this evaluates to true:
x.getClass() == y.getClass()
The answer is simple. Because x and y are both of type String. So calling getClass will return the same instance. This means the two returned the objects share the same memory address.
"But when I compare strings with the same characters with the == operator, it evaluates to false!" you shouted.
This is because the strings are located at different memory addresses. But the classes that getClass will return is always at the same memory address if the class that they represent is the same. This is due to the way ClassLoader works. But I'm not an expert that.
You just need to know that the objects returned by getClass is at the same memory address if the classes they represent are the same.
The comparators == and != compare equality in the way of identity. So how this works for primitives is obvious. However it can also be used to compare objects. However most often this does not work as expected. There are some exceptions:
Strings are stored as literals, therefore if you define two instances of String containing the same value, they use the same literal. Think of this like both instances pointing to the same memory location.
Enums are basically a collection of constants, therefore an enum value is either the same instance or it is not. It cannot be that the enum has the same value but is another instance.
The same is true for Class objects, which is what you get when calling getClass(). A Class object is created by the ClassLoader the first time it is the *.class file is loaded. On subsequent calls the same Class object is used. Therefore Class objects may be compared with == and !=. However beware that if A.class is loaded by two different ClassLoaders, the class objects that you get returned from them are not of the same instance.
getClass() returns an instance (object) of the Class class. Since each Java class has a single instance of the Class class, if two objects belong to the same class, getClass() for those two objects will return the same isntance and therefore you can use == for comparing them, since == when applied to reference types determines if the two references refer to the same instance.
The .getClass method will just return the class of the object. When you declare a new instance of an object, it will be referring to a class. There can only be one class per jvm but multiple object referring to it. So when you get the class of two objects, they might be referring to the same class!
polymorphism is one of the most important feature for java. for example:
//this shows one use of getclass method.
public class Main {
public static void main(String[] args) {
Main m = new Main();
Animal animal = new Animal();
Human human = new Human();
m.dosomething(animal);//print animal
m.dosomething(human);//print human
}
private void dosomething(Animal an){
System.out.println(an.getClass().toString());
}
}
class Human extends Animal{
private void dance(){
}
}
class Animal{
private void eat(){
}
}
Related
Can someone please explain the difference between this and getClass in Java?
Aren't they the same? getClass returns the class of an object and this does the same thing, right?
The difference between an object and a class
No, they are pretty different, so much that it doesn’t make much sense to compare them.
this can be regarded as a constant reference to the containing object. So not a class, and not being a method it doesn’t return anything. It just is a reference.
getClass() is a method and returns a reference to an object’s class. So not the object itself. Also being a method you can trivially call getClass() on a different object — any object, in fact — whereas this is always the containing object.
An example may demonstrate it. The following isn’t meant to be meaningful as a program that anyone could use for an external purpose.
package ovv.so.objects.basic;
public class ThisAndGetClassDemo {
int i;
public void foo() {
i = 3;
System.out.println(this);
System.out.println(getClass());
System.out.println(this.getClass());
System.out.println("A string".getClass());
}
#Override
public String toString() {
return "ThisAndGetClassDemo " + i;
}
public static void main(String[] args) {
new ThisAndGetClassDemo().foo();
}
}
Output from the program is:
ThisAndGetClassDemo 3
class ovv.so.objects.basic.ThisAndGetClassDemo
class ovv.so.objects.basic.ThisAndGetClassDemo
class java.lang.String
So you see:
this gives us the object (printing it implicitly calls toString() and then prints the return value).
getClass() and this.getClass() produce the same output. Calling getClass() without qualification (without mentioning which object’s getClass method we want to call) calls the object’s own getClass method — exactly the same as what this.getClass() does. In both cases the class is printed, not the object itself.
Finally "A string".getClass() gives us the String class because "A string" is an instance (an object) of that class.
I do understand your confusion, though. Every now and then we hear programmers being sloppy and in what they say not making that distinction between an object and a class — in particular in situations where there is only one object of a given class in play (which happens often). It’s like saying “horse” without making explicit whether I mean the horse (the object; given there is only one around) or I mean the concept of a horse (the class).
I want to compare the super classes of two different objects.If it is same then it should ask for another opponnet. Unless it selects the type that is diffenret. I have the following code for it. But it always returns true.
boolean equal(Characters C)
{
return (C.getClass().getSuperclass()== Char.getClass().getSuperclass());
}
we can compare the objects of different classes by calling O1.getClass()==O2.getClass() function of object if the object has same class it return true else false. In case of inheritance if we want to know that the two objects are belonging to same superclass or different then we calling O1.getClass().getSuperClass()==O2.getClass().getSuperClass() to campare.
public class SomeClass {
public static void main(String[] args){
int[] a={1,2,3};
int[] b={1,2,3};
int[] c=a;
String s="Neanderthal";
String s2="Neanderthal";
String s3=s;
System.out.println((a.equals(b))?"Same":"Different");
System.out.println((a.equals(c))?"Same":"Different");
System.out.println((s.equals(s2))?"Same":"Different");
System.out.println((s.equals(s3))?"Same":"Different");
}
}
The 1st system.out.print returns the value different and i cannot see a reason for this, and all the others are the same. Please help me understand this
Unlike Strings which are compared for equality character-by-character *, Java arrays are compared only for reference equality. You need to use Array.equals or Array.deepEquals to do the comparison:
System.out.println(Arrays.equals(a, b) ? "Same" : "Different");
* Since your code uses string literals, s and s2 would refer to the same object instance. However, this is not critical to understanding the issue at hand, because interning is not applicable to arrays.
When you say
int[] a={1,2,3};
int[] b={1,2,3};
a is pointing to an array, b is pointing to another array. Both the arrays are not same in the memory. That is, they both are pointing to different memory locations.Like :
a------------->|mem_loc_1|
b------------->|mem_loc_2|
Hence, equals() method tells you that both references are NOT pointing to same object.
Whereas when you say c= a;, the situation is :
a -------------> |mem_loc_1| <---------------- c
Hence equals() tells you that YES, a and c references reference to same objects.
Conclusion, when you say c = a; there are TWO references, but a single object in the memory.
P.S. Sorry for the bad graphical representation,just wanted to simplify things.
because it doesn't do deep equals and does just shallow equals, Use Arrays.deepEquals(); to get expected output
Before understanding above concept you need to note few things :
equals() method is defined in Object class, and any class can
override it.
By default equals() method use memory address of objects to compare them.
So, if you do not overriding it then it will call Object's method.
String class has overridden version of equals() method.
Now come on your program :
In first print statement you are comparing two different object which has not overridden equals() method, so it use Object's method and obviously it check memory address which is different.
In second print statement two reference variable refer same object so its address are same and equals() method return true.
In other print statements for string, which has overridden equals() method, so it will check only actual (here string value) content of object it doesn't matter two String reference variable referring same object or different.
Is it possible to compare 2 object from 2 different classes.
lets say i have an vector which adds all the objects from class A. i want to compare some string to the elements of the vector.
Example:
if(string.equals(vector.get(i)))
is this possible ?
Yes, you can call equals(). However, any reasonable implementation of SomeClass.equals() would return false if the argument is of a different class (other than perhaps a subclass).
If string is an instance of java.lang.String, this behaviour is specifically guaranteed:
The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
Your objects are at least in the class Object, and thus (at least partly) in the same class.
Equals method of an object can take any other object. However, it would be up to the implementation to not return true when comparing an apple with an orange
If the list's elements have type other than String it will always return false. From the String documentation for method equals:
Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
This is generally true for the method equals - it will or should return true only in the eventuality that the compared object is of the same class or a subclass of the former.
It's perfectly valid to write something like;
public class MyClass {
public boolean equals(Object o) {
if(o instanceof SomeUnrelatedClass) return true;
return false;
}
}
But it is not advisable, as least I would try to avoid it. It would make handling MyClass objects a little strange, for example putting them into a hash-based collection.
I am creating the method .equals(Die aDie) in my program. Do I compare every instance variable including static ones?
boolean equals(Die aDie)
is wrong, classes will call the equals(Object) method and ignore your equals(Die). Also implement the int hashCode() method using the same fields that equals(Object) uses.
#Override public boolean equals(Object aDie){
if(aDie == null || aDie.getClass() != Die.class)return false;
if(aDie == this)return true;
Die other = (Die)aDie;
...
}
#Override public int hashCode(){
...
}
You can ignore static fields since they are the same for every Die.
Static variables, by definition, are not instance variables, and will therefore always be equal across all instances of the same class.
Definitely not the static ones.
Whether you compare all the instance variables depends on what determines the "identity" of your objects, i.e. when do you consider them equal? This can only be decided in the context of your particular application - we'd need more information.
For example, if you had a class representing books, you might only compare the ISBN number to determine whether two books are the same book, if you just wanted to store metadata about them (title, author). If you merged two such databases, you'd want to eliminate duplicate records.
BUT, if you were implementing a library catalogue of actual physical books, each individual copy is important and different, so you might compare ISBN and copy number. If you merged two libraries, you'd expect to be able to detect duplicate copies.
You would compare every instance variable.
Static variables are guaranteed to be equal, as they are class-specific, not instance-specific, so you don't have to worry about comparing them.
It would make no sense, both because with equals() you compare instances and because, well, they are static: what would you compare them to, themselves?
It is useless to compare static data, as it is shared among all instances of your Die class. But you can compare the various fields by accessing them directly (see example below). Note that if your Die object has complex fields (such as instances of Map, Set, etc), you should also call the equals methods on those objects (again, see example below).
If you want to provide an equals () method, you should override the one provided in the Object class (equals (Object anOtherObject), rather than overloading it, or at least make sure you also override equals (Object anOtherObject) to make sure that it returns the correct value too (the default implementation only checks if it's the same instance). And in your method you should then check if anOtherObject is an instance of Die.
Here's an example, assuming that your Die class has 3 fields: String name, int value and Map<Integer> complexField:
public boolean equals (Object anOtherObject) {
if (anOtherObject == this) {
return true;
}
if (!anOtherObject instanceof Die) {
return false;
}
Die otherDie = (Die) anOtherObject;
if (this.value != otherDie.value ||
!this.name.equals (otherDie.name) ||
!this.complexField.equals (otherDie.complexField)) {
return false;
}
return true;
}
Josh Bloch's "Effective Java" has a very details section on how to correctly implement equals. You should definitely read it.
When a variable is declared with the keyword “static”, its called a “class variable”. All instances share the same copy of the variable (always be equal across all instances of the same class). A class variable can be accessed directly with the class, without the need to create a instance.