【问题标题】:Create an object with a String and method overloading使用 String 和方法重载创建对象
【发布时间】:2012-05-02 10:37:49
【问题描述】:

我有一个字符串,它可以是 Double 或 Integer 类型或其他类型。我首先需要创建一个 Double 或 Integer 对象,然后将其发送到重载方法。到目前为止,这是我的代码;

public void doStuff1(object obj, String dataType){

 if ("Double".equalsIgnoreCase(dataType)) {
        doStuff2(Double.valueOf(obj.toString()));
    } else if ("Integer".equalsIgnoreCase(dataType)) {
        doStuff2(Integer.valueOf(obj.toString()));
    }

 }

 public void doStuff2(double d1){
   //do some double related stuff here
 }

 public void doStuff2(int d1){
   //do some int related stuff here
 }

我想在没有 if/else 的情况下这样做;

Class<?> theClass = Class.forName(dataType);

问题是 'theClass' 仍然不能转换为 double 或 int。如果有任何想法,我将不胜感激。 谢谢。

找到一个相关的线程; Overloading in Java and multiple dispatch

【问题讨论】:

    标签: java reflection overloading


    【解决方案1】:

    这不仅仅是处理原始类型的问题。

    调用哪个方法由编译时决定,也就是说,如果你希望能够根据参数的类型调用不同的方法,你需要多次调用(即你需要 if 结构)。

    换句话说,即使doStuff2IntegerDouble 作为参数,它也行不通(你的代码基本上和它一样好)。

    (换句话说,这是因为 Java 有 单次调度。要模拟 多次调度,您需要使用条件语句或访问者模式。 )

    【讨论】:

    • 为什么说doStuff2 采用Integer 和Double 就不行?我不是反对者,但这个说法对我来说似乎是错误的,因此这可能是反对者的动机。
    • @MarkoTopolnik,正如您所见,here 方法重载在运行时根本不存在。
    • 好的,我和你一样了解这个理论——这就是我问的原因。它与 int 和 double 的工作方式与 Integer 和 Double 的工作方式相同。我现在明白了,这就是你所说的,它不会不管怎样
    • 对,但 OP 似乎表明这是原语的问题:问题是 'theClass' 仍然不能转换为 double 或 int。 这就是原因我就这样制定了答案。
    • 是的,我的错,我看错了你的措辞。根据技术,它要么对两者都有效,要么都不适用。
    【解决方案2】:

    由于方法调用是在编译时决定的,正如另一个答案告诉你的那样,重载对你不起作用。我认为这个问题可以通过继承来解决。因此,您使用yourMethod() 编写一个基类并在派生类中覆盖它。

    【讨论】:

      【解决方案3】:

      正如 aioobe 所说,重载方法之间的选择是在编译时根据参数的静态类型进行的。

      如果您想在运行时模拟重载选择,您将需要对不同的可能方法进行一些复杂的运行时分析。它会是这样的:

      1. 获取声明doStuff2的类的所有声明方法。
      2. 过滤掉名字不是doStuff2的方法。
      3. 从参数值的(动态)类型中过滤掉参数类型不能赋值的方法。
      4. 在其余方法中,选择最匹配的方法...注意将“关系”视为模棱两可。

      这对代码来说会很棘手,如果你还要处理原始类型,那就更棘手了。它还会使方法调用变得昂贵。


      坦率地说,某种硬接线调度要简单得多。如果您不喜欢 if / else 测试(或在 Java 7 中打开 String),那么您可以这样做。

      Map<String, Operation> map = ...
      map.put("Double", new Operation(){
          public void doIt(Object obj) {
              doStuff2((Double) obj);
          }});
      map.put("Integer", new Operation(){
          public void doIt(Object obj) {
              doStuff2((Integer) obj);
          }});
      ...
      map.get(typeName).doIt(obj);
      

      ...这至少允许您动态“插入”对新类型的支持。

      【讨论】:

        【解决方案4】:

        如果你使用反射,你只需要专门处理原始类型。因此,您的技术可以工作,但需要添加一些明确的测试。如果您需要反思性地找到接受原始double 的方法,请使用double.class

        【讨论】:

          猜你喜欢
          • 2011-06-06
          • 1970-01-01
          • 1970-01-01
          • 2023-04-03
          • 1970-01-01
          • 2014-11-26
          • 1970-01-01
          • 2018-12-30
          • 2021-06-24
          相关资源
          最近更新 更多