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
17.9k12 gold badges52 silver badges71 bronze badges
asked Aug 1, 2014 at 9:25
8
  • 2
    Not possible to get the variable name unless you use reflection. Do you want to ? Commented Aug 1, 2014 at 9:26
  • 5
    @sᴜʀᴇsʜᴀᴛᴛᴀ: Are you implying this can be done with reflection? Commented Aug 1, 2014 at 9:27
  • @NPE I'm opposed to use reflection :) Just telling the fact. Commented Aug 1, 2014 at 9: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... Commented Aug 1, 2014 at 9: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! Commented Aug 1, 2014 at 9:32

3 Answers 3

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
answered Aug 1, 2014 at 9:45
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));
 } 
}
answered Aug 1, 2014 at 10:03
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.

answered Aug 1, 2014 at 10:26
1
  • 1
    Nobody upvoted this back when the question was first asked but I like this solution! Commented Oct 30, 2018 at 17:40

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.