11
String activityState = "resume";
DebugLog(activityState)

void DebugLog(String obj1) {}

How to make the DebugLog to print like this:

activityState : resume

I used to write many print statement as logs at many places while debugging. I will write statements like

System.out.println("activityState : " + activityState);

I want a method to print the variable name and variable value. In C++, it can be done like the below:

#define dbg(x) cout<< #x <<" --> " << x << endl ;

Is there any way to do this?

Thanks in advance.

clemens
  • 16,716
  • 11
  • 50
  • 65
Navin GV
  • 700
  • 3
  • 10
  • 24
  • 2
    Not possible to get the variable name unless you use reflection. Do you want to ? – Suresh Atta Aug 01 '14 at 09:26
  • 5
    @sᴜʀᴇsʜᴀᴛᴛᴀ: Are you implying this *can* be done with reflection? – NPE Aug 01 '14 at 09:27
  • @NPE I'm opposed to use reflection :) Just telling the fact. – Suresh Atta Aug 01 '14 at 09:28
  • To get the field for a member variable using reflection you have to know its name, or you have to get them all. btw there is nothing wrong with reflection all modern frameworks use it extensively... – A4L Aug 01 '14 at 09:28
  • 1
    You can't do anything more elegant than `DebugLog("activityState", activityState)`. You *could* use reflection to convert "activityState" to activityState but you'd still have to pass a context parameter to tell your function whether activityState is a field etc. So a one-argument version does not exist. So best keep it simple! – Bathsheba Aug 01 '14 at 09:32
  • Completely off topic, and I'm not sure what the etiquette is with talking about points not related to the question, but it is generally considered good practise for methods to start with lowercase letter as opposed to uppercase. ie: `debugLog(String obj1)` instead of `DebugLog(String obj1)` – Ben Green Aug 01 '14 at 09:42
  • possible duplicate of [Java print string C++ equivalent](http://stackoverflow.com/questions/23738010/java-print-string-c-equivalent) – Dmitry Ginzburg Aug 01 '14 at 09:51
  • or http://stackoverflow.com/questions/744226/java-reflection-how-to-get-the-name-of-a-variable – Dmitry Ginzburg Aug 01 '14 at 09:51

3 Answers3

3

There's no direct solution to get the variable name.

However, in a context where you have many fields and don't want to manually print their state, you can use reflection.

Here's a quick example:

class MyPojo {
    public static void main(String[] args) {
        System.out.println(new MyPojo());
    }

    int i = 1;
    String s = "foo";

    @Override
    public String toString() {
        StringBuilder result = new StringBuilder();
        for (Field f: getClass().getDeclaredFields()) {
            try {
            result
            .append(f.getName())
            .append(" : ")
            .append(f.get(this))
            .append(System.getProperty("line.separator"));
            }
            catch (IllegalStateException ise) {
                result
                .append(f.getName())
                .append(" : ")
                .append("[cannot retrieve value]")
                .append(System.getProperty("line.separator"));
            }
            // nope
            catch (IllegalAccessException iae) {}
        }
        return result.toString();
    }
}

Output

i : 1
s : foo
Mena
  • 47,782
  • 11
  • 87
  • 106
2

You can use java Reflection to get the variable name and the value. Here's an example code;

public class Example{

  String activityState = "resume";

  public static void main(String[] args) {

       Example example = new Example();
       Class<?> c = example.getClass();
       Field field = c.getDeclaredField("activityState");
       System.out.println(field.getName());
       System.out.println(field.get(example));
  }    

}
Manorama
  • 69
  • 4
1

Since this is for debugging you could use instrumentation with aspectj, your code remains clean from the the debugging output statements and you can waeve the aspect as needed.

Define a set(FieldPattern) point cut to catch all field assignements (join points)

public aspect TestAssignmentAspect {

    pointcut assigmentPointCut() : set(* *);

    after() : assigmentPointCut() {
        System.out.printf("%s = %s%n", thisJoinPoint.getSignature().getName(),
                String.valueOf(Arrays.toString(thisJoinPoint.getArgs())));
    }
}

Here is Test class

public class Test {

    public static String activityState = "stopped";

    public static void main(String[] args) {
        activityState = "start";

        doSomething();

        activityState = "pause";

        doSomeOtherthing();

        activityState = "resume";

        System.out.printf("the end!%n");
    }

    private static void doSomeOtherthing() {
        System.out.printf("doing some other thing...%n");
    }

    private static void doSomething() {
        System.out.printf("doing something...%n");
    }
}

If you run this example with the aspect weaved the output will be

activityState = [stopped]
activityState = [start]
doing something...
activityState = [pause]
doing some other thing...
activityState = [resume]
the end!

Explanation

pointcut assigmentPointCut() : set(* *);

set point cut to catch assignments, the point joins, to any variable with any name, could also in the example be

pointcut assigmentPointCut() : set(String activityState);

The advice, the desired behavior when the given point cut matches

after() : assigmentPointCut() { ... }

Informations about the point join can be accessed using the special reference thisJoinPoint.

A4L
  • 17,353
  • 6
  • 49
  • 70