20

I have a Java function called testForNull

   public static void testForNull(Object obj)
    {
     if (obj == null)
      {
        System.out.println("Object is null");
      }
    }

I use it to test multiple objects to ensure they are not null. But, I am unable to tell the name of the variable that way.

For eg. if I say

    testForNull(x);
    testForNull(y);
    testForNull(z);

I cannot tell which of the three lines caused the "Object is null" output. Of course, I can simply add another parameter to the function and have something like

    testForNull(x, "x");
    testForNull(y, "y");
    testForNull(z, "z");

But I want to know whether it is possible to deduce the name of the variable without passing it explicitly. Thanks.

Vincent Cantin
  • 16,192
  • 2
  • 35
  • 57
CodeBlue
  • 14,631
  • 33
  • 94
  • 132
  • Not even with [reflection](http://stackoverflow.com/questions/744226/java-reflection-how-to-get-the-name-of-a-variable). – calebds Apr 02 '12 at 22:15
  • 2
    There is nothing in the language to account for this. However, I imagine it could be done with an additional processing tool (e.g. inspect/modify bytecode). Alternatively, use a tool that can insert the appropriate templates auto-filled with matching values ;-) –  Apr 02 '12 at 22:16
  • 3
    your statement 'I cannot tell which of the three lines caused the "Object is null" output.' is only true in your output. You could use new Exception("object is null").printStackTrace to find out exactly where it was, or you could use a debugger and put a breakpoint there. This looks more like something that calls for better logging, or a debugger, instead of a language feature. – John Gardner Apr 02 '12 at 22:35
  • 3
    `testForNull(new Object()); // I have NO name!` – Andrew Thompson Apr 02 '12 at 22:36
  • (1) If you throw an exception, the stack trace would have the line number. (2) In the spirit of throwing an exception, you could use (or implement yourself) [`Preconditions.checkNotNull`](http://guava-libraries.googlecode.com/svn/tags/release03/javadoc/com/google/common/base/Preconditions.html#checkNotNull(T)) from Google's Guava libraries. `Preconditions.checkNotNull(x);` will throw a NullPointerException when `x` is `null`. You can use the variant that takes a string to make it easy to see which variable failed. `Preconditions.checkNotNull(x, "x");`. Of course, exceptions fail fast. – Tom Apr 03 '12 at 00:35

7 Answers7

17

Consider that the parameter might not have been a variable (and therefore wouldn't have a name):

testForNull(x != y);
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
5

No, there is no such a way. You will have to explicitly pass the name of the variable. However, if your object has a field 'name' or displays its name via the toString() function, then that might help you.

Vincent Cantin
  • 16,192
  • 2
  • 35
  • 57
  • 11
    An object is unlikely to display its name via toString() if it's null ;-) – Don Roby Apr 02 '12 at 22:23
  • True. However, `testForNull()` (which tests for null) will know if it should display `null` or call the object's `toString()`. – Vincent Cantin Apr 02 '12 at 22:26
  • @DonRoby is right. The toString() method won't help me if the object is null. It would therefore defeat my purpose of finding out which object was null. – CodeBlue Apr 02 '12 at 22:58
2

Yes, but I wouldn't recommend it and it would be exceptionally hard. Try assert instead:

http://docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html

To do what you want, if you have the source code, get the current thread http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#currentThread()

Get a stack trace http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#getStackTrace()

Get the 2nd to last element, the class name, file name, and line number, then print that line, or parse it http://docs.oracle.com/javase/7/docs/api/java/lang/StackTraceElement.html#method_summary

Chloe
  • 25,162
  • 40
  • 190
  • 357
1

This is what a debugger is for. There is no way to do this programmatically. What if I invoke testForNull(1 + 1). What is the variable name then?

Eclipse has a graphical and easy-to-use debugger for Java built-in. Learning how to use that will pay dividends in the long run, and happens to be the immediate solution to your problem as well.

Travis Webb
  • 14,688
  • 7
  • 55
  • 109
  • 1
    Excuse me. "Programmatically" as in "via reflection". And since we're being pedantic, "debuggers **are programs**". – Travis Webb Apr 02 '12 at 22:18
  • Touché. However, [this](http://stackoverflow.com/a/744341/758280) answer links to a bytecode analysis framework that could be used by Java to inspect itself at runtime. – Jeffrey Apr 02 '12 at 22:21
  • Interesting. Thanks for the link. – Travis Webb Apr 02 '12 at 22:23
0

Bah, After looking at the original question again, this is a non-starter.

The question asks us to be able to provide a means by which a value passed into a CheckForNull() method can retrieve the values name - and here's the kicker... only when the value is null.

There is absolutely no way you are going to get anything from a null value other than a String containing "null" or a NullPointerException.

But, as usual, object orientation to the rescue. Create a value class like I mentioned above. Now add an isNull() method to it. Use this value class for any value you are wanting to dump debugging text for.

0

you could place the method call in a foreach and set a reference ID for each object that you are going through, even if it returns null or not null for that specific object.

Ben Sewards
  • 2,571
  • 2
  • 25
  • 43
-2

Java is an object oriented language, therefore the answer is "most definitely!" you can tell the name of the variable passed as a parameter. To do so, try this...

class Value<T> extends Object
{
    T value;
    String name;

    public Value(String name, T value)
    {
        this.name = name;
        this.value = value;
    }
}

Now in your methods, you would accept all parameters as instances of Value, as in the following method which would accept only Values created with classes having Number as a base class (which would be Long, Float, Double, etc)...

public String SomeMethodWantingToKnowParameterNames(Value<? extends Number> parm1)
{
    if (parm1 != null)
    {
        // Do your work with the parameter - it's name can be accessed via parm1.name
        // This is only an example
        // You would probably want to write an accessor for name
        return parm1.name;
    }

    // Return null for null
    return null;
}

And that is all there is to it! I use a generic class so that Value can be used to pass in any type - Floats, Longs, Double, BigInteger, String - for example...

Value<Float> vFloat = new Value<Float>("MyFloat", 0.0);

Also, the method above is simply an example - in practice any method accepting a Value could access its name.

Good Luck and may all your code compile flawlessly!

Rodney