Java 中的重载和多分派 [英] Overloading in Java and multiple dispatch

查看:21
本文介绍了Java 中的重载和多分派的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个集合(或列表或数组列表),我想在其中放置字符串值和双精度值.我决定让它成为一个对象集合并使用重载和多态,但我做错了.

I have a collection (or list or array list) in which I want to put both String values and double values. I decided to make it a collection of objects and using overloading ond polymorphism, but I did something wrong.

我进行了一个小测试:

public class OOP {
    void prova(Object o){
        System.out.println("object");
    }

    void prova(Integer i){
    System.out.println("integer");
    }

    void prova(String s){
        System.out.println("string");
    }

    void test(){
        Object o = new String("  ");
        this.prova(o); // Prints 'object'!!! Why?!?!?
    }

    public static void main(String[] args) {
        OOP oop = new OOP();
        oop.test(); // Prints 'object'!!! Why?!?!?
    }
}

在测试中似乎参数类型是在编译时决定的,而不是在运行时决定的.这是为什么?

In the test seems like the argument type is decided at compile time and not at runtime. Why is that?

这个问题与:

多态 vs 覆盖 vs 重载
尽量简单地描述多态

好的,要调用的方法是在编译时决定的.是否有避免使用 instanceof 运算符的解决方法?

Ok the method to be called is decided at compile time. Is there a workaround to avoid using the instanceof operator?

推荐答案

这篇文章秒了 voo 的回答,并提供了关于延迟绑定的详细信息/替代方案.

This post seconds voo's answer, and gives details about/alternatives to late binding.

一般JVM只使用single dispatch:运行时类型只考虑接收者对象;对于方法的参数,考虑静态类型.使用 方法表(类似于 C++ 的虚拟表).您可以找到详细信息,例如在 HotSpot Wiki 中.

General JVMs only use single dispatch: the runtime type is only considered for the receiver object; for the method's parameters, the static type is considered. An efficient implementation with optimizations is quite easy using method tables (which are similar to C++'s virtual tables). You can find details e.g. in the HotSpot Wiki.

如果你想要多次分派你的参数,看看

If you want multiple dispatch for your parameters, take a look at

  • groovy.但据我所知,它有一个过时的、缓慢的多分派实现(参见例如 这个性能比较),例如没有缓存.
  • clojure,但这与 Java 完全不同.
  • MultiJava,为 Java 提供多分派.此外,您可以使用
    • this.resend(...) 而不是 super(...) 调用封闭方法的最具体的覆盖方法;
    • 值调度(下面的代码示例).
    • groovy. But to my latest knowledge, that has an outdated, slow multiple dispatch implementation (see e.g. this performance comparison), e.g. without caching.
    • clojure, but that is quite different to Java.
    • MultiJava, which offers multiple dispatch for Java. Additionally, you can use
      • this.resend(...) instead of super(...) to invoke the most-specific overridden method of the enclosing method;
      • value dispatching (code example below).

      如果你想坚持使用Java,你可以

      • 通过在更细粒度的类层次结构上移动重载方法来重新设计您的应用程序.Josh Bloch 的 Effective Java,条目中给出了一个示例41(谨慎使用重载);
      • 使用一些设计模式,例如策略、访问者、观察者.这些通常可以解决与多分派相同的问题(即,在那些情况下,对于使用多分派的那些模式,您有一些简单的解决方案).
      • redesign your application by moving overloaded methods over a finer grained class hierarchy. An example is given in Josh Bloch's Effective Java, Item 41 (Use overloading judiciously);
      • use some design patterns, such as Strategy, Visitor, Observer. These can often solve the same problems as multiple dispatch (i.e. in those situations you have trivial solutions for those patterns using multiple dispatch).

      价值调度:

      class C {
        static final int INITIALIZED = 0;
        static final int RUNNING = 1;
        static final int STOPPED = 2;
        void m(int i) {
          // the default method
        }
        void m(int@@INITIALIZED i) {
          // handle the case when we're in the initialized `state'
        }
        void m(int@@RUNNING i) {
          // handle the case when we're in the running `state'
        }
        void m(int@@STOPPED i) {
          // handle the case when we're in the stopped `state'
        }
      }
      

      这篇关于Java 中的重载和多分派的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