【问题标题】:Convert Generic Types to Objects将泛型类型转换为对象
【发布时间】:2020-08-14 10:46:45
【问题描述】:

我正在编写一个转换器来将String 输入转换为自定义类型的输出。以下是interface 的样子:

public interface Transformer<T> {
    public T transform(String input);
}

它将有多种实现(即IntegerTransformerByteTransformer 等)。我写了一个返回这些变压器的工厂,例如:

public class TransformerFactory {
    public <T> Transformer<T> getTransformer(final SomeEnum enum, final T type) {
        switch(enum) {
        case FOO:
            return new IntegerTransformer();
        case BAR:
            return new ByteTransformer();
            default:
                throw new Exception("blah");
        }
    }
}

在我的main 课堂上,我正在这样做:

factory.getTransformer(foo, Integer.class).transform(input);

这会导致以下错误:

Type mismatch: cannot convert from Class<Integer> to Integer

所以,我需要以某种方式将 Type 文字转换为 Object。有什么方法可以在不修改接口和工厂的通用结构的情况下做到这一点?

【问题讨论】:

  • 既然不用type参数,那为什么还要呢?
  • 参数应该是Class&lt;T&gt; type。这就是Integer.class 是:Class&lt;Integer&gt;
  • @MAnouti 就是这样,如果您可以将其发布为答案,我会接受。
  • 你不能用泛型做到这一点:你可以调用 getTransformer(SomeEnum.FOO, Integer.valueOf(0))getTransformer(SomeEnum.FOO, Byte.valueOf(0)) - 两者都不能是类型正确的。你能做的最好的就是从方法中返回一个Transformer&lt;?&gt;
  • @Steyrix 这只是一个说明性示例。我确实在实际实现中使用了该类型

标签: java generics transform factory


【解决方案1】:

TL;DR:不要试图狙击你为他/她指定的 @MAnouti 的积分。但是为了完整起见,OP,我想分享我在my attempt to reproduce your error 中观察到的内容。


这会导致以下错误:

Type mismatch: cannot convert from Class<Integer> to Integer

您问题中的原始示例代码无法编译 (as confirmed by my failed attempt to reproduce the same error),出现这些不同编译错误...

...
incompatible types: IntegerTransformer cannot be converted to Transformer<T>
...
incompatible types: ByteTransformer cannot be converted to Transformer<T>
...

…请注意,这些与您在问题中报告的错误不同。

即使您确实遵循其他答案/cmets 的建议并将 T 替换为 Class&lt;T&gt; 作为方法的第二个形式参数,您仍然会得到上述 cannot be converted to Transformer&lt;T&gt; 编译错误。

...有什么方法可以在不修改接口和工厂的通用结构的情况下做到这一点?

我有confirmed by a simple experiment 这符合该标准。 并且它成功编译并按预期运行......

    public < T, U extends Transformer< T > > U getTransformer( SomeEnum eNum, Class< T > type ){ 
    
    switch( eNum ){ 
        case FOO:
            return (U)new IntegerTransformer( );
        case BAR:
            return (U)new ByteTransformer( );
        default:
            throw new RuntimeException( "Detected Decepticons Among Us!" );
    }
}

…它修复了您在问题中报告的错误,cannot be converted to Transformer&lt;T&gt; 错误,如果唯一的话你改变的是Class&lt;T&gt;的参数。

【讨论】:

  • 你是绝对正确的。我收到cannot be converted to Transformer&lt;T&gt; 错误并尝试使用通配符、extends 关键字等变通方法,但均未奏效。通过上述解决方案,我能够编写和执行代码。感谢您的全面回答,我认为这比@MAnouti 的回答更完整。
【解决方案2】:

getTransformer(final SomeEnum enum, final T type) 的签名需要T 类型的实际对象。你想要的是传递一个class 的实例,所以它应该是: getTransformer(final SomeEnum enum, final Class&lt;T&gt; type)

此外,从 Java 8 开始,无需声明如此简单的接口。使用通用的Function&lt;String,T&gt; 会为您提供完美的服务。

【讨论】:

  • 那么,getTransformer(SomeEnum.FOO, Integer.class) 的类型是什么,getTransformer(SomeEnum.FOO, Byte.class) 的类型是什么?
猜你喜欢
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多