Hello I am trying to write a Java comparison which takes the current object called MovieCard and compares it with another MovieCard passed as a parameter. code below
boolean sameName(MovieCard movieCard) {
if(this.MovieCard.equals(movieCard))
return true;
}
error cannot find symbol - variable MovieCard
The check is listed in my class before the MovieCard constructor if this makes any difference. Also I'm in a beginner programming class so we cannot use Comparator and it needs to contain this.
boolean sameName(MovieCard movieCard) {
return this.equals(movieCard);
}
MovieCard is a class, not a variable. And that's what the compiler is telling you.
if(this.MovieCard.equals(movieCard))
↑
You probably have to write only this.
Also note that there exists a path that doesn't return anything, this won't compile.
You should do:
boolean sameName(MovieCard movieCard) {
return this.equals(movieCard);
}
Or
boolean sameName(MovieCard movieCard) {
if(this.equals(movieCard)) {
return true;
}
return false;
}
use like
boolean sameName(MovieCard movieCard) {
if(this.equals(movieCard))
return true;
}
But it seems your method is checking whether two object has same name. if so then you can simply use
boolean sameName(MovieCard movieCard) {
if(this.name.equals(movieCard.name))
return true;
}
assuming name is a member variable(string)
If this method is present in your MovieCard class, then just this would suffice.
boolean sameName(MovieCard movieCard) {
if(this.equals(movieCard)) {// this is enough. this.MovieCard is wrong, as there is no variable by that name.
return true;
}
return false; // Since return true is a conditional return, but the method needs to return in any case.
}
And a shortened version of your method would be
boolean sameName(MovieCard movieCard) {
return this.equals(movieCard); // Returns the result of the comparison.
}
If looking at the method name, sameName(), it looks like you want to compare some name field in the class, instead of the objects as such.
boolean sameName(MovieCard movieCard) {
return this.getName().equals(movieCard.getName()); // Returns the result of the name comparison.
// But there is a possible NPE in the above statement.
}
You have to write
boolean sameName(MovieCard movieCard) {
if (this.equals(movieCard)){
return true;
} else{
return false;
}
}
Because this.MovieCard points to a variable in your Moviecard class.
Besides your syntax error, Your equals implementation does nothing other that default implementation
Remember if (this.equals(movieCard)){ This is only true when the movieCard and this points to the same reference.
Because,
Default implementation of equals() class provided by java.lang.Object compares memory location and only return true if two reference variable are pointing to same memory location i.e. essentially they are same object.
I guess you need to override the equals method in your MovieCard class, Such that comparing the fields of MovieCard's are same or not.
Prefers to read, How to essentially Ovveride equals.
You are moving in a wrong direction, Please see the example in the above link and then implement equals
in such a way that If all the fields in MovieCard equals to the passed Object's fields. That would be the implementation you asked for.
In general an example for comparing two Tiger Object's for equals like this
#Override
public boolean equals(Object object) {
boolean result = false;
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
Tiger tiger = (Tiger) object;
if (this.color == tiger.getColor() //checking color and pattern same
&& this.stripePattern == tiger.getStripePattern()) {
result = true;
}
}
return result;
}
all the answers given above answers your question so i would like to add this too.
keep in mind that the equals method called belongs to the object method. so it would be wise for you to override the equals method to fit the needs of your program. and when you override equals make sure you override the hashcode method too..
Related
I have been reading a book called Thinking in Java on Java(I come from C background). I came across the following two set of codes
public class EqualsMethod {
public static void main(String[] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1.equals(n2));
}
}
//Output: true
I understand that this equal method is comparing the reference. But n1 and n2 are two object residing in ´two different "bubble" in the heap. So how come they are equal?
Another example code is
class Value {
int i;
}
public class EqualsMethod2 {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals(v2));
}
} /* Output:false
}
Why does this give false? Your in depth answer would be much anticipated. Thank you.
The behavior of equals in your custom classes is entirely up to you. If you override it, you decide when two objects of your class are considered equal to each other. If you don't override it, you get the default implementation of Object class, which checks if both references refer to the same object (i.e. checks if v1==v2 in your example, which is false).
Root of the issue :
You have not overrriden eqauals and hashCode and then JVM assigns a new hashCode to any object you create in the case of Value class
=================
Solution :
You will need to define the criteria on which the identities of the value object is measured i.e do the following
1) Override the equals method and specify that the equality is checked over the value of the instance variable i
2) Override Hashcode and use instance variable i for the hashCode comparison
== is used in the equals method in the object class to avoid unnecessary calculation if the two refrences point to the same object and if not go ahead with the calculation and comparisons
public boolean equals(Object anObject)
{
if (this == anObject) {
return true;
}
else{
// Do the calculation here to check the identity check
}
I understand that this equal method is comparing the reference.
Wrong. In the Object class, this method contains a referential comparison, but Integer has it's own implementation, which overrides the one provided by Object.
It compares the values of the two Integers, not their references.
Integer is valuable type. So comparing to Integer variables performing by comparing their values. Which are equal in your particular case.
Comparing two objects (reference type) performing by comparing the references, which are not equal.
You could write your own comparison logic by overloading the equals() method in your class.
Integer has the method equals() that compare the value, and your Value class doesn't. It makes the Value class with equals compare the "pointer", and they're different.
If you override the method equals in your class Value comparing the attribute i from the class, it would return true.
For example
public boolean equals(Object o){
return (this.i == ((Value) o).i) ? true : false;
}
Equals method in all Wrapper classes is overridden by default in java. That's is why first snippet works.
For your own classes, you have to provide an implementation of equals method.
By default the equal method in Java check if the two Object references are the same. You can #Override the method, and do what you want. So it is normal that you get False, because the two Object are different.
So how come they are equal?
Integer is an Object. On the other side int is a simple type.
Integer's equals() method compare int inside, because it's overriding Object equals() method. int's there has the same value.
Why does this give false?
Your Value class doesn't override equal's method, so then refferences are compared, exactly like when you write v1 == v2. In this case they are different Objects so it's false.
Because you have not override equals method. If you do not override it then it will check if the reference are equal or not and return accordingly.
You can refer equals() method defined in Integer class.
System.out.println(n1.equals(n2)) // this prints true because it refers to Integer equals method.
Similarly you will have to override it for your Value class like.
class Value {
int i;
#Override
public boolean equals(Object obj) {
boolean returnValue = false;
if (obj != null && obj instanceof Value) {
Value valObj = (Value) obj;
if (this.i == valObj.i) {
returnValue = true;
}
}
return returnValue;
}
}
Now System.out.println(v1.equals(v2)); prints true.
Hi your understanding of equals and == is completely wrong or opposite to what it actually is.
equals() method also checks for reference as == does, there is no difference between both of them unless you override the equals method.
== check for reference equality. For better understanding see Object class source code.
public boolean equals(Object obj) {
return (this == obj);
}
Why is it working in your case? is because Integer class overrides the equals method in it.
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
n
}
Now when you use your custom class to check equality what it is doing is basically calling.
v1==v2
How it can give you true? They both have different memory locations in heap.
If still things are not clear put break points in your code and run it in debug mode.
This question already has answers here:
When overriding equals in Java, why does it not work to use a parameter other than Object?
(7 answers)
Closed 9 years ago.
I have a superclass Order which has a subclass OrderBook. The equals(...) method is overridden in the OrderBook. The method implementation is as follows:-
public boolean equals(Order o)
{
if(o==null){
System.out.println("object is null.");
return false;
}
if(o==this){
System.out.println("The object is itself.");
return true;
}
if(o instanceof OrderBook)
{
OrderBook o1 = (OrderBook)o;
if(!(o1.productId.equals(productId))){
System.out.println("productId mismatch.");
return false;
}
if(!(o1.customerId.equals(customerId))){
System.out.println("customerId mismatch.");
return false;
}
if(o1.book!=book){
System.out.println("book mismatch.");
return false;
}
}
return true;
}
I am encountering an unexpected output if I give the following statement:-
Order order1 = new OrderBook("Algorithms","Kunal",false);
Order order2 = new OrderBook("Algorithms","Kunal",false);
System.out.println(order1.equals(order2));
It should display true but its displaying false. Also, if I change the parameter in the equals(...) to Object o, then the whole program runs without any problem.
My doubt is that why are we using Object when we should be using Order?
public boolean equals(Order o)
Should be
public boolean equals(Object o)
Explanation
This is because you're attempting to override a method. When you override a method, you need to match the signature exactly. The signature is made up of:
The name of the method
The type of the arguments
The number of arguments
The return type.
The type of the argument in the original method signature was Object, yet you've provided an object of type Order. Hence, the runtime will treat these are two distinct methods.
try putting this instead of your block in the books comparing part
if(!o1.book.equals(book)){
System.out.println("book mismatch.");
return false;
}
And change the signature it should be equals(Object o)
Also do not forget the #Override annotation
To override a method in Java, you must match its signature exactly. The signature of Object#equals is:
public boolean equals(Object o)
a fairly standard approach is to overriding equals is:
public boolean equals(Object o) {
if (obj == null)
return false;
if (obj == this)
return true;
if (!(obj instanceof Order))
return false;
// specific comparisons for your Order object
}
Everyone did a good job explaning how to make it work. I want to explain why your's didnt work: (pay close attention to the type of parameter in equals())
Object class has equals(Object ojb). When JVM encounters the statement "order1.equals(order2)" it says to itself: Hmmmm ... order is of type Order and references OrderBook. I need to use the overriden equals() method if OrderBook has one. Dang!! OrderBook doesnt have equals(Object) instead it has equals(Order). So Im going to use equals(Object) from Object class.
What you have is called OVERLOADING. not overriding.
I'm using an ArrayList, and at one point in the program I'm using the contains method to check if a certain item is contained in the ArrayList. The ArrayList holds objects of type CharProfile, a custom class, and it's seeing if a char is contained within it.
So it's using the equals method in the contains method, I assume. So something like CharProfile.contains(char), but it's not working.
I overrode the equals method in CharProfile:
#Override
public boolean equals(Object o) {
if (this.character == (Character)o) {
return true;
}
else {
return false;
}
}
So it should be using my equals method when CharProfile is trying to use it, right? So why won't it work?
(In terms of "not working" I'm referring to the fact that contains always returns false.)
You are comparing a reference type using ==, which is wrong. You must use equals, with proper null-checks added.
But this is just the beginning. Your main problem is that you are trying to compare a CharProfile object to a Character object. You probably need this instead:
public boolean equals(Object o) {
return o instanceof CharProfile
&& this.character.equals((CharProfile)o).character;
}
This assumes that your character field is never null. If it can be null, you need to check that before dereferencing it, as well.
You are overriding equals such that it test for equality of reference, the default behavior of the operator ==
You need to use equals(). You can also make it a oneliner and be more explicit in your cast.
#Override
public boolean equals(Object o) {
return o instanceof Character && this.character.equals(Character.class.cast(o));
}
You have to use the equals() method and DO NOT forget to override the hashCode() method as well. They go hand in hand.
Some people don't know this, but if using eclipse you can right click choose Source-> and Generate hashCode() and equals()...
But, I suggest that you learn what they're for first before using this convenience.
For example, You have CharProfile as below.
List<CharProfile> list = new ArrayList<CharProfile>();
list.add(new CharProfile('a'));
list.add(new CharProfile('b'));
list.add(new CharProfile('c'));
When list.contains('a') is does, the JVM will not call Override equals() method of CharProfile.
For more clear;
public class Data {
public boolean equals(Object o) {
System.out.println("I am data");
return false;
}
}
When list.contains(new Data()) is does, the JVM will not call Override equals() method of Data.
Now, You will get message like I am data..
-- Yes, this is a question asking for help regarding something that was assigned as homework. No, this is not me asking you to do my homework for me. The deadline was a half an hour ago; I literally can't change my submission. You'll just have to take my word for it. Moving on...
I know that testing for the type of objects is supposed to be unnecessary. When I was looking for details about 'instanceof', I found a half dozen threads where people responded only to tell the original poster that they were making a mistake if they had to test to find out what kind of object they were dealing with before processing it. Yes, I know, I would love to follow the conventions. Unfortunately, my professor asked for us to override the equals method of a class we defined, and specifically required an Object type parameter. If you see my code, you'll probably understand better:
public boolean equals(Course other){
if(!(other instanceof Course)){
return false;
} else if(other.name==this.name && other.days==this.days &&
other.start==this.start && other.end==this.end){
return true;
}
return false;
}
You can probably understand where I'm going with this. The 'other' parameter should be an Object type, but the program has a fit if I leave it as an Object and use the name / days / start / end fields. If I change it to Course, of course it works (no pun intended), but that would be a completely different method. The desired behavior is for all objects other than Course instances to make the method return false, and additionally, for mismatched data between Course instances to make it return false.
I'm sorry to all of you who know Java well enough to be frustrated by seeing questions like these.
If you want to override the "equals" method, you should use Object as a parameter, and thus you have to check for the object's type. Usually your own implementation would look like this:
#Override
public boolean equals(Object obj) {
if (obj == this)
return true; // object's references are identical
else if (!(obj instanceof Course))
return false;
Course that = (Course) obj;
return (this.name.equals(that.name)) && (this.days == that.days)
&& (this.start.equals(that.start)) && (this.end.equals(that.end));
}
Of course you should override "hashCode" as well, using the same significant fields.
Instead, you overloaded the method with your own parameter of type Course. So if you call myobject.equals(anotherObject) and anotherObject is not of type Course, your "equals" method will never be called, instead the Object#equals method will be called, which does only the following: return this == obj.
The reason why overloading the "equals" method is not enough is the necessity to overload "hashCode" as well, which takes no parameters and thus cannot be overloaded.
If you write your own implementation of boolean equals(Object), you must also implement int hashCode()
Both methods should use the same significant fields for "hashCode" and "equals".
If a.equals(b) == true than the following must be also true: a.hashCode() == b.hashCode()
Also if a.hashCode() != b.hashCode() then a.equals(b) == false
The last point is the main reason why you should not just overload "equals" with your own type:
Course c1 = new Course("myname");
Course c2 = new Course("myname");
c1.equals(c2); // true
c1.hashCode() == c2.hashCode(); // false
You can cast Object as Course:
Course course = (Course)object;
Then do all the comparisons on the course object. Obviously, still do the instanceof check before casting to avoid a ClassCastException.
You're trying to cast it:
Cource c = (Course)other;
Your code :
public boolean equals(Course other){
if(!(other instanceof Course)){ <-- other can only be Course here
return false;
} else if(other.name==this.name && other.days==this.days &&
other.start==this.start && other.end==this.end){
return true;
}
return false;
}
Correct code :
public boolean equals(Object other){
if(!(other instanceof Course)){
return false;
} else{
Course c = (Course) other;
if(c.name==this.name && c.days==this.days &&
c.start==this.start && c.end==this.end){
return true;
}
}
}
return false;
}
Here, I'll just post my code:
int len = InternalList.size();
ListIterator<E> forward = InternalList.listIterator( 0 );
ListIterator<E> backward = InternalList.listIterator( len );
while( forward.hasNext() && backward.hasPrevious() )
{
E next = forward.next();
E prev = backward.previous();
// When the object references are the same, we expect to be at the
// center of the list (for odd-numbered lists?); we're done
if( next == prev )
return true;
// Otherwise, if the object values aren't the same, we're not a
// palindrome
if( !((E)next).equals( prev ) )
return false;
}
And here's the internal list:
private LinkedList<E> InternalList;
So basically my problem is the last if statement only checks Object's equals() method; not the E's equals(). If forcibly casting it doesn't work, what does?
The runtime types of the elements returned from the iterators are not (and indeed cannot be) changed. They're assigned to fields of type E, which may well be erased to Object at runtime (depending on the generic bounds) but this won't affect the objects themselves.
When equals() is invoked, it's a non-static method and so is invoked on whatever the class of the next object happens to be. If this class doesn't have an overridden equals method then sure, the default Object.equals will be used. However, if this object's class directly or indirectly overrides equals, the most specific override will be used.
In other words, this code should be fine (and the cast is completely unnecessary).
I suggest that you double-check you've overridden equals correctly in the class in question. I would guess that you've implemented it as something like:
public class MyFoo {
...
public boolean equals(MyFoo other) {
...
}
}
whereas the argument must be of type Object, otherwise you're just overloading the equals method instead of overriding it. If you're using Java 6, you can add the #Override annotation to your method, which will catch this sort of error.
The correct implementation of equals(Object) will be chosen at runtime, due to runtime polymorphism. Why do you think that's not the case?
Actually, you might have made a common mistake and implemented equals(ASpecificType) instead of equals(Object): you want to override the equals(Object) method from java.lang.Object. Specifying a different parameter type means you no longer override that method.
A common equals() implementation for ASpecificType could start like this:
public boolean equals(Object o) {
if (this==o) {
return true;
} else if (o==null || o.getClass() != getClass()) {
return false;
}
ASpecificType other = (ASpecificType) other;
// insert specific comparison here
return result;
}
The casting casts E to E so it doesn't do anything.
equals should work without casting.
As you posted in the comment, next == prev will not work for even-numbered lists.
Concerning how to implement equals:
public boolean equals(Object o) {
if(this == o) { return true; }
if(o == null) { return false; }
if(o instanceof [ClassOfThis]) {
o = (Type)o;
// compare here.
} else {
return false;
}
}