Aujourd'hui, j'ai découvert que l'utilisation de Collections.synchronizedXXX ne fonctionne pas correctement avec la réflexion.Solution de contournement pour les wrappers de collections Java qui interrompent la réflexion
Voici un exemple simple:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Weird{
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Hello World");
List<String> wrappedList = Collections.synchronizedList(list);
printSizeUsingReflection(list);
printSizeUsingReflection(wrappedList);
}
private static void printSizeUsingReflection(List<String> list) {
try {
System.out.println(
"size = " + list.getClass().getMethod("size").invoke(list));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Le premier appel à printSizeUsingReflection imprime la taille (c.-à "1"), les résultats du deuxième appel à:
java.lang.IllegalAccessException: Class Weird can not access a member of class
java.util.Collections$SynchronizedCollection with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.reflect.Method.invoke(Method.java:588)
at Weird.printSizeUsingReflection(Weird.java:18)
at Weird.main(Weird.java:13)
Ceci est un peu surprenant et ennuyeux. Y a-t-il une bonne solution de contournement? Je sais qu'il existe une implémentation de liste thread-safe dans java.util.concurrent, mais cette implémentation semble plus lente que l'utilisation de Collections.synchronizedList().
+1 n'utilisez simplement pas de réflexion. 'list.size()' fonctionne bien dans ces situations. – akf
J'éviterais la réflexion si je le pouvais. Dans ce cas, j'ai un intercepteur AOP mis en place par Google Guice, et j'essaie d'enregistrer des choses utiles sur les arguments de la méthode - malheureusement, les types de classe sont essentiellement le seul que je connaisse sur les arguments. Merci pour le conseil Collection.class .. fonctionne comme un charme! –