10

According to: http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html
4.5.2 Variables of Reference Type
A reference type can hold a null reference.

Is it possible to retrieve the declared type of the reference type when the assigned value is null?

Specifically, in a method that uses reflection, I wish the method to be null-safe and act on the original declared type (though I know the following code snippet doesn't work), for instance:

String referenceType = null;
MyReflectionClass.reflectionMethod(referenceType);
...
public static void reflectionMethod(Object referenceType) {
   Class<?> declaredType = referenceType.getClass();
}

I would not be averse to using generics to have type T instead of Object as the declared parameter type, if necessary.

Edit: I know that .getClass() works on the instance, not the declared type. I was wondering if it was possible to ask the reference for it's declared type. Since class hierarchies are static, there should be no problem to get that information.

Edit2: Here, the situation is made clear: Is Java "pass-by-reference" or "pass-by-value"?
Java is only pass-by-value, so even though a reference type is used, it is always handled as if the value (object instance) is passed (even though the internals only pass an object pointer). This means that Java doesn't actually have a reference type that knows about it's type (at least as far as the programmer is concerned), it's all in the value instances.
Therefore it is impossible to determine the type of any null value.

Community
  • 1
  • 1
Alan Escreet
  • 3,499
  • 2
  • 22
  • 19
  • 1
    @Edit2: It is wrong to say that the object instance is passed by value. What happens is that the reference is passed by value. – brain Apr 19 '11 at 10:11
  • @brain But Java handles any reference (call) to the reference as the value. If this was not the case, then a null Object would still be an Object reference. It is not. http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1 states "The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object." Article http://javadude.com/articles/passbyvalue.htm in the linked stackoverflow question explains this very well. – Alan Escreet Apr 19 '11 at 12:40

5 Answers5

8

In a single word, no. It doesn't make a whole lot of sense to try to find the members of a null reference, though, since null implies the absence of anything. You're probably better off just dis-allowing null as an input, probably by throwing a NullPointerException.

If you must handle null, perhaps the best way is to explicitly pass the class reference (or even better, a direct reference to the method in question).

public static void reflectionMethod(Object param, Class<?> referenceType) // null is dis-allowed for referenceType
{
    // ... no need to try to back-track the type from an object
}

If you can only ever get the null value, it's difficult (impossible unless there are other constraints imposed) to do much better than having a very lucky guess.

helloworld922
  • 10,801
  • 5
  • 48
  • 85
  • In this case, I'm trying to figure out which method to call: `Class.getMethod(String, Class>...)` where a `null` parameter value for the call to the target method may be valid. So here, there is a sense to doing it. – Alan Escreet Apr 19 '11 at 07:58
  • if you can, pass the class reference directly rather than trying to back-track the object type from just the object (see updated answer) – helloworld922 Apr 19 '11 at 08:30
7

You misunderstand. getClass() doesn't tell you the declared type of the variable, it tells you the type of the object, if there is one. And let's stop and take a step back for a minute - which variable would you be referring to, if it did that? The original variable? The method parameter? Any other variable that it passed through along the way? That would be total madness.

Robin Green
  • 32,079
  • 16
  • 104
  • 187
3

You can't find the declared type of a null reference. Generics can't really help either, as they're erased at compile time. Some way or another you'll have to pass the type at runtime if you need to know it for the null case.

WhiteFang34
  • 70,765
  • 18
  • 106
  • 111
0

No it is not. In your example you will get a null pointer exception when trying to call a method on the null reference referenceType.

More specifically it is not possible because the concrete type is not neccesarily known at compile time, e.g. if I declare a reference of type Object and assign it to a String then your method should discover that the object is a String not an Object.

Object referenceType= new String("I'm a string");
MyReflectionClass.reflectionMethod(referenceType);
...
public static void reflectionMethod(Object referenceType) {
   Class<?> declaredType = referenceType.getClass(); // returns String.class
}
brain
  • 5,496
  • 1
  • 26
  • 29
  • At run-time, the reference type should still know that it's a `String`, otherwise it would be indistinguishable from a value type. – Alan Escreet Apr 19 '11 at 08:12
  • @leet3lite: the String object knows that it is a string but the Object reference doenst know that the object it refers to is a String. It just references any Object. So without an object (a NULL reference) you can't tell it's type. – brain Apr 19 '11 at 09:32
  • As a reference type, I would expect it to still know it's a String, but for polymorphism to kick in and allow it to be referenced as an Object, however, this appears not to be true (see 2nd edit). – Alan Escreet Apr 19 '11 at 09:48
  • @leet3lite: It was a reference to a String but once you pass it in it's a reference to an Object. – brain Apr 19 '11 at 10:18
  • A String is-an Object. Although the available interface is reduced to that available by Object, it is still a String. – Alan Escreet Apr 19 '11 at 12:43
0

I am not sure this is helpful in your context, but you can use generics for achieving something similar - Java 1.5+ keeps type information for the subclass.

package spikes;

import java.lang.reflect.ParameterizedType;

public class ReflectMethod {
    public abstract static class GenericType<T> {
        public Class typedClass() {
            ParameterizedType pType = (ParameterizedType) getClass().getGenericSuperclass();
            return (Class) pType.getActualTypeArguments()[0];
        }

        public void reflectMethod(T o) {
            System.out.println("Class: " + typedClass());
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        GenericType<String> gs = new GenericType<String>() {

        };
        gs.reflectMethod("");
    }
}
Dakshinamurthy Karra
  • 5,353
  • 1
  • 17
  • 28
  • 1
    That doesn't work for nulls, which is what is being asked here. – Robin Green Apr 19 '11 at 08:00
  • It will work for null. Note that the argument is *not* used for accessing the type. – Dakshinamurthy Karra Apr 19 '11 at 08:09
  • Unfortunately this doesn't even work for non-null values. The point is that I'm trying to get the type of the reference type dynamically. This only works if you can statically instantiate the type in the generic `<...>` brackets. If I could do that, then I could also statically set the type in the parameter list. – Alan Escreet Apr 19 '11 at 08:34
  • Agree. This will not work if you do not know the type of variable at the time of method invocation. – Dakshinamurthy Karra Apr 19 '11 at 09:02