是否可以使用反射或其他魔法获取方法的行号?
如果方法在当前Stacktrace内,则可能。使用Thread.currentThread().getStackTrace()
,可以获得StackTraceElement
的行号。但是,如果我只获得java.lang.reflect.Method
对象,我该怎么办?
我找到了这个,对于课程 - > How to get source file-name/line-number from a java.lang.Class object但它对方法没用。
答案 0 :(得分:15)
我想做同样的事情,经过一些研究确定了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>
答案 1 :(得分:8)
对我而言,Quaternion指向Javassist的答案是这个问题的完美解决方案。 它适用于我,当你只获得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);
答案 2 :(得分:1)
您无法从Method获取行号,因为您不知道这适用于哪种方法。方法可以调用您选择的子类的任何子类。