Implementing .equals(Die aDie) method and static variables - java

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.

Related

Could someone explain me the .getClass() method in java

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(){
}
}

Java reflection check if passed Objects are same type

I have a class with compare method. The method takes two objects as arguments.
With java reflection I was able to get all the private and protected field and with some fancy stuff check their return types and do what I want to do with them.
This is good for me personaly. I know what I want to do so I just compare two objects of same type and thats all.
BUT ... this is used by many people ...and they sometimes are unable to read a Javadocs and comments and other stuff I put there so I have to check if they are passing object of same type. For example you have :
Car a, Car b , Truck a, Truck b ... and so on..
I need to check if the two passed arguments are actually the same type for comparing (Car with car , Truck with truck..)
So ... I dont know the stuff.. Should I use the reflection for listing the size of all fields and then check if all the fields have the same name ?
Or is there a better solution ? Becouse writing something like if the fieldsOfA.size is same as fieldOfB.size ... and then for loop for this if they are same to check the names looks kinda weird..
Also another problem.
Those objects have lists of some other object - for example Car has a list of Wheels..
And you are comparing the wheels with other car.
They have like Wheel 1 , Wheel 2 , Wheel 3, Wheel 4 in list..
and the second car has Wheel1, Wheel 2, WHeel 4 and WHeel 3 ..
So the objects are same , but just have switched positions..is there a way to prevent this ? I have a tracking code that stores every difference in those objects.. So if they have different positions it gives me two changes.. Wheel 3 is different from other car and wheel 4 is different on other car..
But they are still the same ...
I don't know how to solve this with reflection ... Any Ideas ?
To compare classes just use if(object1.getClass() == object2.getClass())
To be fair, it's either a.getClass().isInstance(b) or a.getClass().isAssignableFrom(b) but I always forget which one is which.
boolean isInstance(Object obj)
Determines if the specified Object is assignment-compatible with the object represented by this Class.
And
boolean isAssignableFrom(Class<?> cls)
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.
You probably need the first.
You can use the instanceof operator.
For example:
public boolean isCar(Vehicle x) {
if (x instanceOf Car) {
return true;
} else {
return false;
}
// note: you can also just do "return x instanceof Car"
}
This sounds like you're attempting to write a General Purpose Equals Method. Just in case you are: be aware that this will fail in the general case, because object equality does not necessarily mean all fields are equal, or even that all public fields are equal. It is possible for two Java objects to be intentionally equal even if some fields are different. Equality between two instances of a given class is defined by the programmer designing that class, and anyone subclassing it implicitly abides by their equality contract.
Given that, it's generally a bad idea to attempt to dig out an object's superclass' private fields. A much better idea: super.equals().
So, suppose you write a class Truck that extends Vehicle, and Truck defines two private fields, maxLoad and hasTrailerHitch. You define whether two Trucks are equal; suppose you need both these fields to be equal. In reality, you probably also want them to satisfy whatever equality conditions Vehicle defines. So your equals is likely to look something like this:
#Override
public boolean equals(Object obj) {
// check for type
if (!(obj instanceof Truck)) return false;
// check private fields
Truck other = (Truck)obj;
if (this.maxLoad != other.maxLoad ||
this.hasTrailerHitch != other.hasTrailerHitch) return false;
// check for Vehicle equality
if (!super.equals(obj)) return false;
// everything checks out!
return true;
}
I wrote this a bit less compactly than I would in practice, for display purposes. The order of the checks ideally doesn't matter; I put the superclass check last, since I know two private field comparisons runs really fast, but I don't necessarily know what's involved in checking Vehicles.
Notice how the instanceof works. If someone (including you!) writes a subclass of Truck later, the instanceof will be true, and so if they do the same thing you do and call super.equals(obj), your Truck.equals will check those two private fields, as it should. If, instead of an instanceof check, you had been more strict, say:
if (obj.getClass().getName().equals("my.pkg.Truck")) // ...
then subclasses of Truck would not get these private fields checked properly. Two instances of, say, DumpTruck would never be equals - probably not what you intend.

Override equals and cast object to string

