1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
public class Main {
static interface ConstPersonne {
public String getNom();
}
static class Personne implements ConstPersonne {
private String nom;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
}
@SuppressWarnings("unchecked")
public static <T> T wrapper (Class<T> interfaceType, final T instance) {
return (T) Proxy.newProxyInstance(
instance.getClass().getClassLoader(),
new Class<?>[]{interfaceType},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// On redirige la méthode vers l'instance
return method.invoke(instance, args);
}
});
}
public static void main(String[] args) throws Exception {
Personne personne = new Personne();
personne.setNom("azerty");
// Cas 1 : on utilise simplement une interface (même fonctionnalité que const)
ConstPersonne const1 = personne;
// La 'protection' peut être cassé avec un cast :
System.out.println( const1 instanceof Personne ); // affiche true
((Personne)const1).setNom("qwerty"); // OK (équivalent du const_cast)
// Cas 2 : on englobe l'instance dans un wrapper implémentant l'interface :
ConstPersonne const2 = wrapper(ConstPersonne.class, personne);
// La 'protection' ne peut être cassé avec un cast :
System.out.println( const2 instanceof Personne ); // affiche false
((Personne)const2).setNom("qwerty"); // KO : ClassCastException
}
} |