Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 类,该类使用返回泛型接口的工厂<;T>;解析T的列表,但不只是T_Java_Generics_Interface - Fatal编程技术网

Java 类,该类使用返回泛型接口的工厂<;T>;解析T的列表,但不只是T

Java 类,该类使用返回泛型接口的工厂<;T>;解析T的列表,但不只是T,java,generics,interface,Java,Generics,Interface,我有以下设置。我有一个由StringFetcher实现的AbstractFetcher。然后我有一个工厂,它根据输入返回AbstractFetchers。。这里,OneClass正在使用AbstractFactoryFetcher。在方法doSomething中,我得到了第二行的编译器错误,但不是第一行!换句话说,fetchMany()编译得很好!发生这种情况的原因是什么?即使使用通用方法提示,如何更改签名,从而不需要强制转换?我的最终目标是使OneClass不必知道任何有关returnt的具体

我有以下设置。我有一个由
StringFetcher
实现的
AbstractFetcher
。然后我有一个工厂,它根据输入返回
AbstractFetcher
s。。这里,
OneClass
正在使用
AbstractFactoryFetcher
。在方法
doSomething
中,我得到了第二行的编译器错误,但不是第一行!换句话说,
fetchMany()
编译得很好!发生这种情况的原因是什么?即使使用通用方法提示,如何更改签名,从而不需要强制转换?我的最终目标是使OneClass不必知道任何有关returnt的具体获取程序的信息,这样即使在FetcherFactory上有更改,也可以单独部署/编译它

public interface AbstractFetcher<T> {
    T fetchOne();
    List<T> fetchMany();
}

public class StringFetcher implements  AbstractFetcher<String> {

    @Override
    public String fetchOne() {
        return "a string"
    }

    @Override
    public List<String> fetchMany() {
        List<String> list = new ArrayList<>();
        list.add("String 1");
        list.add("String 2");
        return list;
    }
}

public interface AbstractFactoryFetcher {
    public AbstractFactoryFetcher make(String type);
}

public class FetcherFactory implements AbstractFactoryFetcher {
    public AbstractFetcher make(String type) {
        if (type.equals("String")) {
            return new StringFetcher();
        }
        else {
            return null;
        }
    }
}

public class OneClass {
    FetcherFactory factory;
    public OneClass(FetcherFactory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        List<String> list = factory.make("String").fetchMany();
        String one = factory.make("String").fetchOne(); //compiler error Required: String, Found: Object
    }

}
公共接口抽象获取程序{
T fetchOne();
List fetchMany();
}
公共类StringFetcher实现AbstractFetcher{
@凌驾
公共字符串fetchOne(){
返回“字符串”
}
@凌驾
公共列表fetchMany(){
列表=新的ArrayList();
列表。添加(“字符串1”);
列表。添加(“字符串2”);
退货清单;
}
}
公共接口AbstractFactoryFetcher{
public AbstractFactoryFetcher make(字符串类型);
}
公共类FetcherFactory实现AbstractFactoryFetcher{
公共抽象获取程序生成(字符串类型){
if(type.equals(“字符串”)){
返回新的StringFetcher();
}
否则{
返回null;
}
}
}
公共一类{
菲克特工厂;
公共OneClass(FetcherFactory工厂){
这个工厂=工厂;
}
公共无效剂量测定法(){
List List=factory.make(“字符串”).fetchMany();
String one=factory.make(“String”).fetchOne();//需要编译器错误:String,找到:Object
}
}

谢谢

您在
doSomething
中将
AbstractFetcher
用作原始类型,这意味着使用了对其方法的擦除:

Object fetchOne();
List fetchMany();
列表
可以转换为
列表
(带有未选中的警告)。对象无法转换为
字符串

最好是强类型工厂:

public AbstractFetcher<String> makeStringFetcher() {
    return new StringFetcher();
}
public AbstractFetcher makeStringFetcher(){
返回新的StringFetcher();
}
您试图将返回值用作
抽象获取程序
,这意味着您在编译时以任何方式知道
类型
字符串