EDIT: the question is why cant I use ".contains" (override .equals() in the object) to compare object attributes (a string) instead of comparing the object itself.
Thanks JB:
Turns out I was confusing overriding compareTo() with overriding equals()
EDIT:
QUESTION REDEFINED:
Why cant I override equals to compare strings in my object:
public boolean equals(Object obj){
...
if(obj instanceof String){
String testString = (String) obj;
...
}
...
}
Or even overload for that matter:
public boolean equals(String stringObj){
...
}
I read somewhere that the compiler doesn't use logic to decide this, it uses types. So if I then call myObj.equals(stringOne + "_" + stringTwo) shouldn't this work as it knows a string is being passed?
Thanks,
Steve.
Why this code doesn't make sense:
because Comparable is supposed to respect rules: if a < b is true, then b > a must be true. You can compare an instance of your class with String, but a String can't compare with an instance of your custom class. You're thus breaking the contract of Comparable
because Vector doesn't use compareTo() to check if an element exists or not. It uses equals().
Because you shouldn't alter the nature of a class just to implement a specific use-case consisting in adding instances of this class to a list and check for duplicates. This logic should be outside of the class. You could simply loop through the list and check is an instance with the item and position already exists or not, before creating your custom class instance.
because you shouldn't use Vector for many years (since Java 2 - we're at Java 8). And since it seems the goal is to avoid duplicates, what you should use is a Set.
Do the right thing, and use a HashSet. Make sure CustomClass implements equals() and hashCode() correctly. You could also use a HashMap<CustomClassKey, CustomClass>, where CustomClassKey is a simple class containing the two fields identifying your CustomClass instances.

Check if an object is of the same class as this?

I have a base class for multiple data object types in Java. I want to create an equals method in the base class, that works directly when inherited.
Equality is determined by the two objects
belonging to subclasses of the base class. This is easily achievable using
if (!(anObject instanceof BaseClass))
return false;
having the same ID. The ID field is defined by the base class so we can here test that.
if (this.id != ((BaseClass) anObject).id)
return false;
belonging to the same class. This is where I have the problem. Two objects may be of different types (and so be in different lists), but have the same ID. I have to be able to distinguish them. How can I do this?
Use
this.getClass() == anotherObject.getClass()
instead of instanceof. This will return true only if the two object belong to the same class (it's safe to check if class objects are equal by reference). And after that you may compare the id.
You should read this article for problems when implementing equals.
To make it short: use this.getClass()==other.getClass() instead of instanceof, because otherwise the equals() relationship will not be transitive (superInstance.equals(subInstance) will be true, but subInstance.equals(superInstance) will be false).
If I understand you question correctly, you need a way to differentiate two objects of same Class with same id. If so, for this you may use toString() which gives unique representation of objects unless they are string objects. Of course, you must not have overridden toString() in your base class.
example:You can use this, only for the third case that you mentioned.
if (this.toString()!= anObject.toString())
return false;
You can do that with Class.isInstance() method. In your base class, do this.
public static boolean isAnInstance(Object obj)
{
return BaseClass.class.isInstance(obj);
}
Then you can check
if (BaseClass.isAnInstance(object))
{
// Class of object is 'BaseClass' or
// it extends the 'BaseClass'
}
Hope this helps.
The best practice to know objects equality is to override hashcode() and equals() if you maitain objects in a collection
you can refer Why do we have to override the equals() method in Java?

Is it possible in Java to compare references to instances of class if equals() method is overridden?

I need to compare 2 instances of a class, that has equals method overridden - it returns string that equal concatenation of parameters. But I need be sure that exists only 1 instance. For this I think to check references.
Is it possible in java?
Use == to compare the references. It's enough to make sure if different variables refer to the same instance.
The easy way to ensure that only one instance exists is to use an Enum.
public enum MyEnum {
NameOfSingleton("aPropertyValue");
private String aProperty;
private MyEnum(String aProperty) {
this.aProperty = aProperty
}
public getAProperty() {
return this.aProperty;
}
Using it is just as simple.
MyEnum.NameOfSingleton.getAProperty();
This doesn't really address your equality question, but it addresses your need for a singleton instance of a class.
I'm not entirely sure what you're trying to do, but if you need to ensure that only one instance of something exists then you can use the static keyword to do so. There are multiple ways you could ensure this with static, for instance creating a static variable called count that keeps track of how many instances of the object have been made. Then in the constructor for the object you just increment count. To see if there is more than one instance of the object you just check the count variable and it should tell you.

Categories