Не существует действительно практичного, неинвазивного способа защиты от этого.
Однако , если ваша ситуация действительно требует этой защиты, используйте этот служебный класс для создания динамических прокси-серверов (делегатов) (адаптировано из Динамические прокси-классы - <50 строк производственного кода !!). </p>
Это вызовет ClassCastException
s во время выполнения, если кто-то использует попытку злонамеренного приведения. Вы могли бы даже обусловить код, чтобы отключить его во время производства (пусть newInstance()
просто возвращает obj
- объект в качестве «прокси»).
DynamicProxy.java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DynamicProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
public static Object newInstance(Object obj, Class<?>... interfaces) {
if (interfaces == null || interfaces.length == 0) {
throw new IllegalArgumentException("No interfaces");
}
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
interfaces,
new DynamicProxy(obj));
}
private DynamicProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object result;
try {
result = m.invoke(obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " +
e.getMessage());
}
return result;
}
// ** DEMO CODE BELOW HERE **
interface A {
void methodA();
}
interface B {
void methodB();
}
static class Foo implements A, B {
public void methodA() { System.out.println("A"); }
public void methodB() { System.out.println("B"); }
}
public static void main(String[] args) {
Foo foo = new Foo(); // implements both interfaces
// calls foo's methods, but only A methods
A a = (A) DynamicProxy.newInstance(foo, A.class);
// calls foo's methods, but only B methods
B b = (B) DynamicProxy.newInstance(foo, B.class);
// calls foo's methods, but only B methods
A ab = (A) DynamicProxy.newInstance(foo, A.class, B.class);
a.methodA();
b.methodB();
ab.methodA();
((B) ab).methodB();
// ClassCastException: $Proxy0 cannot be cast to DynamicProxy$Foo
((Foo) a).methodA();
// ClassCastException: $Proxy1 cannot be cast to DynamicProxy$Foo
((Foo) b).methodB();
// ClassCastException: $Proxy0 cannot be cast to DynamicProxy$B
((B) a).methodB();
// ClassCastException: $DynamicProxy1 cannot be cast to DynamicProxy$A
((A) b).methodA();
}
}