Java泛型调用自身类的解释说明

3

Dave Syerorg.springframework.security.oauth2.config.annotation.builders包中编写了以下类。

    public class ClientDetailsServiceBuilder<B extends ClientDetailsServiceBuilder<B>> extends
        SecurityConfigurerAdapter<ClientDetailsService, B> implements SecurityBuilder<ClientDetailsService> {
}

我对这段代码的理解有些困难。有人能解释一下这里泛型的用法以及Dave在这里想要实现什么吗?


如果没有出现好的答案,试着联系Dave Syer,他可能是这个问题最合适的人选。 - Nikos M.
2
从这个小片段来看,我猜测这是流畅构建器API的常见习语。 - chrylis -cautiouslyoptimistic-
2个回答

4
它被称为“递归类型边界”。这里的B是基于ClientDetailsServiceBuilder定义的。但由于这是刚刚声明的类型,因此B再次出现以满足类型参数。
我找到了一个更通用的解释:http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106 这种模式的另一个很好的例子:
public interface Tree<T extends Tree<T>> {
    List<T> getChildren();
}

这个定义使得 Tree 的子类型(实现)自动返回它们的类型参数的子节点,该类型参数必须是一个 Tree,甚至可以是 它们的实际类型。如果返回类型只是 List<Tree>,那么期望子类型的调用者可能需要进行强制类型转换。

这个定义使得树的子类型(实现)自动返回其实际类型的子节点。不一定是这样的。它们返回其类型参数的子节点,这不一定是它们的实际类型。 - newacct
你说得对,一个Tree可以有另一种类型的Tree作为子节点。我会稍微改一下措辞。此外,更大的类型层次结构会让事情变得混乱。只是觉得这比Spring builder的例子更容易理解递归边界。 - stholzm

2
通过使用class MyClass<T extends MyClass<T>>,您可以将任何子类的类型作为通用类型进行访问。
这使您可以执行以下操作:
class MyClass<T extends MyClass<T>> {
    private int value;

    T withValue(int value) {
        this.value = value;
        return (T) this;
    }
}

class MySubclass extends MyClass<MySubclass> {
    private String name;

    public MySubclass withName(String name) {
        this.name = name;
        return this;
    }
}

MySubclass s = new MySubclass()
    .withValue(5)
    .withName("John Doe");

这使您可以做像这样的事情:不,它不能。(T) this是不安全的。 - newacct

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接