-1

I have a raw type Map to store data because the data type could be different. Unfortunately it always returns value as Object type even we can get the exact type with getClass().

How to get specific type value from raw type Map?

/*
Expected result:
class java.lang.Boolean
func1(boolean p)
class java.lang.Integer
func1(int p)
class java.lang.Double
func1(double p)
class java.lang.Character
func1(char p)
class java.lang.String
func1(String p)
class java.lang.Object
func1(Object p)
class java.lang.Boolean
func1(boolean p)
class java.lang.Integer
func1(int p)
class java.lang.Double
func1(double p)
class java.lang.Character
func1(char p)
class java.lang.String
func1(String p)
class java.util.LinkedList
func1(List p)
class java.util.LinkedHashMap
func1(Map p)
class [Ljava.lang.Object;
func1(Object[] p)

Actual result:
class java.lang.Boolean
func1(Object p)
class java.lang.Integer
func1(Object p)
class java.lang.Double
func1(Object p)
class java.lang.Character
func1(Object p)
class java.lang.String
func1(Object p)
class java.lang.Object
func1(Object p)
class java.lang.Boolean
func1(Object p)
class java.lang.Integer
func1(Object p)
class java.lang.Double
func1(Object p)
class java.lang.Character
func1(Object p)
class java.lang.String
func1(Object p)
class java.util.LinkedList
func1(Object p)
class java.util.LinkedHashMap
func1(Object p)
class [Ljava.lang.Object;
func1(Object p)
*/

import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map map = init();

        for (Object v_obj : map.keySet()) {
            println(v_obj + ":\t" + map.get(v_obj).getClass());
            func1(map.get(v_obj));
        }
    }

    public static void func1(boolean p) {
        println("func1(boolean p)");
    }

    public static void func1(int p) {
        println("func1(int p)");
    }

    public static void func1(double p) {
        println("func1(double p)");
    }

    public static void func1(char p) {
        println("func1(char p)");
    }

    public static void func1(String p) {
        println("func1(String p)");
    }

    public static void func1(Object p) {
        println("func1(Object p)");
    }

    public static void func1(List p) {
        println("func1(List p)");
    }

    public static void func1(Map p) {
        println("func1(Map p)");
    }

    public static void func1(Object[] p) {
        println("func1(Object[] p)");
    }

    public static <T> void println(T p_t) {
        System.out.println(p_t);
    }

    public static Map init() {
        Map map = new LinkedHashMap();
        //map.put("null", null);
        map.put("boolean", true);
        map.put("int", 123);
        map.put("double", 123.456);
        map.put("char", 'c');
        map.put("string", "123asd'\"/\\");

        map.put("Object", new Object());
        map.put("Boolean", new Boolean(true));
        map.put("Integer", new Integer(123));
        map.put("Double", new Double(123.456));
        map.put("Character", new Character('c'));
        map.put("String", new String("123asd'\"/\\"));
        map.put("List", new LinkedList());
        map.put("Map", new LinkedHashMap());

        map.put("Object[]", new Object[]{});

        return map;
    }

}
XYZ
  • 41
  • 4

1 Answers1

1

The first thing to understand is that generics are a compile time concept. There's nothing dynamic (runtime) about them.

The next thing to understand is that methods are bound at compile time based on the parameter types and the type of the arguments provided. So which of

public static void func1(boolean p) {
    println("func1(boolean p)");
}

public static void func1(int p) {
    println("func1(int p)");
}
// and more

is bound depends on the actual type argument used in the invocation. You're using

for (Object v_obj : map.values()) {
    println(v_obj.getClass());
    func1(v_obj.getClass().cast(v_obj));
}

So what does

v_obj.getClass().cast(v_obj)

return? The javadoc of Object#getClass() states

The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called.

The expression on which getClass is called is v_obj, which is of type Object. So

v_obj.getClass()

returns a value of type Class<? extends Object>. The Class#cast(Object) uses the type value bound to the type parameter T as its return value. In this case that is also Object. So the method bound for an argument of type Object is the method with a parameter of type Object.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724