2016-03-25 12 views
5

Javaでは、メソッドで使用されるフィールドを取得するにはどうすればよいですか?Java:メソッドで使用されるリストフィールド

基本的には、this one in .NETと同じ質問です。クラスのフィールドをリストするのではなく、クラスの特定のメソッドで使用されているフィールドをリストすることはできません。

例:

public class A { 
int a; 
int b; 

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

私はこのようなフィールドを取得したい:私は、標準のリフレクションを使用して、任意の解決策を見つけられませんでしたfields[0]=A.afields[1]=A.b

ようにするため

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

を。あなたはASMのようなバイトコード操作ライブラリは行く方法だと思いますか?

+0

あなたはこれをやりたい理由について少し説明できますか?あなたが文脈を説明することができれば、より簡単な方法があるようです。 – sprinter

+0

これは研究目的であり、コンパレータで使用されるフィールドをリストアップする必要があります。 – Julien

+1

http://asm.ow2.org/asm50/javadoc/user/org/objectweb/asm/MethodVisitor.html、より具体的な 'visitFieldInst'メソッドを使用できます。 ASMのマニュアルを見て、それは良い出発点です。 – Grzesuav

答えて

2

javassistの例です(従属マネージャの設定に応じて、依存関係として追加する必要があります)。

このコードは、public void doSomething();メソッドでアクセスされるフィールドを一覧表示します。あなたがclassnodeをロードしたら

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、[文字列タイピング](http://c2.com/cgi/wiki?StringlyTyped)。 – immibis

1

は、これは信じられないほど容易になります。

// 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 
     } 
    } 
} 

プラスASMは、Javassistなどのライブラリよりもはるかに高速です。

+0

パフォーマンスが問題になるため、私はこのソリューションに切り替える可能性があります。両方のアプローチを比較するためにいくつかのテストを行います – Julien