给定
private someMethod(String value) {
// do string things
}
private someMethod(Integer value) {
// do number things
}
以下内容是否可以根据 clazz
的类型和 input
的值调用正确的 someMethod
?
public <T> void doSomething(T input, Class<T> clazz) {
// Cast the input to the type specified by clazz
// Call a method that expects a parameter of the type specified by clazz
someMethod(clazz.cast(input));
}
如果不能以这种方式完成,那么最好的方法是什么,而不需要对静态类型常量进行长时间的 if/else 硬检查?
最佳答案
第一个(也是快速的)“解决方案”
实际上,没有任何 Java 内置机制可以为您处理这种调度。这意味着,您必须自己做。
但是...为了避免更长的 if-else 链,您可以使用将类型映射到您要调用的使用方法的映射。示例:
private final Map<Class<?>, Consumer<?>> dispatcher = new HashMap<>();
{
dispatcher.put(String.class, (String value) -> someMethod(value));
dispatcher.put(Integer.class, (Integer value) -> someMethod(value));
}
现在您可以执行以下操作:
public <T> void doSomething(T input, Class<T> clazz) {
Consumer<T> consumer = (Consumer<T>) dispatcher.get(clazz);
if (consumer != null) consumer.accept(input);
}
构建调度程序 map 时要小心。调用 doSomething
方法时,任何错误都会导致运行时错误。甚至有一个编译器警告。
并不完美,但也许是一条路要走......
进一步考虑
这个手动调度对你来说是一个很好的提示,可能会有更多类似 OOP 的解决方案。通常,您的想法背后潜藏着一种类型......
因此,首先为该类型创建一个接口(interface):
interface SomethingDoable {
void someMethod();
}
请注意,这里也消除了泛型类型。现在您可以为此创建一些类:
class StringDoable implements SomethingDoable {
private final String value;
public StringDoable(String value) { this.value = value; }
@Override public void doSomething() { /* your code here using the string value */ }
}
class IntegerDoable implements SomethingDoable {
private final Integer value;
public IntegerDoable(Integer value) { this.value = value; }
@Override public void doSomething() { /* your code here using the integer value */ }
}
通过这些准备,您可以简化您的公共(public)方法:
public void doSomething(SomethingDoable somethingDoable) {
somethingDoable.doSomething();
}
使用它就这么简单:
doSomething(new StringDoable("42"));
doSomething(new IntegerDoable(42));
这种方法的主要优点是......扩展它仅仅意味着添加另一个具体类。无需更改任何其他内容。
关于Java:将通用类型(T)对象转换为由类型化调用签名识别的完全类型化对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75563811/