sob博客(Java泛型T、E、K、V、N、?和Object区别和含义)

Java泛型T、E、K、V、N、?和Object区别和涵义

通常我们在看一些源码时,发觉满是T、?,晕乎乎的:sob:。于是,把泛型把握好十分紧张!

什么是泛型

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时典范宁静检测机制,该机制允许步骤员在编译时检测到不法的典范。

泛型的实质是参数化典范,也就是说所利用的数据典范被指定为一个参数。

泛型有什么利益?写个例子一清二楚:

我们要封装一个消息呼应类:

public class Result implements Serializable { // 呼应码 Integer code; // 对否告捷 Boolean success; // 前往体数据 User user; public Result(Integer code, Boolean success, User user) { this.code = code; this.success = success; this.user = user; } @Override public String toString() { return "Result{" + "code=" + code + ", success=" + success + ", user=" + user + '}'; } public static void main(String[] args) { User user = new User(1, "Tony"); Result result = new Result(200, true, user); System.out.println(result); } } class User implements Serializable { Integer id; String name; public User(Integer id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }

Result{code=200, success=true, user=User{id=1, name='Tony'}} 历程已完毕,退去代码0

呼~如此这个反响体就可以前往哀求形态和用户信息了。可如今需求又必要前往关于手机的信息,那我们又得封装一个能前往手机信息的呼应类了...到后方另有衣服、鞋子...那不得累死?这时分泛型下场了:

public class Result<T> implements Serializable { // 呼应码 Integer code; // 对否告捷 Boolean success; // 前往体数据 T data; public Result(Integer code, Boolean success, T data) { this.code = code; this.success = success; this.data = data; } @Override public String toString() { return "Result{" + "code=" + code + ", success=" + success + ", data=" + data + '}'; } public static void main(String[] args) { User user = new User(1, "Tony"); Result<User> resultUser = new Result<>(200, true, user); System.out.println(resultUser); Phone phone = new Phone(999.99, "Yellow"); Result<Phone> resultPhone = new Result<>(200, true, phone); System.out.println(resultPhone); } } class User implements Serializable { Integer id; String name; public User(Integer id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } } class Phone implements Serializable { Double price; String color; @Override public String toString() { return "Phone{" + "price=" + price + ", color='" + color + '\'' + '}'; } public Phone(Double price, String color) { this.price = price; this.color = color; } }

Result{code=200, success=true, data=User{id=1, name='Tony'}} Result{code=200, success=true, data=Phone{price=999.99, color='Yellow'}} 历程已完毕,退去代码0

可见,使用泛型,可以一致标识必要前往的实体类。不管你来什么类,我都可以给你塞进入!

第一次交往约莫看不太明白,底下就具体解说

泛型办法

你可以写一个泛型办法,该办法在调用时可以吸收不同典范的参数。依据转达给泛型办法的参数典范,编译器得当地处理每一个办法调用。

语法例则

  • 一切泛型办法声明都有一个典范参数声明局部(由尖括号分开),该典范参数声明局部在办法前往典范之前

好比说这是一个用来打印数组的泛型办法:

private static <E> void printArray(E[] inputArray)

  • 每一个典范参数声明局部包含一个或多个典范参数,参数间用逗号离隔。一个泛型参数,也被称为一个典范变量,是用于指定一个泛型典范称呼的标识符。

好比这个办法

private static <E,T> void printArray(E[] inputArray, T data)

  • 典范参数能被用来声明前往值典范,并且能作为泛型办法取得的实践参数典范的占位符
  • 泛型办法体的声明和其他办法一样。注意典范参数只能代表引用型典范,不克不及是原始典范(int double char等)

泛型标志符

