很多使用泛型的小伙伴,都会有一个疑惑:为什么有的方法返回值前带<T>、<K, V>之类的标记,而有的方法返回值前又什么都不带呢?就像这样:

// 实体基类
class Entity {
public String toString() {
return "Entity";
}
}
// 用户类
class User extends Entity {
public String toString() {
return "User";
}
}
// 用户Dao
class UserDao {
public String toString() {
return "UserDao";
}
} /**
* 带<E>标记与不带<E>标记的比较
*/
public class GenericsClass<T extends Entity> {
// 不带标记
public void notSign(T t) {
System.out.println("notSign " + t.toString());
} // 带<T>标记
public <T> void hasSign(T e) {
System.out.println("hasSign " + e.toString());
} public static void main(String[] args) {
GenericsClass<Entity> clazz = new GenericsClass<>();
Entity entity = new Entity();
User user = new User();
UserDao userDao = new UserDao(); System.out.println("不带标记的方法:");
clazz.notSign(entity);
clazz.notSign(user);
// 不能编译通过的
// 因为在GenericsClass<T extends Entity>中已经限定了全局的T为Entity及其子类,
// 所以不能再加入UserDao;
// clazz.notSign(userDao); System.out.println("带标记的方法:");
clazz.hasSign(entity);
clazz.hasSign(user);
// 带上前缀<E>,就是在告诉编译器:这是新指定的一个类型,代表该方法自己独有的某个类,
// 跟GenericsClass<T extends Entity>中的Entity及其子类没有任何关系
// 或者说
// hasSign方法重新定义泛型T、隐藏或者代替了GenericsClass<T>中的T,不再受限于Entity及其子类
clazz.hasSign(userDao);
}
}

因此,返回值前面的<T>的作用是「重新定义泛型」,因此方法参数类型不受对象泛型类型的限制。在Java新的Stream API中有大量这种带前缀的用法,例如:

ArrayList.java:public <T> T[] toArray(T[] a)

Optional.java:public static <T> Optional<T> of(T value)

Collectors.java:public static <T> Collector<T, ?, List<T>> toList()

泛型,作为Java的一个基础特性,并不是一点毛病都没有,「泛型擦除」就是至今还未解决的一个问题(这个问题其实对于大多数人来说可以不用知道,因为实际应用中极少出现这种场景,感兴趣的话稍稍了解一下,不喜可绕过)。

所谓泛型擦除,是这样一个问题:

class User {}
class Product {}
class Shop<V> {}
class Particle<PPP, QQQ> {} public class LostInformation<T> {
public static void main(String[] args) {
// ArrayList<String>和ArrayList<Integer>应该是不同的类型,但结果是它们完全相等
Class<?> c1 = new ArrayList<String>().getClass();
Class<?> c2 = new ArrayList<Integer>().getClass();
System.out.println(c1 == c2); // 无法从泛型获得任何有关参数类型的信息
List<User> list = new ArrayList<>();
Map<User, Product> map = new HashMap<>();
Shop<User> shop = new Shop<>();
Particle<Long, Double> p = new Particle<>();
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
System.out.println(Arrays.toString(shop.getClass().getTypeParameters()));
System.out.println(Arrays.toString(p.getClass().getTypeParameters()));
}
}

可以看见,Particle<Long, Double>中关于Long和Double的信息已经完全丢失了,只剩下了最初的PPP和QQQ,真的应了那句话:历经千帆,归来仍是是少年!

但这是编程啊,不是文案啊~,不能这样丢掉了!

KTV和泛型(2)的更多相关文章

  1. KTV和泛型(3)

    泛型除了KTV,还有一个让人比较疑惑的玩意,而且它就是用来表达疑惑的:? 虽然通过泛型已经达到我们想要的效果了,例如: List<String> list = new ArrayList& ...

  2. java——集合、泛型、ArrayList、LinkedList、foreach循环、模拟ktv点歌系统

    集合:一系列特殊的类,这些类可以存储任意类型的对象,长度可变,集合类都在java.util包中. 但是集合记不住对象的类型,当把对象从集合中取出时这个对象的编译类型就变成了Object类型.这样在取元 ...

  3. 一起学 Java(三) 集合框架、数据结构、泛型

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  4. .NET面试题系列[8] - 泛型

    “可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用.“ - Jon Skeet .NET面试题系列目录 .NET面试题系列[1] - .NET框架基础知识(1) .NET面试题系列[2] ...

  5. C#4.0泛型的协变,逆变深入剖析

    C#4.0中有一个新特性:协变与逆变.可能很多人在开发过程中不常用到,但是深入的了解他们,肯定是有好处的. 协变和逆变体现在泛型的接口和委托上面,也就是对泛型参数的声明,可以声明为协变,或者逆变.什么 ...

  6. 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)

    建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...

  7. 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  8. C#泛型详解(转)

    初步理解泛型: http://www.cnblogs.com/wilber2013/p/4291435.html 泛型中的类型约束和类型推断 http://www.cnblogs.com/wilber ...

  9. C# 泛型

    C# 泛型 1.定义泛型类 在类定义中包含尖括号语法,即可创建泛型类: class MyGenericClass<T> { //Add code } 其中T可以遵循C#命名规则的任意字符. ...

随机推荐

  1. 面试突击71:GET 和 POST 有什么区别?

    GET 和 POST 是 HTTP 请求中最常用的两种请求方法,在日常开发的 RESTful 接口中,都能看到它们的身影.而它们之间的区别,也是一道常见且经典的面试题,所以我们本文就来详细的聊聊. H ...

  2. GreatSQL季报(2021.12.26)

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 自从GreatSQL 8.0.25 于 2021.8.26发布以来,针对MGR的 ...

  3. 【喜讯】Apache DolphinScheduler 荣获 “2020 年度十大开源新锐项目”

    经 10000+ 开发者公开票选,20+专家评审. 10+ 主编团打分,历经数月打磨,11 月 19 日,由InfoQ 发起并组织的[2020中国技术力量年度榜单评选]结果正式揭晓. 2020 年度十 ...

  4. 个人开源项目如何上传maven中央仓库

    最近在写一些开源项目,想把自己写的东西放到maven中央仓库,提供给更多的人使用.所以写这一篇文章,记录一下自研开源项目jar包上传同步maven中央仓库成功的整个过程,这其中还是有不少的坑的. 目录 ...

  5. Git 10 IDEA撤销推送

    参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 如果推送了多 ...

  6. MyBatis 01 概述

    官网 http://www.mybatis.org/mybatis-3/zh/index.html GitHub https://github.com/mybatis/mybatis-3 简介 MyB ...

  7. Ceph创建一个新集群 报错: File "/usr/bin/ceph-deploy", line 18, in..........

    [root@ceph-node1 ceph]# ceph-deploy new node1 Traceback (most recent call last): File "/usr/bin ...

  8. 完整实现-通过DelayQueue实现延时任务

    实现延时任务有很多的方法,网上关于延时任务的实现的文章已经不少了.比如:实现延时任务的10种方法等等.但是这些文章基本上都是将方法大概的列举一下,给出部分示例代码,对于有经验的老程序员可能一看就知道该 ...

  9. Java SE 15 新增特性

    Java SE 15 新增特性 作者:Grey 原文地址:Java SE 15 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  10. 【NOI P模拟赛】仙人掌(圆方树,树形DP)

    题面 n n n 个点, m m m 条边. 1 ≤ n ≤ 1 0 5 , n − 1 ≤ m ≤ 2 × 1 0 5 1\leq n\leq 10^5,n-1\leq m\leq 2\times1 ...