Java:将通用类型(T)对象转换为由类型化调用签名识别的完全类型化对象?

标签 java generics types

给定

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/

相关文章:

java - 扫描带注释的类不适用于 Instant Run

java - Maven cucumber 报告失败 - Java.io.FilenotFoundexception cucumber.json

java - 从数据库创建 Spring Bean

scala - 概括一个 "next permutation"函数

javascript - 添加字符串和数字时,JavaScript 如何转换为字符串?

java - 用 Java 编写随机答案生成器 - 答案出现在 JFrame 中

c# - Java 的使用站点差异与 C# 的声明站点差异相比如何?

java - Java HashMap 的 Eclipse 警告

java - 反序列化集合时不安全的泛型转换

haskell - Haskell 中的递归类型同义词 - 'cycle in type synonym declarations'