19

是否可以使用反射或其他魔法获取方法的行号?
如果该方法在当前 Stacktrace 中,则有可能。使用Thread.currentThread().getStackTrace(),可以得到一个StackTraceElement. 但是,如果我只得到了java.lang.reflect.Method对象,我该怎么办?

我发现了这个,对于类->如何从 java.lang.Class 对象获取源文件名/行号,但它对方法没有用。

4

3 回答 3

18

在对 javassist 进行了一些研究之后,我想做同样的事情。您将需要添加 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 在评论中提到的,此方法实际上返回方法中的第一行代码,而不是声明方法的行。这通常不会成为问题,因为大多数人可能希望建立相对位置(声明它们的顺序)并将此信息用于您自己的约定。每当您觉得需要在注释中包含一个序数值时,就会出现这种情况,这可以很容易地由代码本身中的位置确定。


快速参考 javassist 的 Maven 坐标:

<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>
于 2013-02-20T06:38:24.970 回答
9

对我来说,指向 Javassist 的 Quaternion 的答案是这个问题的完美解决方案。它对我有用,当你只获得 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);
于 2013-05-02T11:17:57.220 回答
0

您无法从 Method 中获取行号,因为您不知道这适用于哪种方法。方法可以调用您选择的方法的任何子类。

于 2012-10-11T08:05:13.037 回答