How to decorate an object in Java

Fast background

I have two lists of (large) POJOs that are passed to a method in which I need to ensure uniqueness in two lists. The best solution that I see is to build two sets and verify that their intersection is empty.

Problem

In the context of this method, and only this method I need to override the method equalsand hashcodefor the POJO.

What i'm looking for

This seems to be the first touch to decorate existing objects. I looked at Guava ForwardingObject , but it seems to be best suited for delegating objects that implement this interface, which is not my case. All in all, I'm looking for a solution that ...

  • Prevents execution of all fields of a large POJO (copy constructors).
  • Easy to understand and maintain
  • Avoids creating a whole new class that extends POJO for the sake of this method
+5
source share
3 answers

I would just go with a wrapper class.

Create a new class created using your POJO in the constructor. It does not copy POJO, just holds onto the link to the original. Then write equalities and hashcode as you like in this wrapper class.

Something like that:

public class MySpecialWrapper{
  private final BigPojo delegate;

  public MySpecialWrapper(BigPojo pojo){
    this.delegate = pojo;
  }

  public int hashCode(){
    //insert special impl here.
  }

  public boolean equals(Object o){
    //insert special impl here.
  }
}

Put shell class instances in your sets and use them to verify uniqueness. Add an access method (getDelegate) if you need to access an abusive POJO in case of failure.

+3
source

- POJO. POJO equals hashcode, POJO. Collections.

+2

You can use a dynamic proxy for each element:

class VeryBigPOJO {}

interface PojoWrapper {
  VeryBigPOJO getPojo();
}

class MyHandler implements InvocationHandler {
    private VeryBigPOJO ob;

    public MyHandler( VeryBigPOJO ob ) {
        this.ob = ob;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if( method.getName().equals( "getPojo") )
            return ob;
        if( method.getName().equals( "equals") )
            //calculate equals
        if( method.getName().equals( "hashCode") )
            //calculate hashCode
    }
}

Then wrap the objects in these dynamic proxies:

VeryBigPOJO pojo = ...;
PojoWrapper wrapper =  Proxy.newProxyInstance( MyHandler.class.getClassLoader(), new Class[] { PojoWrapper.class}, new MyWrapper( pojo ) )

And now you can add your objects wrapperto this HashSet.

However, would it be easier to create a smaller, immutable object idfrom a large pojo? This would certainly be more readable.

0
source

All Articles