为什么我的 Java 泛型数组类型传输方法调用无法编译?

Why won't my Java generic array type transfer method call compile?

我正在尝试创建一个系统,允许我将所有项目放入一个数组中,然后使用工厂对象将它们转换为另一种类型的项目,并用这些新对象填充第二个数组, return 那。我想用泛型来完成这一切,所以这可以在单行静态方法调用中完成。但是,我收到一个我无法完全解析的错误。这是(我希望)所有相关代码:

问题 class 有:

// ...

// "ArrayPP" is my take on ArrayList that has a lot of convenience methods.
// The constructor here uses varargs to initialize the array:
ArrayPP<String> myStrings = new ArrayPP<>("foo", "bar", "baz");
// MyCharSequenceImpl is just a class that implements CharSequence.
ArrayPP<MyCharSequenceImpl> myCSI = new ArrayPP<>();
// The error occurs on the following line:
myCSI = ArrayPP.transfer(myStrings, new CSToMyCSIFactoryDelegate());

// ...

ArrayPP 有:

public class ArrayPP<T> implements Iterable<T> {
    // ...
    // Iterable implementations
    // ...

    public static <From, To> ArrayPP<To> transfer(Iterable<From> origin, FactoryDelegate<From, To> factory)
    {
        ArrayPP<To> ret = new ArrayPP<>();
        for (From f : origin) {
            ret.add(factory.makeFromFactory(f));
        }
        return ret;
    }

    // ...
}

FactoryDelegate 有:

public interface FactoryDelegate<From, To> extends Factory<To> {
    public To makeFromFactory(From basis);
}

Factory 有:

public interface Factory<To> {
    public To makeFromFactory();
}

CSToMyCSIFactoryDelegate 有:

public class CSToMyCSIFactoryDelegate implements FactoryDelegate<CharSequence, MyCharSequenceImpl> {
    @Override
    public MyCharSequenceImpl makeFromFactory(CharSequence basis) {
        // MyCharSequenceImpl has a constructor that converts any CharSequence
        // into a new MyCharSequenceImpl.
        return new MyCharSequenceImpl(basis);
    }

    @Override
    public MyCharSequenceImpl makeFromFactory() {
        return makeFromFactory("");
    }
}

这是我遇到的错误:

error: method transfer in class ArrayPP<T> cannot be applied to given types;
        myCSI = ArrayPP.transfer(myStrings, new CSToMyCSIFactoryDelegate());
                       ^
  required: Iterable<From>,FactoryDelegate<From,To>
  found: ArrayPP<String>,TransferTest.CSToMyCSIFactoryDelegate
  reason: inferred type does not conform to equality constraint(s)
    inferred: CharSequence
    equality constraints(s): CharSequence,String
  where From,To,T are type-variables:
    From extends Object declared in method <From,To>transfer(Iterable<From>,FactoryDelegate<From,To>)
    To extends Object declared in method <From,To>transfer(Iterable<From>,FactoryDelegate<From,To>)
    T extends Object declared in class ArrayPP

这个错误最令人困惑的部分,对我来说,是它说 inferred type does not conform to equality constraint(s),然后推断类型是 CharSequence,等式约束是 CharSequence,String.. .

为什么会出现此错误,我该如何修复我的代码?

From 必须是第一个参数的 String,并且必须是第二个参数的 CharSequenceStringCharSequence 的事实对于您描述泛型的方式并不重要。试试Iterable<? extends From>可能吧?

看来你需要的是

public static <From, To> ArrayPP<To> transfer(
    //       vvvvvvvvv
    Iterable<? extends From> origin,
    FactoryDelegate<From, To> factory
)

因为您只关心 origin 在迭代时产生 From,而不是它一定是 Iterable<From>

另见

  • Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?
  • What is PECS (Producer Extends Consumer Super)?