Is an compareTo method a self association in UML? - java

I'm currently making an package and class diagram. I have a class that uses the compareTo method. My question is when I model it, do I have to make a self association? If so, is the self association a dependency line or just a normal line?
Example of the code:
public class Example implements Comparable<Example> {
private String name;
public Example(String name) {
this.name = name;
}
public String getNaam() {
return name;
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Example) {
return ((Example) obj).name.equals(name);
} else {
return false;
}
}
#Override
public int hashCode() {
return name.hashCode();
}
#Override
public int compareTo(Example o) {
return name.compareTo(o.getNaam());
}
#Override
public String toString() {
return name;
}
}

Because a class knows itself (which is self-evident) you simply write it this way:
Note: I left out most of the operations.
A self reference is used if you have an attribute which is typed with the class itself. A simple example is Employee which references a manager that is an Employee itself:
To elaborate on this: as you have seen, associations are just another rendering for attributes. If you use a typed parameter which is not represented by an attribute you would create a dependency like in the following picture.

Related

Why this Java Code is compiling successfully

I haven't overridden much of hashCode() and equals() methods so I may be wrong
My question is for the last line where
dep1.equals(emp2) is being compiled successfully(why) (I am expecting compilation error as they have different types) and after compiling I get following
15 15 false
where I am expecting 15 15 true since I am checking the hashcode in the equals method.
class Employee {
private String name;
private int id;
public Employee(String name, int id) {
this.name = name;
this.id = id;
}
public int hashCode() {
return this.id;
}
public boolean equals(Employee employee) {
return this.hashCode() == employee.hashCode();
}
public int getEmployeeId() {
return this.id;
}
}
class Department {
private String name;
private int id;
public Department(String name, int id) {
this.name = name;
this.id = id;
}
public int hashCode() {
return this.id;
}
public boolean equals(Department department) {
return this.hashCode() == department.hashCode();
}
public int getDepartmentId() {
return this.id;
}
}
public class JavaCollections {
public static void main(String args[]) {
Employee emp2 = new Employee("Second Employee", 15);
Department dep1 = new Department("Department One", 15);
System.out.println(dep1.hashCode()+" "+emp2.hashCode()+" " + dep1.equals(emp2));
}
}
First, for the reason why this compiles: all classes in Java inherit from java.lang.Object, which defines equals(Object) method, and provides a default implementation. This is the method that you call when you compare an Employee and a Department, not one of the overloads that you have provided.
Your equals code compiles fine, because the compiler does not know that you thought you were overriding equals when you actually didn't. The compiler thinks that you want to make a new method
public boolean equals(Department department)
to compare Department objects to other Department objects.
If you are writing a code that overrides a method of a superclass, add #Override annotation to it, like this:
#Override
public boolean equals(Department department)
Now the compiler will correctly complain to you that your method does not in fact override a method in its base class, alerting you to the problem at compile time.
To fix your code change the signatures of equals to take Object, add #Override, check for null and for the correct type, do the cast, and then do the actual comparison:
#Override
public boolean equals(Department obj) {
if (obj == null || !(obj instanceof Department)) {
return false;
}
Department dept = (Department)obj
return dept.id == id;
}
Note: Implementing equals like this
return this.hashCode() == department.hashCode();
is very fragile. Although it works in your case, when hash code is a unique ID of the object, this wouldn't survive a code refactoring when hashCode is replaced with some other implementation, for example, an implementation that considers both id and name. If you want to rely on comparing IDs, compare IDs directly, without calling hashCode to get them.
That's because both of classes Employee and Department still have not overriden methods public boolean equals(Object obj) inherited from Object class.
Exactly this method is invoked in dep1.equals(emp2), not public boolean equals(Department department).
More specifically, read JLS:
An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:
...
The signature of mC is a subsignature (ยง8.4.2) of the signature of mA.
In this case boolean equals(Department department) is not subsignature of boolean equals(Object obj).
First, this code dep1.equals(emp2) calls default implementation of Object class.
Second, U didnt overrides the default implementation in both of your class becoz u cant override equal method for specific customizied types.
If u need ur answer to be 15 15 true
replace
public boolean equals(Department department) {
return this.hashCode() == department.hashCode();
}
by
#override
public boolean equals(Object department) {
return this.hashCode() == department.hashCode();
}

How to use enums to create generic API for Search and Filter of POJOs in Java?

Lets say you have a particular enum called Field:
public enum Field {
ALBUM,
DESCRIPTION
}
And another enum called:
public enum Operator {
CONTAINS,
EQUALS,
LESS_THAN,
GREATER_THAN
}
And you have a corresponding Java interface called Music
public interface Music {
String getAlbum();
String getDescription();
}
Which the implementation looks liks this:
public class MusicImpl implements Music {
#Override
public String getYear() {
return Field.Year.toString();
}
#Override
public String getDescription() {
return Field.DESCRIPTION.toString();
}
#Override
public Object getField(Field field) {
Object myObject = field.getClass();
return myObject;
}
}
How would you use this API to implement the following two methods?
public class MyApp {
#Override
public List<Music> searchMusic(String query) {
// What to put in this?
}
#Override
public List<Music> filterMusic(Field field, Operator op, String query) {
// What to put in?
}
}

