Is it possible to get the type of an uninstantiate

2019-06-28 06:02发布

问题:

Is it possible to get the type of a variable that is declared (but not instantiated) in Java? for example:

public class Foo {

     FooTwo foo2;
     FooTwo foo3;
     FooThree foo4;

     public static void main(String[] args) {
         if (foo2.getClass() == foo3.getClass()) {
             System.out.println("foo2 is the same type as foo3");
         }
         if (foo3.getClass() == foo4.getClass()) {
             System.out.println("foo3 is the same class as foo4");
         }
     }
}

With output:

foo2 is the same type as foo3

obviously the method getClass() does not work on an uninstantiated variable, so this code does not function. I am assuming that the information I am looking for is stored somewhere in the variable (pointer?) for type safety, and that it may be accessible. Is it possible to Achieve this comparison?

the reason: I have a class with several declared variables. These variables are supposed to point to objects stored in an ArrayList in another class. I am trying to create a method that will take an initialized (but uninstantiated) variable as a parameter, scan the arraylist for an object matching the type of the initialized variable, and set the variable to the object (Make the variable point to the object).

ALSO: The point of the system is to remove coupling in the constructor of the class. The objects cannot be instantiated immediately or in the constructor.

回答1:

To start with, you need to be aware of the difference between the type of an expression and the runtime-type of a value. Consider, for example, the following code:

List<String> list = new ArrayList<String>();
System.out.println(list.getClass());

The above code prints class java.util.ArrayList, not java.util.List<java.lang.String>, because getClass() returns the runtime-type of the object that list refers to, not the type of list itself.

So it doesn't make sense to call getClass() on an uninitialized variable, because there's no value for it to return the runtime-type of.


I am trying to create a method that will that will take an initialized (but uninstantiated) variable as a parameter, […] and set the variable to the object (Make the variable point to the object).

Since Java is a pass-by-value language, it doesn't expose a way to modify a variable that is passed in as a parameter. For example, consider this method:

public void doNothing(Object obj) {
    obj = "obj";
}

The above method does absolutely nothing. It has a local variable obj, which originally contains whatever reference is passed in, and then is changed to refer to the string "obj" instead; but this change has no effect, because nothing actually uses the local variable obj after that point. In particular, this method does not have any effect on whatever reference was passed in.

The closest you can get is to use reflection; if your method takes an instance of type Field, it can both examine the declared type of the field, and set the field to a value of its choosing.



回答2:

You can do something similar using reflection. Here is an example code snippet. But may be there is a better way to solve your problem if you explain your use case in a bit more in detail.

import java.lang.reflect.Field;

public class Foo {

    static FooTwo foo2;
    static FooTwo foo3;
    static FooThree foo4;

    public static void main(String[] args)  {

        try {
            Field foo2Field = Foo.class.getDeclaredField("foo2");
            Field foo3Field = Foo.class.getDeclaredField("foo3");
            Field foo4Field = Foo.class.getDeclaredField("foo4");

            if (foo2Field.getType().equals(foo2Field.getType())) {
                System.out.println("foo2 is the same type as foo3");
            }
            if (foo3Field.getType().equals(foo4Field.getType())) {
                System.out.println("foo3 is the same class as foo4");
            }

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            // TODO handle this if this can happen
        } catch (SecurityException e) {
            e.printStackTrace();
            // TODO handle this appropriately
        }

    }

}

class FooTwo {

}

class FooThree {

}