Here is my application
public class testwithmain {
public static void main(String[]args)
{
Money m12CHF = new Money(12,"CHF");
System.out.println(m12CHF.amount());
Money m14CHF = new Money(14,"CHF");
System.out.println(m14CHF.amount());
Money expected = new Money(26,"CHF");
System.out.println("expected "+expected.amount()+expected.currency());
Money result = m12CHF.add(m14CHF);
System.out.println("result "+result.amount()+result.currency());
System.out.println(expected.equals(result));
}
}
//-------------------------
public class Money {
private int fAmount;
private String fCurrency;
public Money(int amount, String currency) {
fAmount = amount;
fCurrency = currency;
}
public int amount() {return fAmount;}
public String currency() {return fCurrency;}
public Money add(Money m) {
return new Money(amount() + m.amount(), currency());
}
}
The result is:
12
14
expected 26CHF
result 26CHF
false
Please, why i have false ?
Thank you so much.
Your Money class lacks an implementation of equals method, which is required in order for Java to know that the object representing the result of m12CHF.add(m14CHF) and the new Money(26,"CHF") represent the same thing, even though the two are distinct Java objects.
The code inside equals should follow this general template:
#Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Money)) {
return false;
}
Money other = (Money) o;
... // Your code goes here
}
#Override
public int hashCode() {
return Objects.hash(fAmount, fCurrency);
}
Your implementation needs to compare fAmount and fCurrency of your object to the values in other.fAmount and other.fCurrency. Use equals for comparison of String objects; numbers can be compared with == operators.
As Nexevis said you need to override the equals method (which is inherited from the object class)
#Override
public boolean equals(Object obj){
if(obj instanceof Money){
Money other = (Money)obj;
//now you define when two intance object of Money are equal...
}
//...
}
Why is this necessary?
Because the current equals that you are using it is the equals from the Object class. Object's equals method defines that two objects are the same when they have the same reference
Related
In this exercise, I need to create a equals() method for a Drink class. Two drinks are the same if they have the same name and same size. I am receiving false from testing the method, even though I'm certain it should be true.
The main code:
public class Drink {
private String name;
private double size;
public Drink(String name, double size)
{
this.name = name;
this.size = size;
}
public String getName()
{
return name;
}
public double getSize()
{
return size;
}
//I tried to stringify the double values
public boolean equals(Drink a, Drink b){
String q = String.valueOf(a.getSize());
String w = String.valueOf(b.getSize());
if(q.equals(w) && a.getName().equals(b.getName())){
return true;
}
else{
return false;
}
}
}
The tester Code:
public class DrinkTester
{
public static void main(String[] args)
{
Drink one = new Drink("Soda", 12);
Drink two = new Drink("Soda", 12);
Drink three = new Drink("Soda", 20);
System.out.println(one.equals(two));
System.out.println(one.equals(three));
}
}
You need to override the equals method, if you use the
#Override annotation you'll see if you're doing it right.
public boolean equals(Object obj) {
return (this == obj);
}
That is the Object one, so yours might for example look like:
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Drink drink = (Drink) obj;
return this.size.equals(drink.size)
&& this.name.equals(drink.name);
}
you'll also have to override your hashCode if you want your code to work optimally.
(And i've only recently noticed that if you use Objects.hash in your overridden hashCode method, your overridden equals method won't get used, the Objects one will get used instead)
I created an abstract class Fruit, which overrides the equals() method. Then I created a subclass, Orange, which overrides the copy() and the equals() method. In my test file, TestFruit.java, I am creating an array of oranges and testing their methods. I am trying to create a deep copy of orange and do a deep comparison between the parent orange and the copy. However, in my output, the comparison always returns false. I checked the parent and the copy's attributes and they do seem to be the same. Any pointers would be appreciated. I am pretty new to Java and copying. I attached my code below.
Fruit.java:
package juicer;
import copy.Copyable;
public abstract class Fruit implements Copyable, Cloneable
{
private double mass;
private boolean isJuicedRemoved;
protected Fruit(double theMass)
throws IllegalMassException
{
{
if (theMass <= 0)
{
throw new IllegalMassException(theMass);
}
else
{
this.mass = theMass;
this.isJuicedRemoved = false;
}
}
}
protected Fruit(Fruit fruit)
{
this.mass = fruit.mass;
this.isJuicedRemoved = fruit.isJuicedRemoved;
}
public double getMass()
{
return mass;
}
public boolean getIsJuicedExtracted()
{
return isJuicedRemoved;
}
protected void setMass(double value)
{
this.mass = value;
}
protected abstract double juiceRatio();
public double extractJuice()
{
double liquidMass = amountJuice();
if (!isJuicedRemoved)
{
isJuicedRemoved = true;
mass -= liquidMass;
}
return liquidMass;
}
public double amountJuice()
{
if (isJuicedRemoved) return 0.0;
return mass * juiceRatio();
}
#Override
public boolean equals(Object obj)
{
// Steps to override the equals() method():
// Step 1: Test if obj is an instance of Fruit.
// If it is not, then return false.
if (!(obj instanceof Fruit)) return false;
// Step 2: Cast obj to an Fruit.
Fruit rhs = (Fruit)obj;
// Step 3: Test if the data fields of the invoking object are
// equal to the ones in rhs using a deep comparison
// and return this result.
return super.equals(obj) && // test for equality in the super class
mass == rhs.mass &&
isJuicedRemoved == rhs.isJuicedRemoved;
}
#Override
public int hashCode()
{
int result = super.hashCode();
result = 31*result + Double.hashCode(mass);
result = 31*result + Boolean.hashCode(isJuicedRemoved);
return result;
}
#Override
public Object clone() throws CloneNotSupportedException
{
Fruit objectClone = (Fruit)super.clone();
objectClone.mass = mass;
objectClone.isJuicedRemoved = isJuicedRemoved;
return objectClone;
}
#Override
public String toString()
{
return "\tmass = " + mass +
"\n\tisJuiceExtracted = " + isJuicedRemoved + "\n";
}
}
Orange.java:
package juicer;
public class Orange extends Fruit
{
public Orange(double mass)
{
super(mass);
}
// copy constructor
public Orange(Orange other)
{
super(other);
}
#Override
protected double juiceRatio()
{
return 0.87;
}
#Override
public boolean equals(Object obj)
{
// Steps to override the equals() method():
// Step 1: Test if obj is an instance of Orange.
// If it is not, then return false.
if (!(obj instanceof Orange)) return false;
// Step 2: Cast obj to an Orange.
// This step is not needed since the only data fields this
// class has are the ones it inherits.
// Step 3: Test if the data fields of the invoking object are
// equal to the ones in rhs using a deep comparison
// and return this result.
return super.equals(obj);
}
#Override
public Object copy()
{
return new Orange(this);
}
#Override
public String toString()
{
return "Orange:\n" + super.toString();
}
}
TestFruit.java:
package test;
import juicer.*;
import java.util.Random;
public class TestFruit
{
public static void main(String[] args)
{
Orange[] oranges = new Orange[1];
//Random double generator for mass
Random rd = new Random();
//create oranges
for (int i = 0; i <= oranges.length - 1; i++ )
{
oranges[i] = new Orange(rd.nextDouble());
}
for (Orange orange : oranges)
{
Orange orangeCopy = new Orange(orange);
if (orange == orangeCopy)
{
System.out.print("The comparison is true!");
}
else
{
System.out.print("Does not match.");
}
}
}
}
One of the common misconceptions in Java is the use of == vs .equals(). When you use == to compare two objects in Java, internally it's comparing its memory address. == does not actually call .equals().
In this case, you have two distinct orange objects, so the comparison will always return false.
If you use a.equals(b), then it will actually invoke your equals method which you implemented.
As #Andreas pointed out in the comments, there's another issue. Calling super.equals(obj) in Fruit will call the superclass implementation of equals, and the superclass of Fruit is Object. Object.equals() behaves the same as == (i.e. also checking for reference equality). Overriding .equals() is not trivial, so it can often be nice to have the IDE generate it for you.
In contrast with a language like C++, Java does not have operator overloading. This means that you can't define a different implementation for ==. This is why it's best practice to always call .equals() when comparing any non-primitive types (unless you're explicitly checking reference equality, which is rare).
I'm working on a homework assignment, and I'm having a really hard time wrapping my head around how to compare two of the same subclass objects.
Basically I have this superclass Magnitude:
class Magnitude {
public boolean lessThan(Magnitude m) {
}
public boolean lessThanEqualTo(Magnitude m) {
}
public boolean equalTo(Magnitude m) {
}
public boolean greaterThan(Magnitude m) {
}
public boolean notEqual(Magnitude m) {
}
}
And then I have a subclass Currency that extends Magnitude ( I am only allowed to override the lessThan() method):
class Currency extends Magnitude {
double amount;
public Currency(double amt) {
this.amount = amt;
}
#Override
public boolean lessThan(Magnitude m) {
Currency other_currency = (Currency) m;
if (this.amount < other_currency.amount) {
return true;
}
else {
return false
}
}
public void print() {
System.out.println(amount);
}
}
What exactly is the way that I should implement these methods for the super and subclass so that I can compare 2 objects of the same subclass?
You can make use of the fact that you can call lessThan() also from m and use this as the other argument.
abstract class Magnitude {
public abstract boolean lessThan(Magnitude m);
public boolean lessThanEqualTo(Magnitude m) {
return this.lessThan(m) || this.equalTo(m);
}
public boolean equalTo(Magnitude m) {
return ((!this.lessThan(m))&&(!m.lessThan(this)));
}
public boolean greaterThan(Magnitude m) {
return m.lessThen(this);
}
public boolean notEqual(Magnitude m) {
return !this.equal(m);
}
}
You then need to have
class Currency extends Magnitude {
double amount;
public Currency(double amt) {
this.amount = amt;
}
#Override
public boolean lessThan(Magnitude m) {
Currency other_currency = (Currency) m;
if (this.amount < other_currency.amount) {
return true;
}
else {
return false
}
}
public void print() {
System.out.println(amount);
}
}
Simply rewrite the methods at the subclass.
Now, if you create two instances of the subclass and compare them, it'll use the subclass method
Currency c1 = new Currency();
Currency c2 = new Currency();
c1.lessThan(c2); //will call Currency.lessThan method
To use parent's class method, use this way
c1.lessThan((Magnitude) c2);
See this form more info.
If I understand your question correctly, you want to know how to implement and override the lessThan() method in your Currency class, knowing you can only compare currencies but not magnitudes, but what you receive is a Magnitude type parameter.
In that case, you need to check if the Magnitude object you received as a paramether is actually an instance of Currency wrapped in a Magnitude class. To do that, you use the instanceof comparison operator and then cast the object to Currency:
#Override
public boolean lessThan(Magnitude m) {
if(m instanceof Currency) {
return this.amount < ((Currency)m).amount;
} else {
throw new IllegalArgumentException("Parameter is not a Currency");
}
}
If I run the below code then the output is 2 which means that the set contains 2 elements. However I think that set should contain 1 since both the objects are equal based on hashcode() value as well as .equals() method.
Seems like some obvious mistake in my understanding ?
package HELLO;
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) throws Exception {
Set<Alpha> s = new HashSet<Alpha>();
Alpha a1 = new Alpha();
Alpha a2 = new Alpha();
s.add(a1);
s.add(a2);
System.out.println(s.size());
}
}
class Alpha {
int a = 10;
public int hashcode() {
return a;
}
public boolean equals(Object obj) {
return (obj instanceof Alpha && ((Alpha) obj).a == this.a);
}
public String toString() {
return "Alpha : " + a;
}
}
Your hashcode method does not override the Object class's hashCode method and thus your equals method breaks contract since it doesn't agree with the hashCode results, and you can have objects that are "equal" but have different hashCodes.
Remember: You should always use the #Override annotation when overriding methods as this will help you catch this and similar errors.
#Override // ** don't forget this annotation
public int hashCode() { // *** note capitalization of the "C"
return a;
}
Also, you will want to improve your code formatting, especially when posting code here for our review. We will be able to better understand your code and help you if it conforms to standards (that's why standards exist). So try to keep your indentations consistent with all code lines that are in the same block indented at the same level, and you will want to be sure that base level code, including imports, outer class declarations and its end curly brace, is flush left:
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) throws Exception {
Set<Alpha> s = new HashSet<Alpha>();
Alpha a1 = new Alpha();
Alpha a2 = new Alpha();
s.add(a1);
s.add(a2);
System.out.println(s.size());
}
}
class Alpha {
int a = 10;
#Override
public int hashCode() {
return a;
}
public String toString() {
return "Alpha : " + a;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Alpha other = (Alpha) obj;
if (a != other.a)
return false;
return true;
}
}
For a beautiful review on this, please read: Overriding equals and hashCode in Java
The #Overrides annotation is to override the method with the same name in the super class".
#Override
public int hashCode() {
return a;
}
#Override
public boolean equals(Object obj) {
return (obj instanceof Alpha && ((Alpha) obj).a == this.a);
}
#Override
public String toString() {
return "Alpha : " + a;
}
your method hashcode should be named hashCode (capital letter "C").
If you plan on overriding methods you should use the #Override annotation.
If you had used that annotation, you'd have noticed the problem earlier as the code wouldn't have compiled.
How should I implement hashCode() and equals() for the following class in Java?
class Emp
{
int empid ; // unique across all the departments
String name;
String dept_name ;
String code ; // unique for the department
}
in Eclipse right mouse click-> source -> generate hashCode() and equals() gives this:
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (code == null ? 0 : code.hashCode());
return result;
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Emp))
return false;
Emp other = (Emp) obj;
return code == null ? other.code == null : code.equals(other.code);
}
I've selected code as a unique field
try this code, use org.apache.commons.lang3.builder
public int hashCode() {
return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
append(empid).
append(name).
append(dept_name ).
append(code ).
toHashCode();
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof Person))
return false;
Emp rhs = (Emp) obj;
return new EqualsBuilder().
// if deriving: appendSuper(super.equals(obj)).
append(name, rhs.name).
isEquals();
}
Guava has helper methods for creating them. You tell it which fields to take in consideration and it will handle nulls for you and do the prime number calculation for hashcode.
IDEs can also generate them based on the fields you choose.
The advantage of delegating it to a tool like that is you get a standard solution and will worry less about bugs and maintenance of varied implementations spread all over your project.
Here's an example of using Guava and generated by an IntelliJ plugin: https://plugins.jetbrains.com/plugin/7244?pr=
If code is unique (i.e. your business key), it's best to only use the code for equals and hashCode - it's good practice to seperate business key (code) from object id (id).
Here's a nice read: Hibernate Documentation: Equals and HashCode (valid not only for Hibernate itself)
what ever values you use in equals to determine if two objects are the same, are the the values that you need to use to create a hash code.
public boolean equals(Object o) {
boolean result = false;
if(o instanceof CategoryEnum) {
CategoryEnum ce = (CategoryEnum) o;
result = ce.toString().equals(name);
}
return result;
}
public int hashCode()
{
int hash = 6;
hash += 32 * name.hashCode();
return hash;
}
equals()and hashcode(),They have a lot of different places.
equals(),if we don't Override it from Object,it represent that whether two variables are pointing to the same object heap?
public Class Student(){
private int id;
private name;
public Student(int id,String name){
this.name=name;
this.id=id;
}
public void main(String[] args){
Student A=new Student(20,'Lily');
Student B=new Student(20,'Lily');
boolean flag=A.equals(B)//flag=flase;
/*
*Although they attribute the same, but they are two different objects, they point to different memory
*/
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (this.getClass() != obj.getClass()) {
return false;
}
Student s=(Student)obj;
return new Integer(this.id).equals(new Integer(s.id))&&this.name.equals(s.name);
}
/**
*Sometimes even though we Override the equals, but we still can not determine whether the *two objects the same,
*In the collection object, such as HashSet, this time we have to Override the hashoCode ()
*/
public int hashCode(){
return id + name.hashCode() ;
}