Je rencontre un comportement étrange en essayant de surcharger une méthode avec accesseur par défaut (ex: void run()
). Selon Java spec, une classe peut utiliser ou remplacer les membres par défaut de la classe de base si les classes appartiennent au même package. Tout fonctionne correctement lorsque toutes les classes sont chargées à partir du même chargeur de classe. Mais si j'essaie de charger une sous-classe de séparé classloader alors le polymorphisme ne fonctionne pas.Le remplacement de la méthode d'accès par défaut à travers différents classloaders rompt le polymorphisme
est Voici un exemple:
App.java:
import java.net.*;
import java.lang.reflect.Method;
public class App {
public static class Base {
void run() {
System.out.println("error");
}
}
public static class Inside extends Base {
@Override
void run() {
System.out.println("ok. inside");
}
}
public static void main(String[] args) throws Exception {
{
Base p = (Base) Class.forName(Inside.class.getName()).newInstance();
System.out.println(p.getClass());
p.run();
} {
// path to Outside.class
URL[] url = { new URL("file:/home/mart/workspace6/test2/bin/") };
URLClassLoader ucl = URLClassLoader.newInstance(url);
final Base p = (Base) ucl.loadClass("Outside").newInstance();
System.out.println(p.getClass());
p.run();
// try reflection
Method m = p.getClass().getDeclaredMethod("run");
m.setAccessible(true);
m.invoke(p);
}
}
}
Outside.java: devrait être dans le dossier séparé. sinon classloader sera le même
public class Outside extends App.Base {
@Override
void run() {
System.out.println("ok. outside");
}
}
La sortie:
class App$Inside
ok. inside
class Outside
error
ok. outside
Alors j'appelle Outside#run()
je suis arrivé Base#run()
("erreur" en sortie). Les réflexions fonctionnent correctement.
Qu'est-ce qui ne va pas? Ou est-ce un comportement attendu? Puis-je contourner ce problème en quelque sorte?
Je remarque que votre classe 'Outside' déclare' run' être public ... Je me demande si c'est le problème. Pouvez-vous l'essayer avec 'Outside.run' ayant un accès par défaut? –
Si 'Outside # run' a un accesseur par défaut quand Reflections (sans' setAccessible (true) ') _also_ ne fonctionne pas:' 'Exception dans le thread" main "' java.lang.IllegalAccessException: L'application Class ne peut pas accéder à un membre de class Outside avec des modificateurs "" ' – mart
J'ai réécrit l'échantillon pour Outside # run a l'accesseur par défaut – mart