是你眼中的泛型吗?

《? extends T与? super T》以后,咱们再聊聊泛型。html

Demo 1

public interface Generator {
    <T> T next();
}

第一种解决方法,在方法返回类型前加“<T>”使其成为一个泛型方法。java

public interface Generator<T> {
    T next();
}

第二种解决方法,在接口名后加“<T>”使其成为一个泛型接口。app

泛型类/接口在使用前,必须先指名参数类型,其中除了泛型方法外的泛型参数都将是所指定的类型。以下:ide

// 泛型接口与其子类
public interface Generator<T> {
    T next(T t);
    void print(T t);
}

public class SubGenerator implements Generator<String>{

    @Override
    public String next(String t) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void print(String t) {
        // TODO Auto-generated method stub
        
    }

}

// 含有泛型方法的接口及其子类
public interface Generator<T> {
    T next(T t);
    <U> void print(U t);
}

public class SubGenerator implements Generator<String>{

    @Override
    public String next(String t) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public <U> void print(U t) {
        // TODO Auto-generated method stub
        
    }

}

Demo 2

即静态方法没法访问泛型类上定义的泛型,此时采用泛型方法可解决。测试

// 正确作法
public class StaticGenerator {
    public static <T> T rebey(T t) {
        return null;
    }
}

Demo 3

在《深刻理解Java虚拟机 JVM高级特性与最佳实践(高清完整版)》P271 介绍了“当泛型碰见重载”的例子。得出的结论是:url

两个方法若是有相同的名称和特征签名,但返回值不一样,那他们也是能够合法地共存于一个Class文件中的。code

public String url(String s) {
    return "rebey.cn";
}

public int url(String s) {
    return 0;
}

然而以上代码是没法编译经过的。由于此书出版时还未发布JDK7,所以其实只有JDK1.6及如下才能编译经过。随着时间的推移,原来错的可能因此仍是按咱们原来的理解来解读重载就行了。同名方法参数个数、顺序、类型不一样,与返回值类型无关。htm

Demo 4

public class Utilities {
    public static <T> HashSet<T> create(int size) {
        return new HashSet<T>(size);
    }
     
    public static void print( HashSet<String> h) { 
        for (String s : h) System.out.println(s);
    }
}

public class ResultGerneric {
    public static void main(String[] args) {
        Utilities.print(Utilities.create(10));    // error in Java 5,6,7 ; fine in Java 8
    }
}

这是来自GenericsFAQ403中的一个例子。笔者在java7上测试了,如愿的看到了错误提示:“The method print(HashSet<String>) in the type Utilities is not applicable for the arguments (HashSet<Object>)”。因为Utilities.create方法未指定具体类型,默认转为Object,因此Utilities.print此时没法接收其做为String类型的参数。而在Java8版本的增长了类型推断(type argument inference),可以根据赋值符号左边值类型自动推断出右边。接口

此外,经过显示指定参数类型也可以解决上述问题:get

public class ResultGerneric {
    public static void main(String[] args) {
        Utilities.print(Utilities.<String>create(10));//点操做符与方法名之间
    }
}

在《Think In Java》4th中泛型章节也提到了类似的例子(P363)。

说点什么

经过几个泛型的例子,咱们看到:随着时间的推移,对的可能错,错的亦能对。

这不是颇有趣的一件事吗?

待续...


更多有意思的内容,欢迎访问笔者小站: rebey.cn

相关文章
相关标签/搜索