Java编译时参数分派是否中断?

Java编译时参数分派是否中断?,java,parameters,overloading,dispatch,method-dispatch,Java,Parameters,Overloading,Dispatch,Method Dispatch,我已经知道Java根据编译时类型分派方法。然而,我有一个案例,我希望它能起作用,但事实并非如此 考虑这个简单的例子: class Foo{ void bar(Object... objects) { //do something } void bar(Map<String, Object> map) { //do something else } } class Foo{ 空栏(对象…对象){//do something} 空栏(映射){//执行其他操作} }

我已经知道Java根据编译时类型分派方法。然而,我有一个案例,我希望它能起作用,但事实并非如此

考虑这个简单的例子:

class Foo{ 
    void bar(Object... objects) { //do something }

    void bar(Map<String, Object> map) { //do something else }
}
class Foo{
空栏(对象…对象){//do something}
空栏(映射){//执行其他操作}
}
以及呼叫代码:

Foo foo = new Foo();
HashMap<String, T> map = createSomeHashMap(); //wil generate HashMap
foo.bar(map);
Foo-Foo=new-Foo();
HashMap=createSomeHashMap()//wil生成哈希映射
富吧(地图),;
为什么Java认为调用
bar(Object…objects)
最合适?
因为我在compileTime有一张地图,所以一切都应该正常!为什么我必须像
foo.bar((Map)Map)那样显式地向下转换它??

我在下面尝试了这个程序,结果发现eror
类型不匹配:T无法转换为对象

public class DispatchTest
{

   private void bar( HashMap<String, Object> map )
   {
   }

   public static void main( String[] args )
   {
      test();
   }

   private static <T> void test()
   {
      DispatchTest dt = new DispatchTest();
      HashMap<String,T> map = new HashMap<>();
      dt.bar( map );
   }
}
编辑:为了详细说明这一点,我将代码放回原处,并添加了一个方法,如您的示例中的
bar(Object…
)。以下是生成的Java字节码:

private static <T extends java/lang/Object> void test();
Code:
   0: new           #3                  // class quicktest/DispatchTest
   3: dup
   4: invokespecial #4                  // Method "<init>":()V
   7: astore_0
   8: new           #5                  // class java/util/HashMap
  11: dup
  12: invokespecial #6                  // Method java/util/HashMap."<init>":()V
  15: astore_1
  16: aload_0
  17: iconst_1
  18: anewarray     #7                  // class java/lang/Object
  21: dup
  22: iconst_0
  23: aload_1
  24: aastore
  25: invokevirtual #8                  // Method bar:([Ljava/lang/Object;)V

  28: return
私有静态无效测试();
代码:
0:新的#3//类快速测试/调度测试
3:dup
4:invokespecial#4//方法“”:()V
7:astore_0
8:new#5//类java/util/HashMap
11:dup
12:invokespecial#6//方法java/util/HashMap。”“:()V
15:astore_1
16:aload_0
17:iconst_1
18:anewarray#7//类java/lang/Object
21:dup
22:iconst_0
23:aload_1
24:aastore
25:invokevirtual#8//方法栏:([Ljava/lang/Object;)V
28:返回
您可以看到,在这种情况下,已经做出决定,
Map
参数不合适,第25行的invokevirtual字节码需要调用的
对象…
版本。这是在编译时完成的,而不是在运行时


如果我将代码更改回我的建议(使用
Map
),那么invokevirtual字节码将请求Map参数。您的版本也可以工作,因为强制转换强制编译器为Map而不是对象发出invokevirtual…它通常会解析为。

Java不会动态调度(在运行时)关于参数。方法签名的选择完全发生在编译过程中。不,选择不是“坏的”:它是由JLS定义的。他说的是“编译时类型”。;)我想他至少有一点是对的。@markspace完全正确!我甚至没有要求“运行时调度”!我觉得user28…甚至都不看我的问题,但只是主题(我承认我犯了一个错误)我无法更改
Foo
类的方法,因为它属于我使用的API(ElasticSearch)。我甚至不想有一个工作解决方案(通过强制转换解决),但只对它不起作用感兴趣。我觉得它不可能是泛型的,因为它们被删除了。你甚至不允许在同一个类中编写两个这样的方法:
void bar(列表字符串)
void bar(列表整数)
,因为java在运行时是一样的:
void bar(列表列表)
。你甚至不被允许编译你的程序(至少在eclipse中是这样)。但我的程序是编译的!@Rafael t:是的,泛型在运行时被删除,但是调用哪个方法的决定是在编译时做出的。因此,泛型会出现在它和第一个方法栏(对象…)中是由编译器调用的。非常感谢您提供的内部信息,但是我现在真的很困惑。但是,如果T(至少)是,它有意义吗对象?Java中的这些泛型太糟糕了……它们从来没有像预期的那样工作过!任何
T
都不是对象。泛型是。例如,类型与类型不匹配,因为保存对象的类型可能有数字或JButton,字符串是包含泛型的不同类型。
private static <T extends java/lang/Object> void test();
Code:
   0: new           #3                  // class quicktest/DispatchTest
   3: dup
   4: invokespecial #4                  // Method "<init>":()V
   7: astore_0
   8: new           #5                  // class java/util/HashMap
  11: dup
  12: invokespecial #6                  // Method java/util/HashMap."<init>":()V
  15: astore_1
  16: aload_0
  17: iconst_1
  18: anewarray     #7                  // class java/lang/Object
  21: dup
  22: iconst_0
  23: aload_1
  24: aastore
  25: invokevirtual #8                  // Method bar:([Ljava/lang/Object;)V

  28: return