2016-03-25 30 views
5

Java'da, bir yöntemde kullanılan Alanları nasıl alabilirim?Java: bir yöntemde kullanılan liste alanları

Temel olarak, bu this one in .NET ile aynı sorudur. Sınıflardan alan listelemek istemiyorum, ancak sınıfın belirli bir yönteminde kullanılan alanları listelemiyorum.

Örnek:

public class A { 
int a; 
int b; 

public int bob(){ 
return a-b; 
} 

böyle alanları almak istiyorum:

Fields[] fields = FieldReader.(A.class.getMethod("bob")); 

Böylece fields[0]=A.a ve fields[1]=A.b

Ben standart Yansıma kullanarak herhangi bir çözüm bulamadık. ASM gibi bir bytecode manipülasyon kütüphanesi gitmek için bir yol olduğunu düşünüyor musunuz?

+0

Bunu neden yapmak istediğiniz hakkında biraz bilgi verir misiniz? Bağlamı açıklayabilirseniz daha kolay bir yolu olması muhtemeldir. – sprinter

+0

Bu araştırma amaçlıdır, karşılaştırıcıda kullanılan alanları listelemem gerekiyor. – Julien

+1

http://asm.ow2.org/asm50/javadoc/user/org/objectweb/asm/MethodVisitor.html, daha spesifik 'visitFieldInst' yöntemini kullanabilirsiniz. ASM kılavuzuna bakın, bu iyi bir başlangıç ​​noktasıdır. – Grzesuav

cevap

2

İşte bir örnek javassist ile (bağımlılık yöneticisi tercihlerinize bağlı olarak onu bağımlı olarak eklemeniz gerekir).

Bu kod, public void doSomething(); yönteminde erişilen alanı listeler. Bir classnode yüklemek kez

package bcm; 

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.PrintStream; 

import javassist.CannotCompileException; 
import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.CtMethod; 
import javassist.NotFoundException; 
import javassist.bytecode.InstructionPrinter; 

public class Person { 

    String name; 
    String surname; 
    int age; 

    boolean candrink = false; 

    public Person(String name, String surname, int age) { 
     super(); 
     this.name = name; 
     this.surname = surname; 
     this.age = age; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getSurname() { 
     return surname; 
    } 

    public void setSurname(String surname) { 
     this.surname = surname; 
    } 

    public int getAge() { 
     return age; 
    } 

    public void setAge(int age) { 
     this.age = age; 
    } 

    public void doSomething() { 
     if (this.age > 18) { 
      candrink = true; 
     } 
    } 

    public static void main(String[] args) throws IOException, 
      CannotCompileException { 
     ClassPool pool = ClassPool.getDefault(); 
     try { 
      CtClass cc = pool.get("bcm.Person"); 
      CtMethod m = cc.getDeclaredMethod("doSomething", null); 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      PrintStream ps = new PrintStream(baos); 
      InstructionPrinter i = new InstructionPrinter(ps); 
      i.print(m); 
      String content = baos.toString(); 

      for (String line : content.split("\\r?\\n")) { 
       if (line.contains("getfield")) { 
        System.out.println(line.replaceAll("getfield ", "")); 
       } 
      } 

     } catch (NotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

HTH

+1

Ack, [string typing] (http://c2.com/cgi/wiki?StringlyTyped). – immibis

1

bu inanılmaz kolay hale gelir.

// Assuming you have loaded classNode 
for (MethodNode method : classNode.methods){ 
    for (AbstractInsnNode ain : method.instructions.toArray()) { 
     if (ain.getType() == AbstractInsnNode.FIELD_INSN) { 
      FieldInsnNode fin = (FieldInsnNode) ain; 
      //fin.name = Field name 
      //fin.owner = ClassNode's name 
     } 
    } 
} 

Artı ASM, Javassist gibi kitaplıklardan çok daha hızlıdır.

+0

Performans bir sorun olduğundan, bu çözüme geçebilirim. Her iki yaklaşımı karşılaştırmak için bazı testler yapacağım – Julien

İlgili konular