泛型,也就是将类型参数化,然后在使用类或者方法的时候可以传入类型,在不需要创建新类型实现的前提下可以通过泛型控制形参的类型。泛型可以用在类,方法和接口中。

1,泛型中的相关操作符

		在使用泛型的代码中经常可以看到一些泛型相关的符号,它们的作用如下表所示:
类型 功能
T,E,K,V 泛型标识,可以写人任意标识,不同字母更多是一种约定,等同于< T extends Object>
? 无限制通配符,表示不确定类型,等同于< ? extends Object>
extend 上界通配符
super 下界通配符
& 附加约束(AdditionalBound, tjls8-4.4)

2,泛型基本使用示例

public class GenericDemo<C> { //泛型类

    public static void main(String[] args) {
//泛型类用Integer初始化,所以C相关的方法属性必须是Integer
GenericDemo<Integer> gd = new GenericDemo<Integer>();
gd.classPrint(1);
gd.setX(2);
//----------------------
//泛型方法,与调用的类型保持一致,参数类型得为String
GenericDemo.<String>methodPrint("abc");
//---------------------
//泛型接口,与初始化时候传入的类型保持一致,参数类型得是Double
IFC<Double> ifc = new IFC<Double>() {};
ifc.interfacePrint(2.9);
} private C c; public void setX(C c) {
this.c = c;
}
public void classPrint(C c) {
System.out.println(c.getClass());
} //泛型方法,前面的<T>是为了标识这是一个泛型方法
public static <T> void methodPrint(T t) {
System.out.println(t.getClass());
} interface IFC<I> { //泛型接口
default void interfacePrint(I i) { System.out.println(i.getClass());}
}
}

3,通配符

3.1, T和?的区别

基本泛型T是用于定义,将数据类型参数化,不能用于实例化。而 ? 则是在实例化对象时不确定泛型具体参数类型的时候泛指Object的所有子类型。

类型 特点
T < T extends Object>,用于定义
? < ? extends Object>,用于实例化

?不能和Object等效,?是类型实参而不是类型形参,它用于泛指各种类型实参,当具体类型不确定的时候就可以使用?,示例如下:

public class test6 {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
test(list1);
test(list2);
} public static void test(List<?> list) {
System.out.println(list);
}
}

3.2,上下界通配符

上下界通配符其实涉及到java 的多态属性,上下转型的可行性,子类实例可以转换成父类实例,但是父类实例却不一定能转换成子类实例,只有本身就是该子类实例向上转型的父类实例才可以向下转型为子类实例。

<? extends T> 表示类型范围为T以及其子类,<? super T>表示类型范围为T及其父类。

界限通配符在应用于集合的时候会影响集合的读写行为:

上界<? extends T> 限制了类型上限,只能向上转型,可以读,但是没法写,因为子类型不确定,没法向下转型;

下界<? super T>限制类型的下限,只能向下转型,可以写,但是没法读,因为父类型不确定,没法向上转型。

示例:

public class test {

    public static void main(String[] args) {
//<? extends B> 范围: A类或者A的子类
//由于下限不确定,所以无法向下转型至具体类型
List<? extends B> list1 = new ArrayList<B>(){{add(new B());}};
// list1.add(new B()); //无法添加该类型, 向下转型无法确定目标类型
// list1.add(new C());
A a = list1.get(0); //正常向上转型 //<? super B> 范围: B类或者B的父类
//由于上限不确定,所以B类和B类的子类均可以加入,但是B类的父类不行
List<? super B> list2 = new ArrayList<>();
// list2.add(new A()); //无法向下转型
list2.add(new B()); //正常向上转型
list2.add(new C());
// C c = list2.get(0);//无法向下转型,不加强制转换会报错
C c = (C)list2.get(0);
}
// A -> B -> C
static class A {};
static class B extends A {};
static class C extends B {};
}

4, 附加约束(&)

AdditionalBound 的语法如下:

TypeBound:
extends ClassOrInterfaceType {AdditionalBound}
AdditionalBound:
& InterfaceType

也就是说extends后面可以在加个额外约束,具体为接口类型,可以I1 & I2 & I3这样连排,注意必须是接口类型,不能是class或者类型变量,这里额外约束的作用是限制类型必须实现相关的接口,示例如下:

public class test {

    public static void main(String[] args) {
test1(1); test1("1");
test2(2); test2("2");
// test3(3); //test3方法String类型才满足额外约束
test3("3");
} public static <T extends Object> void test1(T t) {
System.out.println(t.getClass());
}
//得同时实现Serializable和Comparable接口
public static <T extends Object & Serializable & Comparable> void test2(T t) {
System.out.println(t.getClass());
}
//得同时实现Serializable,CharSequence和Comparable接口
public static <T extends Object & Serializable & CharSequence & Comparable> void test3(T t) {
System.out.println(t.getClass());
}
}

此外,附加约束还可用于类型强制转换:

public class test12 {
public static void main(String[] args) {
System.out.println(test());
}
public static Object test() {
// return (Object & Number)"abced"; //编译不通过
// return (Object)"abced"; //编译通过
return (Object & CharSequence & Comparable)"abcde"; //编译通过
}
}