  • E Element 聚集元素
  • T Type Java类
  • K Key 键
  • V Value 值
  • N Number 数值典范
  • ? 表现不确定的Java典范

这些标志并不是限定仅有对应的典范才干使用,即使你一致使用A-Z英笔墨母的此中一个,编译器也不会报错。之以是又不同的标志符,这是一种商定。在开发中很多端正都是一种商定,它能提高我们代码的可读性,便利团队见的互助开发

写个完备的例子:

public class TFunction { public static void main(String[] args) { // 创建种品种型的数组 Integer[] intArray = {1, 2, 3, 4, 5}; Double[] doubleArray = {1.1, 2.2, 3.3, 4.4}; Character[] charArray = {'H', 'E', 'L', 'L', 'O'}; System.out.println("整型数组元素为:"); printArray(intArray); // 转达一个整型数组 System.out.println("\n双精度型数组元素为:"); printArray(doubleArray); // 转达一个双精度型数组 System.out.println("\n字符型数组元素为:"); printArray(charArray); // 转达一个字符型数组 } // 泛型办法 private static <E> void printArray(E[] inputArray) { // 遍历打印数组 Arrays.stream(inputArray).forEach(e -> { System.out.printf("%s ", e); }); System.out.println(); } }

泛型类

泛型类的声明与非泛型类几乎相反,唯一的不同在于类名的后方添加了参数声明局部

这边就不举例子了,由于开篇的例子就是封装了一个泛型类,事先不太了解的可以再回去看一下

典范通配符

我们寻常可以使用?来承接一切的引用典范,搬运一个菜鸟上的例子:

public class GenericTest { public static void main(String[] args) { List<String> name = new ArrayList<String>(); List<Integer> age = new ArrayList<Integer>(); List<Number> number = new ArrayList<Number>(); name.add("icon"); age.add(18); number.add(314); getData(name); getData(age); getData(number); } public static void getData(List<?> data) { System.out.println("data :" + data.get(0)); } }

data :icon data :18 data :314

?extends T

这是泛型上界限:仅有T目标的子类可以被传入

假如是? extends C,那么仅有D和E允许被传入,不然会编译报错

? super T

这是泛型下界限:仅有T目标的父类可以被传入

假如是? super D,那么仅有C和A允许被传入,不然会编译报错

T 和 ?

不晓得看到这里,有没有疑惑。T和?仿佛作用差不多啊,有什么区别?

这里表明一下,T寻常作为泛型参数,而?是更多是用来一个不确定的引用典范,意会一下吧~~~

T 和 Object

重头戏!!

晓得的Object的同道都了解其是Java的超类(一切目标的父类),不了解的可以去看看我的博客,有做具体的表明。

那么成绩就来了,Object仿佛可以代替泛型的功效啊!一切能用到泛型的场合Object都可以!

但是,在JDK5之前,都是用的Object,但其存在很多的成绩,JDK5之后便引入了泛型

Object是一切类的父类,在编码历程中就不免显现典范转化成绩,且在编译阶段不会报错,到了运转阶段才暴露成绩,大大低落了步骤的宁静性健壮性

举例之前说一些转型的分类:

  • 向上转型 用父类声明一个子类目标 比如:Animal是Cat的父类,在声明时我们这么写:

Animal cat = new Cat();

  • 向下转型
  • 将父类目标强转为其子类实例:

Animal cat = new Cat(); Cat anotherCat = (Cat) cat;

以是当我们使用Object作为泛型来使用时,不仅写起来贫苦,还要不休的举行典范转化,还很容易显现成绩,很逊的诶~

举个例子看看:

使用Object界说了一个数字变量,我们知识将其向下转型为Integer和String。将一个数字转型为字符串是一件怪诞的事变,可编译器并不克不及发觉这件事,直到步骤运转了起来...

典范转换特别!!!

总结

泛型的显现,当典范转化显现成绩的时分,在编译阶段就会暴显露来。处理了Object存在的诸多成绩,让代码愈加优雅,步骤愈加宁静,愈加健壮。

作者:不想起床的小张
链接:
https://juejin.cn/post/7072703705811779620

sob博客(Java泛型T、E、K、V、N、?和Object区别和含义)

本站资源均来源于互联网,仅提供信息存储空间服务,用于学习交流,如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 dhh0407@outlook.com 举报,一经查实,本站将立刻删除。

本文链接:https://6wyx.com/post/238086.html

发表列表

评论列表

还没有评论,快来说点什么吧~