美文网首页
Java泛型让声明方法返回子类型(泛型递归模式)

Java泛型让声明方法返回子类型(泛型递归模式)

作者: 梦沉薇露 | 来源:发表于2016-09-13 23:46 被阅读407次

转自:http://codelife.me/blog/2014/03/05/returning-subtype-of-declared-type-from-method-by-java-generics/

泛型典型的使用场景是集合。考虑到大多数情况下集合是同质的(同一类型),通过声明参数类型,可免去类型转换的麻烦。本文将讨论本人阅读Spring Security源码时遇到的一个关于泛型递归模式的问题。

在Spring Security的源码里有一个ProviderManagerBuilder接口,声明如下:

public interface ProviderManagerBuilder<B extends ProviderManagerBuilder<B>> extends 
SecurityBuilder<AuthenticationManager> {
    B authenticationProvider(AuthenticationProvider authenticationProvider);
}

其实现类AuthenticationManagerBuilder

public class AuthenticationManagerBuilder extends 
AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder> implements ProviderManagerBuilder<AuthenticationManagerBuilder> {

    //...
    
    public AuthenticationManagerBuilder authenticationProvider(
        AuthenticationProvider authenticationProvider) {
        this.authenticationProviders.add(authenticationProvider);
        return this;
    }
    
    //...

}

上面有很多干扰项,我们来简化一下
接口A定义如下


public interface A<T extends A<T>> {

    T add();

} 

A接口的实现类B


public class B implements A<B> {
    
    @Override
    public B add() {
        return null;
    }

} 
/*注意,此处类`B`里的add方法返回类型`B`。也就是说,
接口`A`里声明的方法时并不知道子类型`B`的存在,通过继承和泛型,
可以放返回值动态的适配子类型,这一切都要归功于`<T extends A<T>>`
*/

泛型递归模式(Recurring Generic Pattern)
public interface A<T extends A<T>>对于参数类型T是递归定义的。有如GNU的定义“GNU’s Not Unix!”。

典型的例子是java.lang.Enum

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {
    //...
}

java所有的枚举类型都隐式的继承java.lang.Enum
,不允许通过现实的继承声明枚举类型,甚至集成java.lang.Enum
也是编译器所不允许的。

假设有一个枚举类StatusCode,其等价的声明如下:
public class StatusCode extends Enum<StatusCode>
现在我们来验证一下泛型约束,
1.因为Enum<StatusCode>,所以E=StatusCode

2.根据<E extend Enum<E>>E=StatusCode 可得,<StatusCode extend Enum<StatusCode>>

3.由于public class StatusCode extends Enum<StatusCode>第二步的结论显然成立。

为什么Enum的声明这么绕?直接Enum不行么?

因为Enum<E>实现了Comparable<E>接口,该接口有一个compareTo方法:

public int compareTo(E o) {}

泛型递归模式与继承
泛型递归模式interface A<T extend A<T>>用于约束参数类型T,要求其为类型A的子类。考虑到继承和实现B implements A<B>,参数类型和实体类型是一致的。这样类A中方法签名里涉及到参数类型T的地方,在实现类里会为实现类本身,这让类型系统更加的严谨。

相关文章

  • Java泛型让声明方法返回子类型(泛型递归模式)

    转自:http://codelife.me/blog/2014/03/05/returning-subtype-o...

  • Kotlin---泛型

    Kotlin不变型泛型 Kotlin的不变型泛型和Java一样,通过声明泛型类型来使用泛型类。而该种泛型声明后,则...

  • Java泛型

    泛型有三种实现方式,分别是泛型接口、泛型类、泛型方法。下面通过泛型方法来介绍什么是类型参数。 泛型方法声明方式:访...

  • OC 泛型, __kindof

    泛型:限制类型 泛型声明格式:在声明类的时候,在类型后面<泛型名称>泛型定义格式:放在限制的类型后面<类型> 泛型...

  • Java中的泛型

    泛型方法 下面是定义泛型方法的规则: 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分...

  • 7. Dart - 泛型

    1. 泛型方法 泛型方法的定义: 第一个T,表示方法返回类型第二个T,表示声明的泛型类型第三个T,表示方法入参类...

  • Java泛型教程

    Java泛型教程导航 Java 泛型概述 Java泛型环境设置 Java泛型通用类 Java泛型类型参数命名约定 ...

  • 泛型的用法

    一、泛型方法1、函数的参数是泛型下面是定义泛型方法的规则:所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔)...

  • 《Oracle Java SE编程指南》20-04:泛型方法

    内容导航: 前言 1、定义 1、定义 方法也可以声明成泛型方法,只要在返回值前声明泛型参数列表即可。泛型方法使得该...

  • Kotlin泛型与DSL重点记录

    泛型 kotlin的泛型语法与java类似,比如声明一个泛型类: 类型参数约束 类似于java中的entends关...

网友评论

      本文标题:Java泛型让声明方法返回子类型(泛型递归模式)

      本文链接:https://www.haomeiwen.com/subject/ooqvettx.html