2017-03-08 4 views
1

J'ai étendu l'ASM ClassVisitor et je veux savoir si la classe visitée dans une classe anonyme. Comme j'ai le fichier de classe, j'ai pensé que si le nom du fichier de classe se terminait par $ [1-9] [0-9] *. Class, ce serait une classe anonyme. Mais les caractères de devise sont valides dans les noms de classe, par exemple une classe nommée MyClass $ 1 correspond (class class est nommée MyClass $ 1.class) même si ce n'est pas une classe anonyme. Je sais que la plupart des gens ne nommeraient probablement pas des choses comme ça, mais c'est permis. J'ai donc pensé à surcharger la méthode visitOuterClass pour voir si elle avait une classe externe qui éliminerait les classes externes avec des noms se terminant par $ # mais vous pourriez toujours avoir un nom de classe interne non anonyme se terminant, par exemple, par $ 1.Comment savoir si je suis en train de visiter une classe anonyme dans ASM?

Y at-il un moyen dans ASM de savoir qu'il visite une classe anonyme? Ou un meilleur tour que le mien?

# signifie un nombre quelconque (regexp: [1-9] [0-9] *)

Répondre

2

Les critères pertinents est de savoir si la classe InnerClasses attribute déclare que la classe est une classe interne anonyme. ASM signale le contenu en appelant visitInnerClass pour chaque entrée de l'attribut, le cas échéant.

Vous pouvez le vérifier comme

public class CheckForInnerClass extends ClassVisitor { 
    public static void main(String[] args) throws IOException { 
     Class<?>[] test={ Object.class, Map.Entry.class, new Object(){}.getClass() }; 
     for(Class<?> c: test) { 
      new ClassReader(c.getName()) 
       .accept(new CheckForInnerClass(Opcodes.ASM5), ClassReader.SKIP_CODE); 
     } 
    } 

    private String actualName; 
    private Boolean anonymous; 

    public CheckForInnerClass(int api) { 
     super(Opcodes.ASM5); 
    } 
    @Override 
    public void visit(int version, int access, 
     String name, String signature, String superName, String[] interfaces) { 
     actualName=name; 
    } 
    @Override 
    public void visitInnerClass(String name, String outer, String innerName, int access) { 
     if(name.equals(actualName)) { 
      anonymous = innerName==null; 
     } 
    } 
    @Override 
    public void visitEnd() { 
     System.out.println(actualName+": is " 
      + (anonymous==null? "not an": anonymous? "an anonymous": "a named") 
      + " inner class"); 
    } 
} 

qui imprime

java/lang/Object: is not an inner class 
java/util/Map$Entry: is a named inner class 
CheckForInnerClass$1: is an anonymous inner class 
+0

Merci! Pensé/googling sur ceci et off pour quelques jours. – osundblad