【问题标题】:java generics parameter can't apply to a specific typejava泛型参数不能应用于特定类型
【发布时间】:2017-10-05 04:15:01
【问题描述】:
public class Demo {
    public String work(String s) {
        return s;
    }

    public <T> T Test(T t) {
        // common work to do !!
        // .....
        // spec work to do 
        T result = work(t);
        return result;
    }
}

Test() 首先要做一些共同的工作,然后是针对不同类型的 T 的具体工作。 上面的代码导致编译器错误,我该怎么做? 非常感谢!

【问题讨论】:

  • 你不能在 Java 中做这样的事情。关于选择哪个方法的重载的决定是在编译时做出的,而不是在运行时。
  • 如何实现? Test()需要处理不同的param类型,在这个函数中需要先做一些常用的工作,我只是想把常用的部分提取到Test()中。
  • 将公共部分拉到一个单独的方法中,并有多个测试重载调用该单独的方法,然后做专门的工作。
  • 这确实有效。但不是优雅的风格。它需要将许多接口 [Test()] 导出到调用者...。 c++可以轻松做到这一点,我认为java也可以做到这一点

标签: java generics casting


【解决方案1】:

有许多因素会导致您的代码无法在此处编译;除了 ';',您还从 void 方法返回了一些东西。请发布您也面临的编译器错误,这将使潜在的响应者更清楚。

【讨论】:

  • 对不起,这是一个简单的演示问题的部分主要错误是参数不匹配它说:work()需要像String这样的参数,但是传递一个T(通用类型)
【解决方案2】:

可以做的可能是创建一个从 T 类型到 (unary?) function 的映射。然后,在test 方法中,您可以查找T 类型。如果函数已注册,则应用:

public class Demo {
  private static final Map<Class<?>, UnaryOperator<?>> typeFuncs = new HashMap<>();
  static {{
    addTypeFunc(String.class, (String s) -> s); // Anonymous function.
    addTypeFunc(Integer.class, Demo::workInteger); // Function reference.
  }}

  private static <T> void addTypeFunc(Class<T> type, UnaryOperator<T> func) {
    typeFuncs.put(type, func);
  }

  private static Integer workInteger(Integer i) {
    return i;
  }

  public <T> T test(T t) {
    // common work to do !!
    // .....

    T result = null;
    UnaryOperator<T> operator = (UnaryOperator<T>) typeFuncs.get(t.getClass());
    if (operator != null) {
      result = operator.apply(t);
    }

    return result;
  }
}

请注意,test 中的转换 (UnaryOperator&lt;T&gt;) 是安全的,因为我们可以完全控制 typeFuncs 映射中键和值类型之间的关系。

【讨论】:

  • 非常感谢,这行得通,但它带来了两个限制:1)需要手动调用 addTypeFunc() 2)UnaryOperator 可能不够不优雅
  • @TAW8750 是的,1)您需要在类型和适用功能之间显式映射。 2) 什么?
  • 2) UnaryOperator operator = (UnaryOperator) typeFuncs.get(t.getClass());这里的操作符可能很复杂,例如:许多参数
【解决方案3】:

另一种方法是使用反射。请注意,反射是一种强大的工具,但它是有代价的(性能)。执行测量以查看这是否是一个可行的解决方案是您的具体情况:

public class Demo {
  private String work(String s) {
    return s.toUpperCase();
  }

  private Boolean work(Boolean b) {
    return !b;
  }

  public <T> T test(T t) {
    // common work to do !!
    // .....

    // Now look-up "work" method for type T. Invoke if defined.
    T result = null;
    try {
      Class<T> tType = (Class<T>) t.getClass();
      Method work = Demo.class.getDeclaredMethod("work", tType);
      if (work.getReturnType() != tType) {
        throw new NoSuchMethodException("No `work` method for type: " + tType);
      }

      result = (T) work.invoke(this, t);
    } catch (NoSuchMethodException e) {
      // NOOP - or whatever.
    } catch (IllegalAccessException | InvocationTargetException e) {
      // Method invocation failed. Handle properly.
      e.printStackTrace();
    }

    return result;
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多