5

В Java, как я могу получить поля, которые используются в методе?Java: поля списка, используемые в методе

В основном, это те же вопросы, что и this one in .NET. Я не хочу перечислять поля из класса, но перечислять поля, которые используются в данном методе класса.

Пример:

public class A { 
int a; 
int b; 

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

Я хочу, чтобы получить такие поля, как это:

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

Так что fields[0]=A.a и fields[1]=A.b

я не нашел решение с использованием стандартного отражения. Как вы думаете, что можно использовать библиотеку манипуляции с байт-кодом, например 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();.

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(); 
     } 
    } 

} 

НТН

+1

Ack, [строка ввода] (http://c2.com/cgi/wiki?StringlyTyped). – immibis

1

После того, как вы загрузите classnode это становится невероятно легко.

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