多个通用类型

Multiple Generic Types

所以首先,我要说明我的问题不是指将多个泛型应用于 class。我知道你可以简单地用逗号来做到这一点。

我的问题是是否有一种方法可以对泛型进行多种可能的扩展。例如:

public class Foo<? extends String>{}
public class Bar<? extends StringBuilder>{}
//combined
public class FooBar<? extends String, StringBuilder>{}
//or perhaps
public class FooBar<? extends String || StringBuilder>{}

我知道 FooBar class 不会编译,但我希望这有助于解释我的问题和指定的意图。最后重申我的问题:是否可以在通用子句中扩展两个 classes 或间接模拟此类操作的方式?

注意我不是询问泛型如何工作,也不是扩展如何工作,也不是涉及如何以及何时使用泛型的任何事情,因为我已经知道了。如果问题需要澄清,我会编辑以尽我所能提供进一步的理解。

class 不可能同时扩展 StringStringBuilder,因为 class 只有一个父 class。但是,它们可以实现多个接口,您可以使用 &.

指定这些接口
class FooBar<T extends String & Runnable & Collection<Integer>> {}

(请注意,String 是最终的,因此实际上不可能满足上述约束条件。)

因此,正如 John 所说,您所要求的不可能开箱即用,但您仍然可以使用所谓的 Either 类型实现类似的行为,该类型用于表示您可以 1 2 种类型。

您可以通过简单的 google 搜索轻松找到完全实现的 Either class,例如 github

上的这个

对于下面的代码片段,让我们考虑这个简化版本:

public class Either<L, R> {
    private final L left;
    private final R right;
    private final boolean isRight;

    private Either(L left, R right, boolean isRight) {
        this.left = left;
        this.right = right;
        this.isRight = isRight;
    }

    public static <L, R> Either<L, R> left(L left){
        return new Either<>(left, null, false);
    }

    public static <L, R> Either<L, R> right(R right){
        return new Either<>(null, right, true);
    }

    public <T>  T fold(Function<L,T> foldLeft, Function<R, T> foldRight){
        return isRight ? foldRight.apply(right) : foldLeft.apply(left);
    }
}

现在假设您有一些方法接口,应该接受 StringStringBuilder:

public interface IFooBar <T extends Either<? extends String, ? extends StringBuilder>>{
    String  doSomething(T t);
}

和实现:

class FooBar implements IFooBar<Either<String, StringBuilder>> {
    @Override
    public String doSomething(Either<String, StringBuilder> either) {
        return either.fold(s -> "String: " + s, sb -> "StringBuilder:" + sb);
    }
}

然后你可以像这样简单地使用它:

public static void main(String[] args) {
    IFooBar<Either<String, StringBuilder>> fooBar = new FooBar();
    // Since in this case it is single method interface you can even use lambda expression
    // IFooBar<Either<String, StringBuilder>> fooBar = either -> either.fold(s -> "String: " + s, sb -> "StringBuilder:" + sb);
    System.out.println(fooBar.doSomething(Either.left("Foo")));
    System.out.println(fooBar.doSomething(Either.right(new StringBuilder("Bar"))));
}

希望对您有所帮助。