Reputation: 848
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.
Upvotes: 2
Views: 929
Reputation: 5570
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
Upvotes: 0
Reputation: 1601
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);
Upvotes: 0
Reputation: 500853
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.
Upvotes: 1
Reputation: 20091
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
.
Upvotes: 0
Reputation: 3189
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.
Upvotes: 2