Как получить номер строки метода?

Можно ли получить номер строки метода с использованием отражения или другой магии?
Это возможно, если метод находится внутри текущей Stacktrace. Используя Thread.currentThread().getStackTrace(), можно получить номер строки StackTraceElement. Но что я могу сделать, если я получил java.lang.reflect.Method Объект?

Я нашел это, для classes- > Как получить исходное имя файла/номер строки из объекта java.lang.Class, но это не полезно для методов.

Ответ 1

Я хотел сделать то же самое, и после некоторых исследований, посвященных джавассисту. Вам нужно будет добавить javassist (я использовал версию 3.15.0-GA).

Учитывая следующий класс, определите местоположение метода "x". Имя метода "x" жестко закодировано, однако, если вы находитесь в той же лодке, что и я, отражение не сложно, поэтому я уверен, что вы можете получить список имен методов, а затем вы получите номера строк методов:

public class Widget {
    void x(){System.out.println("I'm x\n");}
    //comment added to create space
    void y(){System.out.println("I'm y\n");} 
}

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

public class App {
    public static void main(String[] args) throws NotFoundException {
        System.out.println("Get method line number with javassist\n");
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.quaternion.demo.Widget");
        CtMethod methodX = cc.getDeclaredMethod("x");
        int xlineNumber = methodX.getMethodInfo().getLineNumber(0);
        System.out.println("method x is on line " + xlineNumber + "\n");
    }
}

Выход: method x is on line 12, который в моем случае является точным, я вырезал некоторые комментарии...

Примечание. Как упоминалось в комментариях Pete83, этот метод фактически возвращает первую строку кода в методе, а не строку, объявляющую метод. Обычно это не будет проблемой, поскольку большинство из них, вероятно, захотят установить относительное положение (порядок, в котором они были объявлены), и использовать эту информацию для своих собственных конвенций. Это будет возникать в любое время, когда вы почувствуете необходимость включить порядковое значение в аннотацию, которая может быть легко определена положением внутри самого кода.


Для быстрого указания координат Maven для javassist:
<dependency>
   <groupId>org.javassist</groupId> <!-- if a version prior to 3.13.0-GA is needed use "javassist" and not "org.javassist" -->
   <artifactId>javassist</artifactId>
   <version>3.15.0-GA</version>
</dependency>

Ответ 2

Для меня ответ Кватерниона, указывающий на Джавассиста, является идеальным решением этого вопроса. Он работает для меня, и вы можете использовать его также, когда вы получаете только объект java.lang.reflect.Method.

Вот как я это сделал:

Method m; // the method object
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get(m.getDeclaringClass().getCanonicalName());
CtMethod javassistMethod = cc.getDeclaredMethod(m.getName());
int linenumber = javassistMethod.getMethodInfo().getLineNumber(0);

Ответ 3

Вы не можете получить номер строки из метода, потому что вы не знаете, к какому методу это относится. Метод может вызывать любой подкласс того, который вы выбрали.