泛型是编译时的东西,编译器无法知道
类型
字符串的运行时值。因此,在这种情况下,您不能使用泛型类型安全。

您在
doSomething
中将
AbstractFetcher
用作原始类型,这意味着将使用对其方法的擦除:

Object fetchOne();
List fetchMany();
列表
可以转换为
列表
(带有未选中的警告)。对象无法转换为
字符串

最好是强类型工厂:

public AbstractFetcher<String> makeStringFetcher() {
    return new StringFetcher();
}
public AbstractFetcher makeStringFetcher(){
返回新的StringFetcher();
}
您试图将返回值用作
抽象获取程序
,这意味着您在编译时以任何方式知道
类型
字符串


泛型是编译时的东西,编译器无法知道
类型
字符串的运行时值。因此,在这种情况下,您不能使用通用类型安全性。

虽然仍有铸件,但在工厂中:

public class FetcherFactory {
        public <T> AbstractFetcher<T> make(Class<T> type) {
            if (type.equals(String.class)) {
                return (AbstractFetcher<T>) new StringFetcher();
            }
            else {
                return null;
            }
        }
    }
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
if(type.equals(String.class)){
返回(AbstractFetcher)新StringFetcher();
}
否则{
返回null;
}
}
}
然后你可以像这样打电话:

public void doSomething() {
    List<String> list = factory.make(String.class).fetchMany();
    String one = factory.make(String.class).fetchOne(); 
}
public void doSomething(){
List=factory.make(String.class).fetchMany();
stringone=factory.make(String.class).fetchOne();
}

虽然仍有铸件,但在工厂中:

public class FetcherFactory {
        public <T> AbstractFetcher<T> make(Class<T> type) {
            if (type.equals(String.class)) {
                return (AbstractFetcher<T>) new StringFetcher();
            }
            else {
                return null;
            }
        }
    }
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
if(type.equals(String.class)){
返回(AbstractFetcher)新StringFetcher();
}
否则{
返回null;
}
}
}
然后你可以像这样打电话:

public void doSomething() {
    List<String> list = factory.make(String.class).fetchMany();
    String one = factory.make(String.class).fetchOne(); 
}
public void doSomething(){
List=factory.make(String.class).fetchMany();
stringone=factory.make(String.class).fetchOne();
}

如果可以将
而不是字符串参数传递给工厂,有一种方法可以实现这一点,而无需任何强制转换,但需要反射才能使其工作

实现
FetcherFactory
如下:

public class FetcherFactory {
  public <T, U extends AbstractFetcher<T>> AbstractFetcher<T> make(Class<U> type) {
    try {
      return type.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }
}
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
试一试{
返回类型:newInstance();
}捕获(实例化异常|非法访问异常e){
抛出新的运行时异常(e);
}
}
}
然后您可以在呼叫站点使用它,如下所示:

public class OneClass {
  FetcherFactory factory;
  public OneClass(FetcherFactory factory) {
    this.factory = factory;
  }

  public void doSomething() {
    List<String> list = factory.make(StringFetcher.class).fetchMany();
    String one = factory.make(StringFetcher.class).fetchOne();
  }
}
公共类OneClass{
菲克特工厂;
公共OneClass(FetcherFactory工厂){
这个工厂=工厂;
}
公共无效剂量测定法(){
List List=factory.make(StringFetcher.class).fetchMany();
stringone=factory.make(StringFetcher.class).fetchOne();
}
}

如果可以将
而不是字符串参数传递给工厂,有一种方法可以实现这一点,而无需任何强制转换,但需要反射才能使其工作

实现
FetcherFactory
如下:

public class FetcherFactory {
  public <T, U extends AbstractFetcher<T>> AbstractFetcher<T> make(Class<U> type) {
    try {
      return type.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }
}
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
试一试{
返回类型:newInstance();
}捕获(实例化异常|非法访问异常e){
抛出新的运行时异常(e);
}
}
}