compile time type at runtime

眉间皱痕 提交于 2019-12-11 02:47:10

问题


Is there any way in Java to get the compile time type of a reference at runtime?

Example:

private void doSomething(final Object o)
{
   // do somthing
}

final Number n = 1; 
doSomething(n);

final Object o = 1; 
doSomething(o);

final Integer i = 1; 
doSomething(i);

1st call --> Number

2nd call --> Object

3rd call --> Integer

Edit: This is a very simplified version of the problem. What i am trying to do is to detect(instead of being told) inside a framework metadata about objects being passed. What could happen is, that the method gets first called with an Integer and then with a Double, both declared as Number.


回答1:


The only way I see is to use overloading. But you would need to specify a overlading method for each class of the inheritance relation to exclude sub classes.

private void doSomething(final Object o)
{
   // do something
}

private void doSomething(final Number n)
{
   // do something
}

private void doSomething(final Integer i)
{
   // do something
}

final Number n = 1;
doSomething(n); // doSomething(final Number) is called.



回答2:


Quite simply, you can't.

You already know the compile-time of the function argument (Object) and you can find out the run-time type of the object that's passed in (by using getClass()). However, there's no way to get the information you're asking for.




回答3:


You can't. Integer is the correct answer, because Number is an abstract class and you can't have an instance of an abstract class, and you relied on autoboxing to convert the primitive int.




回答4:


Use object.getClass()

private static void doSomething(final Object o) {
    System.out.println(o.getClass().getSuperclass());
}

private static <T extends Number> void doSomething(final T o) {
    System.out.println(o.getClass());
}


final Integer n = 2;
doSomething(n);

final Double n = 2D;
doSomething(n);



回答5:


you can use 'instanceof'

public class Test {
  private static void doSomething(final Object o){
    if(o instanceof Number){
      System.out.println("it's a number!");
    }
    System.out.println("canonical class : "+o.getClass().getCanonicalName());
  }
  public static void main(String[] args) {
    Number n = new Integer(10);
    doSomething(n);
  }
}

prints out

it's a number!
canonical class : java.lang.Integer

Another option is to recursively check superclasses

public class Test {
  private static Class<?> doSomething(final Object o){
    // assuming o is not null
    Class<?> klass = getSuperClass(o.getClass());
    return klass;
  }

  private static Class<?> getSuperClass(Class<?> klass){
    // if super class is object or null break recursion
    if(klass.getSuperclass() == null || klass.getSuperclass().equals(Object.class)){
      return klass;
    }
    // keep looking higher up 
    return getSuperClass(klass.getSuperclass());
  }

  public static void main(String[] args) {
    Number n = new Integer(10);
    System.out.println("n  is a "+doSomething(n).getCanonicalName());
    Object o = new Integer(10);
    System.out.println("o  is a "+doSomething(o).getCanonicalName());
    Number d = new Double(10.0d);
    System.out.println("d  is a "+doSomething(d).getCanonicalName());
    String s = "10";
    System.out.println("s  is a "+doSomething(s).getCanonicalName());
    Object so = "10";
    System.out.println("so is a "+doSomething(so).getCanonicalName());
  }
}

prints out

n  is a java.lang.Number
o  is a java.lang.Number
d  is a java.lang.Number
s  is a java.lang.String
so is a java.lang.String


来源:https://stackoverflow.com/questions/8593498/compile-time-type-at-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!