java - Java 编译时参数分配是否损坏?

标签 java parameters overloading dispatch method-dispatch

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

考虑这个简单的例子:

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

    void bar(Map<String, Object> map) { //do something else }
}

和调用代码:

Foo foo = new Foo();
HashMap<String, T> map = createSomeHashMap(); //wil generate HashMap
foo.bar(map);

到底为什么 Java 认为调用 bar(Object... objects) 是最合适的? ? 因为我在编译时有一个 map ,所以一切都应该可以工作!为什么我必须明确地向下转换它,如 foo.bar((Map<String, Object>)map); ??

最佳答案

我尝试了下面的这个程序,但出现错误 Type mismatch: T cannot be converted to Object :

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

所以我猜是泛型把你搞乱了。将参数类型从 Object 更改为至? ,这对我有用。

private void bar( HashMap<String, ?> 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

您可以看到,在本例中,已经做出了 Map 的决定。参数不合适,第 25 行的 invokevirtual 字节代码需要 Object...调用的版本。这是在编译时完成的,而不是运行时。

如果我将代码更改回我的建议(使用 Map<String,?> ),则调用虚拟字节代码会要求提供 Map 参数。您的版本也可以工作,因为强制转换强制编译器为 Map 发出 invokevirtual,而不是 Object...它通常会解析为。

关于java - Java 编译时参数分配是否损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24917787/

相关文章:

arrays - 将多维数组传递给函数

c# - C# 中的多态性和静态方法重载。

java - 重写和重载之间的区别?

java - 为什么我无法获取所有页面

java - 没有 Thread.sleep 的异步测试

java - WSO2 ESB 无法更新配置

c++ - 如何使用 '=' 将一个类的对象复制到同一类的另一个对象

java - 如何从非 ui Widget 线程发布 toast

azure - 如何在 Azure 数据工厂中的相对 URL 中使用动态内容

javascript - 将参数和默认值动态绑定(bind)到 Javascript 中的现有函数