Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<blockquote> <p>In general, I don't want really to change the class of the objects. What I want is to have some mechanism to make client classes to obey to the contracts of the different types. I.e., I don't want a class to be able to call setShareholders on a Person, and it's not important how I can achieve this, I mean that maybe the fact that an entity is a Person can be represented on other ways than using a class Person.</p> </blockquote> <p>This last paragraph got me thinking that a <a href="https://stackoverflow.com/questions/933993/what-are-dynamic-proxy-classes-and-why-would-i-use-one">dynamic proxy</a> may address your need. If you have an "<em>entity</em>" E that "<em>is a Person [that] can be represented on other ways than using a class Person</em>". A proxy could wrap your entity E and "implement"/present only the desired interface <code>Person</code> (while hiding any other implemented interfaces or implementation detail about E).</p> <p><em>Edit: Since the OP found the answer useful, I'm adding a utility class and demo code:</em></p> <p>Some code:</p> <pre><code>import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * Utilities to support using dynamic proxies */ public class DynamicProxy { /** * An invocation handler that passes calls to its delegate. This class * could be subclassed to provide dynamic method invocation handling * while still being able to fall back to the delegate object's methods. * * @see InvocationHandler */ public static class DelegatingInvocationHandler implements InvocationHandler { /** The object this proxy is wrapping */ private final Object delegate; /** * Creates a delegate invocation handler around an object * * @param object * The object to wrap */ public DelegatingInvocationHandler(final Object delegate) { this.delegate = delegate; } /* (non-Javadoc) * * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, * java.lang.reflect.Method, java.lang.Object[]) */ @Override public Object invoke(final Object proxy, final Method m, final Object[] args) throws Throwable { Object result; try { result = m.invoke(delegate, args); } catch (final InvocationTargetException e) { throw e.getTargetException(); } catch (final Exception e) { throw new RuntimeException("unexpected invocation exception: " + e.getMessage()); } return result; } } /** * Create a dynamic proxy that implements only a specified subset of the * original object's implemented interfaces. The proxy allows you to * essentially hide the other interfaces implemented by the original * object. * * @param delegate * the object that the proxy "proxies" for (a.k.a. the delegate * that handles the calls the proxy "allows" through) * @param requiredInterface * one of the interfaces of the delegate that the proxy exposes * @param moreInterfaces * any additional interfaces of the delegate to expose * @return the proxy * a proxy for the delegate that can be cast to any of the * specified interfaces */ public static &lt;T&gt; T createSelectiveProxy(final T delegate, final Class&lt;T&gt; requiredInterface, final Class&lt;?&gt;... moreInterfaces) { if (delegate == null) { throw new IllegalArgumentException( "The delegate object cannot be null"); } return createProxy(new DelegatingInvocationHandler(delegate), requiredInterface, moreInterfaces); } /** * Creates a proxy using the specified invocation handler. * * @param object * the implementing object that proxy wraps * @param invocationHandler * the interfaces * @param moreInterfaces * the interfaces * @return the object */ @SuppressWarnings("unchecked") public static &lt;T&gt; T createProxy(final InvocationHandler invocationHandler, final Class&lt;T&gt; requiredInterface, final Class&lt;?&gt;... moreInterfaces) { if (invocationHandler == null) { throw new IllegalArgumentException( "The invocation handler cannot be null"); } final int size = (moreInterfaces != null ? moreInterfaces.length : 0); final Class&lt;?&gt;[] interfaces = new Class&lt;?&gt;[size + 1]; interfaces[0] = requiredInterface; System.arraycopy(moreInterfaces, 0, interfaces, 1, moreInterfaces.length); return (T) Proxy.newProxyInstance(invocationHandler.getClass() .getClassLoader(), interfaces, invocationHandler); } } </code></pre> <p>Demo:</p> <pre><code>public class DynamicProxyDemo { private interface A { void methodA(); } private interface B { void methodB(); } private static class Foo implements A, B { public void methodA() { System.out.println("A"); } public void methodB() { System.out.println("B"); } } private DynamicProxyDemo() {} public static void main(final String[] args) { final Foo foo = new Foo(); // implements both interfaces // calls foo's methods, but only A methods final A a = DynamicProxy.createSelectiveProxy(foo, A.class); // calls foo's methods, but only B methods final B b = DynamicProxy.createSelectiveProxy(foo, B.class); // calls foo's methods, but A and B methods final A ab = DynamicProxy.createSelectiveProxy(foo, A.class, B.class); System.out.println("\n *** Call a method A.methodA() on proxy 'a'"); a.methodA(); try { System.out.println("\n *** Call a method B.methodB() on proxy 'a' (throws exception)"); ((B) a).methodB(); } catch (final Exception ex) { ex.printStackTrace(System.out); } System.out.println("\n *** Call a method B.methodB() on proxy 'b'"); b.methodB(); try { System.out.println("\n *** Call a method A.methodA() on proxy 'b' (throws exception)"); ((A) b).methodA(); } catch (final Exception ex) { ex.printStackTrace(System.out); } System.out.println("\n *** Call a method A.methodA() on proxy 'ab'"); ab.methodA(); System.out.println("\n *** Call a method B.methodB() on proxy 'ab'"); ((B) ab).methodB(); // ClassCastException: $Proxy0 cannot be cast to DynamicProxy$Foo try { System.out.println("\n *** Call a method 'A' of class 'Foo' on proxy 'a' (throws exception)"); ((Foo) a).methodA(); } catch (final Exception ex) { ex.printStackTrace(System.out); } // ClassCastException: $Proxy1 cannot be cast to DynamicProxy$Foo try { System.out.println("\n *** Call a method 'B' of class 'Foo' on proxy 'b' (throws exception)"); ((Foo) b).methodB(); } catch (final Exception ex) { ex.printStackTrace(System.out); } // ClassCastException: $Proxy0 cannot be cast to DynamicProxy$B try { System.out.println("\n *** Call a method B.methodB() on proxy 'a' (throws exception)"); ((B) a).methodB(); } catch (final Exception ex) { ex.printStackTrace(System.out); } // ClassCastException: $DynamicProxy1 cannot be cast to DynamicProxy$A try { System.out.println("\n *** Call a method A.methodA() on proxy 'b' (throws exception)"); ((A) b).methodA(); } catch (final Exception ex) { ex.printStackTrace(System.out); } } } </code></pre> <p>Run:</p> <pre><code> *** Call a method A.methodA() on proxy 'a' A *** Call a method B.methodB() on proxy 'a' (throws exception) java.lang.ClassCastException: net.bertfernandez.reflection.$Proxy0 cannot be cast to net.bertfernandez.reflection.DynamicProxyDemo$B at net.bertfernandez.reflection.DynamicProxyDemo.main(DynamicProxyDemo.java:49) *** Call a method B.methodB() on proxy 'b' B *** Call a method A.methodA() on proxy 'b' (throws exception) java.lang.ClassCastException: net.bertfernandez.reflection.$Proxy1 cannot be cast to net.bertfernandez.reflection.DynamicProxyDemo$A at net.bertfernandez.reflection.DynamicProxyDemo.main(DynamicProxyDemo.java:59) *** Call a method A.methodA() on proxy 'ab' A *** Call a method B.methodB() on proxy 'ab' B *** Call a method 'A' of class 'Foo' on proxy 'a' (throws exception) java.lang.ClassCastException: net.bertfernandez.reflection.$Proxy0 cannot be cast to net.bertfernandez.reflection.DynamicProxyDemo$Foo at net.bertfernandez.reflection.DynamicProxyDemo.main(DynamicProxyDemo.java:73) *** Call a method 'B' of class 'Foo' on proxy 'b' (throws exception) java.lang.ClassCastException: net.bertfernandez.reflection.$Proxy1 cannot be cast to net.bertfernandez.reflection.DynamicProxyDemo$Foo at net.bertfernandez.reflection.DynamicProxyDemo.main(DynamicProxyDemo.java:81) *** Call a method B.methodB() on proxy 'a' (throws exception) java.lang.ClassCastException: net.bertfernandez.reflection.$Proxy0 cannot be cast to net.bertfernandez.reflection.DynamicProxyDemo$B at net.bertfernandez.reflection.DynamicProxyDemo.main(DynamicProxyDemo.java:89) *** Call a method A.methodA() on proxy 'b' (throws exception) java.lang.ClassCastException: net.bertfernandez.reflection.$Proxy1 cannot be cast to net.bertfernandez.reflection.DynamicProxyDemo$A at net.bertfernandez.reflection.DynamicProxyDemo.main(DynamicProxyDemo.java:97) </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload