是这样的 我想写一个函数 例如 void func(String param)String a = "hello";
String b = "world";我把变量a 传进去 它能打印出变量名 "a"
我把变量b 传进去 它能打印出变量名 "b"以此类推
不知道大家有没有什么办法 我网上查了一下 只找到一个用反射机制 输出对象中属性变量名的方法但是这种输出 传进来参数的变量名 能不能实现 怎么实现 望高手赐教能解决此问题者 立马送上50分
String b = "world";我把变量a 传进去 它能打印出变量名 "a"
我把变量b 传进去 它能打印出变量名 "b"以此类推
不知道大家有没有什么办法 我网上查了一下 只找到一个用反射机制 输出对象中属性变量名的方法但是这种输出 传进来参数的变量名 能不能实现 怎么实现 望高手赐教能解决此问题者 立马送上50分
String a = "hello";
String b = "world";func(a);
func(b);这样会输出a和b?这个基本不太可能实现,因为a和b这个名字都可能在编译后没有了如果你非常非常需要这个东西,那么在保证这个类保持LocalVariable表的时候,再在你的实现中根据new Exception().getStackTrace()[1]得到行号,再访问这个类LineNumber表,再分析Class的指令,最后可以大致算出传入的名字是什么。
但是这个非常非常非常非常复杂,而且只要这个类没有保留调试信息的方式编译,那么就不可能。所以建议你放弃这个想法。
,Java 里……
System.out.println("a");
else if (b == "world")
System.out.println("b");这就当玩吧,不知能达到楼主的目的不?
{
public hello()
{
System.out.println("hello");
}
}class world
{
public world()
{
System.out.println("world");
}
}
String a;
String b;
Test(String a, String b) {
this.a = a;
this.b = b;
}; public static void main(String[] args) {
Test t = new Test("Hello", "World");
Field[] fields = t.getClass().getDeclaredFields();
for (Field f : fields) {
try {
if (f.get(t).equals("Hello")) {
System.out.println(f.getName());
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if (f.get(t).equals("World")) {
System.out.println(f.getName());
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}输出
a
b这个意思?
String a;
String b;
Test(String a, String b) {
this.a = a;
this.b = b;
};
void func(String param) {
Field[] fields = getClass().getDeclaredFields();
for (Field f : fields) {
try {
if (f.get(this).equals(param)) {
System.out.println(f.getName());
return;
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("null");
} public static void main(String[] args) {
Test t = new Test("Hello", "World");
t.func("World");
}
}
修改了下,封装成lz说的func接口了
// 3 5:ldc1 #2 <String "ddddd">
// 4 7:putfield #3 <Field String oj>
上面的oj是类变量的名称,他是给用户保留的,你再去看看局域变量,根本无法获得
如果你真的非常需要这个功能,那么也并非没有办法(前提是这个类保留了调试信息编译的)使用proguard这个项目中的一些类可以帮助你读取相关的信息
我还是那句话,建议你放弃这个想法。实在不是很有意思的东西,而且涉及到JVM底层的指令了。引用proguard.jar(我用4.2版本的,其它版本应该差不多)package chdw;import java.io.DataInputStream;import proguard.classfile.ProgramClass;
import proguard.classfile.ProgramMethod;
import proguard.classfile.attribute.Attribute;
import proguard.classfile.attribute.CodeAttribute;
import proguard.classfile.attribute.LineNumberTableAttribute;
import proguard.classfile.attribute.LocalVariableInfo;
import proguard.classfile.attribute.LocalVariableTableAttribute;
import proguard.classfile.constant.MethodrefConstant;
import proguard.classfile.constant.Utf8Constant;
import proguard.classfile.instruction.ConstantInstruction;
import proguard.classfile.instruction.Instruction;
import proguard.classfile.instruction.InstructionFactory;
import proguard.classfile.instruction.VariableInstruction;
import proguard.classfile.io.ProgramClassReader;public class TestName {
public static String getName(String name) throws Exception {
String callerClzName = new Exception().getStackTrace()[1].getClassName();
String callerMethodName = new Exception().getStackTrace()[1].getMethodName();
int callerLineNumber = new Exception().getStackTrace()[1].getLineNumber();
Class<?> callerClz = Class.forName(callerClzName);
ProgramClassReader r = new ProgramClassReader(new DataInputStream(callerClz.getResourceAsStream("/" + callerClzName.replace('.', '/') + ".class")));
ProgramClass clz = new ProgramClass();
r.visitProgramClass(clz);
for(ProgramMethod m : clz.methods) {
if(m == null)
continue;
if(callerMethodName.equals(m.getName(clz))) {
String lineNumRange = m.getLineNumberRange(clz);
int index = lineNumRange.indexOf(':');
int start = Integer.parseInt(lineNumRange.substring(0, index));
int end = Integer.parseInt(lineNumRange.substring(index + 1));
if(callerLineNumber >= start && callerLineNumber <= end) {
for(Attribute attr : m.attributes) {
if(attr instanceof CodeAttribute) {
CodeAttribute code = (CodeAttribute) attr;
LineNumberTableAttribute lineNumberTable = (LineNumberTableAttribute) code.getAttribute(clz, "LineNumberTable");
for(int i = 0; i < lineNumberTable.u2lineNumberTableLength; i++) {
if(lineNumberTable.lineNumberTable[i].u2lineNumber == callerLineNumber) {
int codeEnd = (i < lineNumberTable.u2lineNumberTableLength - 1) ? lineNumberTable.lineNumberTable[i + 1].u2startPC : code.code.length;
Instruction prev = null;
for(int z = 0; z < codeEnd;) {
Instruction instruction = InstructionFactory.create(code.code, z);
if(lineNumberTable.getLineNumber(z) == callerLineNumber
&& instruction.getName().equals("invokestatic")) {
ConstantInstruction invokeStatic = (ConstantInstruction) instruction;
MethodrefConstant method = (MethodrefConstant) clz.constantPool[invokeStatic.constantIndex];
if(method.getName(clz).equals("getName") && method.getClassName(clz).replace('/', '.').equals(TestName.class.getName())) {
VariableInstruction var = (VariableInstruction) prev;
for(Attribute at : code.attributes) {
if(at instanceof LocalVariableTableAttribute) {
LocalVariableTableAttribute varTable = (LocalVariableTableAttribute) at;
LocalVariableInfo varInfo = varTable.localVariableTable[var.variableIndex];
Utf8Constant varName = (Utf8Constant) clz.constantPool[varInfo.u2nameIndex];
return varName.getString();
}
}
}
}
z += instruction.length(z);
prev = instruction;
}
}
}
}
}
}
}
}
return null;
}
}package chdw;
public class Test {
public static void main(String[] args) throws Exception {
String xyz = "aa";
String zyx = "aa";
System.out.println(TestName.getName(xyz));
System.out.println(TestName.getName(zyx));
}
}
最后可以输出
xyz
zyx