2017-01-14 3 views
3

Ich versuche, ein Verfahren zu schaffen, die die Parameter von 2 Methoden und geben Sie mir einen Prozentsatz der passenden Parameter, wie vergleicht:ASM MethodNode Parameter vergleichen

Method1(int i, boolean b, char c)  
Method2(boolean b, int i) 
Method3(char c)  
Method4(double d) 


Method1 and Method2 = 66% -> 2 matching parameters  
Method1 and Method3 = 33% -> 1 matching parameter 
Method1 and Method4 = 0% -> 0 matching parameters 

Kann mir jemand eine Ahnung, wie dies zu tun ?

+0

sieht eher wie eine Frage für einen Compiler als für ein Java-Programm . Fromw innerhalb eines Programms können Sie Methoden nicht untersuchen, soweit ich weiß. –

Antwort

3

mit Holger Tipps Aktualisiert

private static float compare(MethodNode mn1, MethodNode mn2) { 
    Type[] typeArgs1 = Type.getArgumentTypes(mn1.desc); 
    Type[] typeArgs2 = Type.getArgumentTypes(mn2.desc); 
    int max = Math.max(typeArgs1.length, typeArgs2.length); 
    if (max == 0) 
     return 1f; 
    int matches = 0; 
    List<Type> types = Arrays.asList(typeArgs1); 
    for (Type arg : typeArgs2) 
     if (types.contains(arg)) 
      matches++; 
    return ((float) matches/max); 
} 

Originalcode:

private static float compare(MethodNode mn1, MethodNode mn2) { 
    Type t1 = Type.getMethodType(mn1.desc); 
    Type t2 = Type.getMethodType(mn2.desc); 
    Type[] targs1 = t1.getArgumentTypes(); 
    Type[] targs2 = t2.getArgumentTypes(); 
    int max = Math.max(targs1.length, targs2.length); 
    int matches = 0; 
    if (max == 0) 
     return 1f; 
    List<String> types1 = new ArrayList<String>(); 
    for (Type t : targs1) 
     types1.add(t.getDescriptor()); 
    for (Type t : targs2) 
     if (types1.contains(t.getDescriptor())) 
      matches++; 
    return (1F * matches/max); 
} 

Ausgang für Ihr Beispiel Methoden:

0,1 0.0 
0,2 0.0 
0,3 0.0 
0,4 0.0 
1,2 0.6666667 
1,3 0.33333334 
1,4 0.0 
2,3 0.0 
2,4 0.0 
3,4 0.0 
+1

Es wäre sinnvoller, 'types1' als' Set' zu deklarieren (z. B. mit einem 'HashSet'). Außerdem verfälscht das Multiplizieren mit "1F" die tatsächliche Absicht, eine einfache Umwandlung von "int" in "float" durchzuführen. Verwenden Sie stattdessen einen Typ-Cast, '(float) matches'. Beachten Sie, dass Sie Ihren Code vereinfachen können, indem Sie einfach ['Type.getArgumentTypes (desc)'] (http://asm.ow2.org/asm50/javadoc/user/org/objectweb/asm/Type.html#getArgumentTypes) verwenden -java.lang.String-) ohne den Umweg über 'Type.getMethodType'. Sie können auch die Tatsache nutzen, dass "Type" bereits 'equals' und' hashCode' implementiert, so dass Sie 'getDescriptor()' nicht benötigen. – Holger

+0

Ich habe das Snippet mit Ihren Vorschlägen aktualisiert, abgesehen von der Verwendung eines HashSets. Stattdessen habe ich 'Arrays.asList' verwendet, um zwei zusätzliche Zeilen hinzuzufügen. Der zusätzliche Schritt 'new HashSet (Arrays.asList (typeArgs1));', um ein 'Set ' zu erstellen, scheint unnötig. –

+0

Scheint fair. Die Anzahl der Parametertypen ist normalerweise sehr klein und auf '255' beschränkt, so dass der leichtgewichtige 'Arrays.toList'-Wrapper in den meisten Fällen besser ist als das Kopieren auf ein' HashSet'. Beachten Sie jedoch, dass Sie eine Code-Duplizierung haben. Sie rufen 'Type.getArgumentTypes (mn2.desc)' zweimal auf, anstatt die Variable 'typeArgs2' zu verwenden. – Holger