Java equals() and hashcode() during automatic code generation

I am working on a project where code gets automatically generated based upon an MySQL library. It is somewhat like JPA, but not quite.
This is an example bean:
public class TemplateBean implements Bean {
private Integer templateId;
private Integer businessPartnerId;
public TemplateBean(final Integer businessPartnerId) {
this.businessPartnerId = businessPartnerId;
}
private TemplateBean(final Object nullObject, final Integer templateId, final Integer businessPartnerId) {
this.templateId = templateId;
this.businessPartnerId = businessPartnerId;
}
public TemplateBean(final ResultSet rs) throws SQLException {
this(null, rs.getInt(1), rs.getInt(2));
}
public Integer getTemplateId() {
return templateId;
}
public void setTemplateId(final Integer templateId) {
this.templateId = templateId;
}
public Integer getBusinessPartnerId() {
return businessPartnerId;
}
public void setBusinessPartnerId(final Integer businessPartnerId) {
this.businessPartnerId = businessPartnerId;
}
#Override
public String toString() {
return "Template(" + templateId + ", " + businessPartnerId + ")";
}
}
Now I need it to implement equals() and hashCode(). I of course have access to all data that is available from SQL, so I think implementing equals() should be doable, but how am I going to create a good hashCode()?
Any tips will be appreciated.
I would like to suggest to use EqualsBuilder
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
public class Person {
private String id;
private String name;
private String address;
private String phone;
private String version;
#Override
public boolean equals(Object object) {
return EqualsBuilder.reflectionEquals(this, object,);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
or
/*
* equal() method with exclude fields.
* it will neglect id and version fields.
*
* */
#Override
public boolean equals(Object object) {
return EqualsBuilder.reflectionEquals(this, object, "id", "version");
}
}
One very convenient way is to use the #EqualsAndHashCode annotation provided by Groovy. Using this is as simple as
#EqualsAndHashCode
public class TemplateBean implements Bean {
// implementation omitted
}
This will generate equals() and hashCode() methods based on the class' properties using an algorithm similar to the one outlined in the book Effective Java.
Because the annotation is implemented via an AST transformation, it can be used in Java or Groovy classes, though you will of course need the Groovy library on your classpath to use it.

Java: After adding 2 identical objects to a Set, it contains the 2 elements

After adding two identical objects to a Set, I would expect the set to contain only one element.
public void addIdenticalObjectsToSet(){
Set<Foo> set = new HashSet<Foo>();
set.add(new Foo("totoro"));
set.add(new Foo("totoro"));
Assert.assertEquals(1, set.size()); // PROBLEM: SIZE=2
}
private class Foo {
private String id;
public Foo(String id) {
this.id = id;
}
public String getId() {
return id;
}
public boolean equals(Object obj) {
return obj!= null && obj instanceof Foo &&
((Foo)obj).getId().equals(this.getId());
}
public int hashcode() {
return this.getId().hashCode();
}
}
I consider two objects as identical if they have the same id (String).
Other strange thing: Neither Foo.equals nor Foo.hashcode are accessed, as far as I can tell using debug/breakpoints. What am I missing?
public int hashcode() {
return this.getId().hashCode();
}
should be
#Override
public int hashCode() {
return this.getId().hashCode();
}
The annotation would have told you about the spelling mistake.
There should also be a (missing) little triangle symbol in your IDE on the method to indicate if an interface is being implemented or a parent method overridden.

Why isn't Collections.binarySearch() working with this comparable?

I have this Player class which implements the Comparable interface. Then I have an ArrayList of Players. I'm trying to use binarySearch() on the list of Players to find one Player, but Java is giving me a "cannot find symbol: method binarySearch(java.util.ArrayList< Player>,Player)".
This the Player class:
class Player implements Comparable {
private String username;
private String password;
Statistics stats;
//Constructor, creates a new Player with a supplied username
Player(String name) {
username = name;
password = "";
stats = new Statistics();
}
//Accessor method to return the username as a String
String getName() {
return username;
}
String getPassword() {
return password;
}
void setPassword(String newPass) {
password = newPass;
}
//Method to change the username
void setName(String newName) {
username = newName;
}
public int compareTo(Object o) {
return username.compareTo(((Player)o).username);
}
}
Weird thing, when I try Collections.sort() on this same list, it works.
Use are using generics inconsistently. Take heed of the compiler warnings. Always supply generic arguments (or never supply them).
Instead of:
class Player implements Comparable {
[...]
public int compareTo(Object o) {
Use
class Player implements Comparable<Player> {
[...]
public int compareTo(Player o) {
The rules of generics are difficult enough without the complication of rare types. So, typically the language spec gives up if you mix them up.
As long as you are implementing Comparable, you can make compareTo() consistent with equals() by also overriding equals() and hashCode(). This is particularly easy in this case, as you can simply delegate to String. Moreover, it's convenient if you ever need a Map containing instances of Player:
class Player implements Comparable<String> {
private String username;
private String password;
// ...
#Override
public int compareTo(String name) {
return username.compareTo(name);
}
#Override
public boolean equals(Object obj) {
return obj instanceof Player
&& username.equals(((Player)obj).username);
}
#Override
public int hashCode() {
return username.hashCode();
}
}

Categories