是这样的  我想写一个函数  例如  void func(String param)String  a = "hello";
String  b = "world";我把变量a 传进去  它能打印出变量名  "a"
我把变量b 传进去  它能打印出变量名  "b"以此类推   
不知道大家有没有什么办法  我网上查了一下  只找到一个用反射机制  输出对象中属性变量名的方法但是这种输出 传进来参数的变量名  能不能实现  怎么实现  望高手赐教能解决此问题者  立马送上50分

解决方案 »

  1.   

    不明白。你的意思是
    String a = "hello";
    String b = "world";func(a);
    func(b);这样会输出a和b?这个基本不太可能实现,因为a和b这个名字都可能在编译后没有了如果你非常非常需要这个东西,那么在保证这个类保持LocalVariable表的时候,再在你的实现中根据new Exception().getStackTrace()[1]得到行号,再访问这个类LineNumber表,再分析Class的指令,最后可以大致算出传入的名字是什么。
    但是这个非常非常非常非常复杂,而且只要这个类没有保留调试信息的方式编译,那么就不可能。所以建议你放弃这个想法。
      

  2.   

    在 C 语言里可以使用宏来实现:#define printString(x) printf("%s: %s\n", #x, x)
    ,Java 里……
      

  3.   

    if (a == "hello")
    System.out.println("a");
    else if (b == "world")
    System.out.println("b");这就当玩吧,不知能达到楼主的目的不?
      

  4.   

    想了想  其实根本 不可能  因为 如果你去看class文件  会发现 其中生成的字节码 ,你声明的变量 a已经不是以前的变量名,也就是说你声明的变量名只是写给自己看的!!jvm根本不会接受所以 你也无法获得你声明的变量名,获得也是jvm自己定义的变量名 希望能对你有所帮助
      

  5.   

    定义两个类,然后用反射去做,反射的代码我就不贴了,到处都是class hello
    {
    public hello()
    {
        System.out.println("hello");
    }
    }class world
    {
    public world()
    {
        System.out.println("world");
    }
    }
      

  6.   

    变量名称在编译以后就没有了,成员变量会变成指向堆内存的指针的偏移量,虚拟机通过对象指针偏移量获得成员变量数据。局部变量会变成方法栈空间中,方法的局部变量索引,虚拟机根据索引下标获得局部变量数据。因此变量名称只对开发者有意义,对虚拟机变量名称是没有意义的,所以编译以后就没有这些名称了。自然通过反射就无法获得,不错成员变量的变量名还是能够得到的,因为解析class文件的时候会用到成员变量名,但是局部变量是肯定没有的。
      

  7.   

    public class Test {
        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这个意思?
      

  8.   

    public class Test {
        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接口了
      

  9.   

    18楼、21楼正解某些人不要觉得编译后就没有名称只有地址了,先去理解一下什么是反射机制吧楼主看一下java.lang.Class类的API,它所提供的方法可以帮助你获得你想要的信息
      

  10.   

    自己好好看看  类变量的字节码 
    //    3    5:ldc1            #2   <String "ddddd">
        //    4    7:putfield        #3   <Field String oj>
    上面的oj是类变量的名称,他是给用户保留的,你再去看看局域变量,根本无法获得
      

  11.   

    我的回复已经说明了吧。这个信息在保留了调试信息的编译方式下,其实是可以获得的。只是非常复杂而且意义不是很大,建议你不要做。
    如果你真的非常需要这个功能,那么也并非没有办法(前提是这个类保留了调试信息编译的)使用proguard这个项目中的一些类可以帮助你读取相关的信息
      

  12.   

    以下是一段代码参考,我考虑不是很周全的。肯定在某些情况下不能正确判断出变量名的。
    我还是那句话,建议你放弃这个想法。实在不是很有意思的东西,而且涉及到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