在一些类型转换的场景可以通过附加约束控制类型转换的范围。

参考链接:

https://codeday.me/bug/20190313/767875.html

https://juejin.im/post/5b614848e51d45355d51f792

https://www.cnblogs.com/whatlonelytear/p/11055126.html

https://blog.csdn.net/s10461/article/details/53941091

https://blog.csdn.net/claram/article/details/51943742

java8泛型的更多相关文章

  1. java8 泛型声明 The diamond operator ("<>") should be used

    The diamond operator ("<>") should be used Java 7 introduced the diamond operator (& ...

  2. java8之stream

    lambda表达式是stream的基础,初学者建议先学习lambda表达式,http://www.cnblogs.com/andywithu/p/7357069.html 1.初识stream 先来一 ...

  3. java代码之美(2)---Java8 Stream

    Stream 第一次看到Stream表达式就深深把我吸引,用它可以使你的代码更加整洁而且对集合的操作效率也会大大提高,如果你还没有用到java8的Stream特性,那就说明你确实out啦. 一.概述 ...

  4. java代码(2)---Java8 Stream

    stream Java8新特性Stream流,那Stream表达式到底是什么呢,为什么可以使你的代码更加整洁而且对集合的操作效率也会大大提高? 一.概述 1.什么是Stream Stream是一种可供 ...

  5. java8中lambda表达式的应用,以及一些泛型相关

    语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...

  6. 20190920 On Java8 第二十章 泛型

    第二十章 泛型 多态的泛化机制: 将方法的参数类型设为基类: 方法以接口而不是类作为参数: 使用泛型: 泛型实现了参数化类型 简单泛型 Java 泛型的核心概念:你只需告诉编译器要使用什么类型,剩下的 ...

  7. Java 8 新特性之泛型的类型推导

    1. 泛型究竟是什么? 在讨论类型推导(type inference)之前,必须回顾一下什么是泛型(Generic).泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据 ...

  8. java基础-泛型2

    浏览以下内容前,请点击并阅读 声明 6 类型推测 java编译器能够检查所有的方法调用和对应的声明来决定类型的实参,即类型推测,类型的推测算法推测满足所有参数的最具体类型,如下例所示: //泛型方法的 ...

  9. java8 ArrayList源码阅读

    转载自 java8 ArrayList源码阅读 本文基于jdk1.8 JavaCollection库中有三类:List,Queue,Set 其中List,有三个子实现类:ArrayList,Vecto ...

随机推荐

  1. Leetcode之深度优先搜索(DFS)专题-130. 被围绕的区域(Surrounded Regions)

    Leetcode之深度优先搜索(DFS)专题-130. 被围绕的区域(Surrounded Regions) 深度优先搜索的解题详细介绍,点击 给定一个二维的矩阵,包含 'X' 和 'O'(字母 O) ...

  2. 答辩过了,但我知道我写的是一坨shi

    如果时间可以重来, 请好好珍惜大学里最重要的一份答卷. 以后的你会发现, 这种完全独立做出科研成果的机会, 可能不会再有. 1.保研了,才发现科研是多么难的一件事. 一直以来,读的喜欢的专业,考试成绩 ...

  3. CodeForces 402 E Strictly Positive Matrix

    Strictly Positive Matrix 题解: 如果原来的 a[i][j] = 0, 现要 a[i][j] = 1, 那么等于 sum{a[i][k] + a[k][j]} > 1. ...

  4. 2019 HZNU Winter Training Day 14 Comprehensive Training

    A - Choosing Capital for Treeland CodeForces - 219D 题意:有一颗单向边的树,要选取一个结点作为首都.要求是这个结点到其它结点,总共需要翻转的路径数量 ...

  5. poj 1182 食物链(种类并查集 ‘初心者’)

    题目链接:http://poj.org/problem?id=1182 借着这题可以好好理解一下种类并查集,这题比较简单但挺经典的. 题意就不解释了,中问题. 关于种类并查集结局方法也是挺多的 1扩增 ...

  6. MongoDb 快速翻页方法

    翻阅数据是MongoDB最常见的操作之一.一个典型的场景是需要在你的用户界面中显示你的结果.如果你是批量处理的数据,同样重要的是要让你的分页策略正确,以便你的数据处理可以规模化. 接下来,让我们通过一 ...

  7. 技术漫谈 | 远程访问和控制云端K8S服务器的方法

    对于部署在云端的K8S容器编排系统,可以先通过SSH远程登录到K8S所在主机,然后运行kubectl命令工具来控制K8S服务系统.然而,先SSH登录才能远程访问的二阶段方式,对于使用Linux桌面或者 ...

  8. velocity中文乱码

    当使用velocity出现中文乱码. 首先:我们设置 eclipse的编码方式 : 右键工程师属性->properties->查看编码格式是否伟URF-8 然后:spring-xml文件中 ...

  9. 每天学会一点点(HashMap实现原理及源码分析)

    HashMap实现原理及源码分析   哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希 ...

  10. windows系统下安装JDK8

    学习JAVA,必须得安装一下JDK(java development kit java开发工具包),配置一下环境就可以学习JAVA了,下面是下载和安装JDK的教程: 一.下载 1.JDK下载地址: h ...