Generics

With this article, the aim is to introduce one pretty nice style of programming which I actually learned in my professional trainee period. With this style, you are able to more in less coding, which means there are lot less programming need to be done.

What is generics

To learn more deeply about generics look these sites. They example it a lot more deeply

What I believe the thing behind curtain is to parameterize the classes or interfaces by types they are using. After that, single method that is introduces in the generic class, can be used afterwards in the other classes. What this means, we no longer have to type each DAO or Manager class separately, which means there can be only one class that handles all the saving, fetching and deleting from database.

So how it’s done?

Firstly we could write all our beans we are going to need and after that we could do the generic class. Let’s start by creating interface

package generic;

public interface Generics {

public T print(T object);
}

After creating the the interface let’s make a class that implements the interface we just created

package generic.impl;

import generic.Generics;

public class GenericImpl<T> implements Generics<T> {

@SuppressWarnings("unchecked")
public T print(T object) {
    return (T) object.toString();
  }
}

We have set up our generics. Next for this example I have created couple beans to demostrate. They are Person and Address, and one of the Person properties is to use Address.

package bean;

public class Address {

private String streetName;
private int postalCode;
String country;

public String getStreetName() {
return streetName;
}

public void setStreetName(String streetName) {
this.streetName = streetName;
}

public int getPostalCode() {
return postalCode;
}

public void setPostalCode(int postalCode) {
this.postalCode = postalCode;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public Address() {
super();
}

public Address(String streetName, int postalCode, String country) {
super();
this.streetName = streetName;
this.postalCode = postalCode;
this.country = country;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((country == null) ? 0 : country.hashCode());
result = prime * result + postalCode;
result = prime * result
+ ((streetName == null) ? 0 : streetName.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Address other = (Address) obj;
if (country == null) {
if (other.country != null)
return false;
} else if (!country.equals(other.country))
return false;
if (postalCode != other.postalCode)
return false;
if (streetName == null) {
if (other.streetName != null)
return false;
} else if (!streetName.equals(other.streetName))
return false;
return true;
}
@Override
public String toString() {
return "Address [streetName=" + streetName + ", postalCode="
+ postalCode + ", country=" + country + "]";
}
}
package bean;
public class Person {
private String firstName;
private String lastName;
private Address address;
public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}

public Person() {
super();
}

public Person(String firstName, String lastName, Address address) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.address = address;
}

@Override
public String toString() {
return "Person [firstName=" + firstName + ", lastName=" + lastName
+ ", address=" + address + "]";
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result
+ ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
}

Now that we have beans we could make DAO classes. Firstly let’s done interface and then we actually make extends to Generics interface. Now we have made DAO interface to inherit the methods of generic interface.

package dao;
import generic.Generics;
import bean.Address;
public interface AddressDAO extends Generics <Address>{
}
package dao;
import bean.Person;
import generic.Generics;
public interface PersonDAO extends Generics<Person> {
}

Next step is to make Implemations that use DAO classes. The key point here is to make extend to genericImpl and then implement the DAO interface. After that, we can use all the methods that has been written to GenericsImpl. And to use it, we just tell which bean class our DAO uses.

package dao.impl;
import bean.Address;
import dao.AddressDAO;
import generic.impl.GenericImpl;
public class AddressDAOImpl extends GenericImpl
<address>implements AddressDAO {
}
package dao.impl;
import generic.impl.GenericImpl;
import bean.Person;
import dao.PersonDAO;
public class PersonDAOImpl extends GenericImpl implements PersonDAO {
}

Now that everthing is set up, we can make custom program to use it.

package example;
import dao.AddressDAO;
import dao.PersonDAO;
import dao.impl.AddressDAOImpl;
import dao.impl.PersonDAOImpl;
import bean.Address;
import bean.Person;
public class Example {
private Address address1;
private Address address2;
private Person person1;
private Person person2;
public void run(){
setUpData();
printdata();
}
public void setUpData(){
address1 = new Address("Street 1", 25456, "Country name");
address2 = new Address("Street 2", 98752, "Country name");
person1 = new Person("John", "Steam", address1);
person2= new Person("Natalie", "Myer", address2);
}
public void printdata(){
PersonDAO personDAO = new PersonDAOImpl();
System.out.println(personDAO.print(person1));
System.out.println(personDAO.print(person2));
AddressDAO addressDAO = new AddressDAOImpl();
System.out.println(addressDAO.print(address1));
System.out.println(addressDAO.print(address2));
}
public static void main (String [] args){
Example example = new Example();
example.run();
}
}

The outcome should be like

 Person [firstName=John, lastName=Steam, address=Address [streetName=Street 1, postalCode=25456, country=Country name]]
Person [firstName=Natalie, lastName=Myer, address=Address [streetName=Street 2, postalCode=98752, country=Country name]]
Address [streetName=Street 1, postalCode=25456, country=Country name]
Address [streetName=Street 2, postalCode=98752, country=Country name]
 

Conclusion

Using the generics can be quite useful tactic when facing the problem that many class is going to use same methods or similar methods. For example, if you are using hibernate, you could build up this kind of handler layer, and then use it in generics.

– Tuomas Törmä

Leave a comment