2011-12-21 95 views
2

Java有没有什么方法可以在运行时获取编译时类型的引用?在运行时的编译时间类型

实施例:

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); 

第一呼叫 - >号

第二呼叫 - >对象

第三呼叫 - >整数

编辑:这是一个非常简单的问题的版本。我想要做的是检测(而不是被告知)内部框架元数据关于传递的对象。可能发生的情况是,该方法先用Integer调用,然后用Double调用,都声明为Number。

+1

'getClass()'?也许检查一下API。 – 2011-12-21 17:03:34

+1

@Dave牛顿将返回整数不是数字。 – Stefan 2011-12-21 17:03:55

+2

这是不可能的。 – SLaks 2011-12-21 17:05:16

回答

2

我看到的唯一方法是使用过载。但是你需要为继承关系的每个类指定一个重叠方法来排除子类。

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. 
+0

我担心我不得不使用重载,但我可能能够限制类型,然后生成代码。 – Stefan 2011-12-21 17:21:19

+0

毕竟这可能不是那么糟糕。我可以为受支持的数据类型创建接口,然后使用代理/处理程序将元数据处理代码放入其中。客户甚至可以创建自己的接口,通用的InvocationHandler仍然可以工作。 – Stefan 2011-12-21 17:47:53

1

很简单,你不能。

您已经知道函数参数的编译时间(Object),您可以找到传入的对象的运行时类型(使用getClass())。但是,没有办法获得您要求的信息。

0

使用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); 
+0

返回整数而不是数字。 – Stefan 2011-12-21 17:11:06

+0

@Stefan,看到我的答案 - 你不能拥有Number的实例,因为Number是一个抽象类。 – Paul 2011-12-21 17:14:49

+0

@Paul看我的编辑 – Stefan 2011-12-21 17:18:46

0

你可以使用 '的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); 
    } 
} 

打印出

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

Anoth呃选项是递归查询超

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()); 
    } 
} 

打印出

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 
+0

请参阅编辑。我不知道什么对象正在通过。我试图'检测'编译时间类型。 – Stefan 2011-12-21 17:19:41

+0

在这种情况下,我会推荐方法重载并查看实际调用哪个方法。 – 2011-12-21 18:09:52

+0

我将尝试重载。 – Stefan 2011-12-21 18:17:07

0

你不能。 Integer是正确的答案,因为Number是一个抽象类,您不能拥有抽象类的实例,并且您依靠自动装箱来转换基元int

+0

它的抽象无关紧要。我试图获得编译时的类型,这实际上是数字。请参阅编辑。 – Stefan 2011-12-21 17:16:26

+0

你不能有一个实例,但你可以有一个参考;那就是 - 一切就是这样。 – 2011-12-21 17:25:47

+0

@DaveNewton,一个实例是一个参考。在Java中,将实例传递给另一个方法只是传递引用(通过值传递)。 – Paul 2011-12-21 17:55:13