java魔功心法-范型篇

打印 上一主题 下一主题

主题 994|帖子 994|积分 2986

前言:
https://www.cnblogs.com/LoveBB/p/17277662.html
什么是范型

JDK 1.5开始引入Java泛型(generics)这个特性,该特性提供了编译时类型安全检测机制,允许程序员在编译时检测到非法的类型。停,废话就不多说了,这些术语,自己去百度看看吧,反正不管你看不看得懂,我就要把你教懂,所以,这里不是重点。
泛型的作用

泛型有四个作用:类型安全、自动转换、性能提升、可复用性。即在编译的时候检查类型安全,将所有的强制转换都自动和隐式进行,同时提高代码的可复用性。着实是废话,但是不说又不行,生怕你们把路走弯了。
泛型的使用


  • 我们写代码,不也是这几样嘛:类、接口、方法。
泛型类


  • 来个3简单的类,为了让我们看清楚,类的结构
正经类
  1. public class Student {
  2.   
  3. }
复制代码
  1. public class Teacher {
  2.   
  3. }
复制代码
  1. public class Room {
  2.   
  3. }
复制代码
这谁不会啊,嘿嘿,别着急,这一般就是我们修炼的名门正派功法,这是很标准的"正派"写法。接下来,使用魔教功法进行魔改。
范型类结构
  1. public class 类名 <泛型类型1,...> {
  2. // todo
  3. }
复制代码
范型类


  • 一个范型
简简单单
  1. public class Student {
  2.   
  3. }
复制代码

  • 两个范型
我好像在骂人,但是你没哟证据
  1. public class Student<S,B> {
  2. }
复制代码

  • 三个范型
这里注意,范型里面的 S, B, Q 都是自定义的,一般用大些字母表示,个数不限
  1. public class Student<S,B> {
  2. }
复制代码

  • N 个范型
嘿嘿,个数不限,那就来个不限的吧
  1. public class Student<S,B> {
  2. }
复制代码

  • 关于字母
有人说,字母就26个啊,你写重复的话,那不是一样了嘛。对,你是对的,但是魔教功法就在于,他不讲道理,谁说一定要使用大写字母了,下面来个逼死强迫症写法,什么叫无限火力
  1. public class Student {
  2.   
  3. }
复制代码
怎么样,好好的一个类,经过魔教功法的改造,是不是看起来不一样了。


  • 一般规定
虽然我们可以乱写,但是魔教功法还是很讲武德的,一般关于大些字母的定义如下
  1. T:任意类型 type
  2. E:集合中元素的类型 element
  3. K:key-value形式 key
  4. V: key-value形式 value
  5. N: Number(数值类型)
  6. ?: 表示不确定的java类型
复制代码
对比


  • 为了加深记忆,我们前后在对比一下
  1. // 改造前public class Student {
  2.   
  3. }// 改造后public class Student {
  4.   
  5. }
复制代码
实例化


  • 那我们范型类应该怎么样实例化呢,请看下面正派写法
  1. // 正经写法
  2. Student student = new Student();
  3. // 范型写法
  4. Student<T> student = new Student<>();
  5. // 案例1
  6. Student<String> student = new Student<>();
  7. // 案例2
  8. Student<Integer> student = new Student<>();
  9. // 案例3
  10. Student<Teacher> student = new Student<>();
  11. // 案例4:前面都没意思,来试试套娃吧,哈哈,走火入魔了没有,魔功就是魔功,这里自己动手,这样才清晰
  12. Student<Student<Student<Student<Student<String, Student<String, Long>>, Boolean>, Integer>, String>, Student<String, Integer>> student = new Student<>();
  13. // 案例5:那个最长的,我实在懒得写了,后面全部用String代替了
  14.     Student<
  15.             String,
  16.             BigDecimal,
  17.             Integer,
  18.             Boolean,
  19.             Long,
  20.             Double,
  21.             Room,
  22.             Teacher,
  23.             String,
  24.             String,
  25.             String,
  26.             String,
  27.             String,
  28.             String,
  29.             String,
  30.             String,
  31.             String
  32.             > student = new Student<>();
复制代码
咱就是说,用了魔教功法之后,我们 new 出来的对象,想传什么就传什么,有多少个范型参数,就传多少个对象进去。总之就一句话,很强,运用好了,绝对是秒天秒地秒空气。
泛型接口

看过范型类了,那接下来就是接口。说实在的,接口的使用率比类高很多很多
正经接口
  1. public interface Student {
  2.   // todo
  3. }
复制代码
范型接口结构
  1. public interface 接口名<T> {
  2.   // todo
  3. }
复制代码
范型接口


  • 两个参数
  1. public interface Student<T> {
  2.     // todo
  3. }
复制代码

  • 两个参数
  1. public interface Student<T> {
  2.     // todo
  3. }
复制代码

  • 三个参数
停,就到这里吧,再写下去就不礼貌了,参数是和类一样的,可以N个,英文字母不限大小。
对比
  1. // 改造前public interface Student<T> {
  2.     // todo
  3. }// 改造后public interface Student<T> {
  4.     // todo
  5. }
复制代码

  • 实例化
中所周知,接口只能用实现的方式类实例化,java8之后还能用函数式编程,这次就不展开来说了
  1. // 正经实现
  2. public class GoodStudent implements Student{
  3.    
  4. }
  5. // 范型实现
  6. public class GoodStudent<T> implements Student<T>{
  7.    
  8. }
  9. // 这里不用T可不可以呢,可以的,只要子类和父类的范型一样就行
  10. public class GoodStudent<B> implements Student<B>{
  11. }
  12. // 实战1
  13. public class GoodStudent<String> implements Student<String>{
  14. }
  15. // 实战2
  16. public class GoodStudent<Integer> implements Student<Integer>{
  17. }
  18. // 实战N,别忘记了我们还能套娃,还能无限火力N,这里就不演示了
复制代码

  • 那子类和父类的范型不一样呢,那就编译器报错呗
![image-20230331231845229](/Users/zhangch/Library/Application Support/typora-user-images/image-20230331231845229.png)
使用方式

那说了那么多,这个范型有什么用呢,答案是:接口、类声明中定义的类型形参则可以在整个接口、类中使用。
可以作为参数类型,入参,返回值使用

  • 范型使用
  1. public class GoodStudent<T> implements Student<T>{
  2.     // 范型作为参数类型
  3.     private T personality;
  4.                 // 范型接口1,作为入参
  5.     public void evaluation(T t){
  6.         
  7.     }
  8.           // 范型接口2,作为入参和返回值
  9.     public T evaluation2(T t){
  10.         return t;
  11.     }
  12. }
复制代码

  • 案例参考(比较容易看懂)
  1. // 实例化后很简单的,一看就懂,这就是我们正常的写法
  2. public class GoodStudent<String> implements Student<String>{
  3.     // 范型参数
  4.     private String personality;
  5.     public void evaluation(String t){
  6.     }
  7.     public String evaluation2(String t){
  8.         return t;
  9.     }
  10.    
  11. }
  12. // 案例2
  13. public class GoodStudent<Integer> implements Student<Integer>{
  14.     // 范型参数
  15.     private Integer personality;
  16.     public void evaluation(Integer t){
  17.     }
  18.     public Integer evaluation2(Integer t){
  19.         return t;
  20.     }
  21.    
  22. }
复制代码

  • 实例化
  1.     public static void main(String[] args) {
  2.                                 // String 类型
  3.         GoodStudent<String> goodStudent = new GoodStudent<>();
  4.         String personality = "";
  5.         goodStudent.evaluation(personality);
  6.         String result = goodStudent.evaluation2(personality);
  7.               // Integer 类型
  8.         GoodStudent<Integer> goodStudent = new GoodStudent<>();
  9.         Integer personality = "";
  10.         goodStudent.evaluation(personality);
  11.         Integer result = goodStudent.evaluation2(personality);
  12.       
  13.                      // 套娃类型,这里我就套一层,不然容易走火入魔
  14.         GoodStudent<GoodStudent<String>> goodStudent = new GoodStudent<>();
  15.         GoodStudent<String> personality = new GoodStudent<>();
  16.         // 内层
  17.         String resultString = personality.evaluation2("");
  18.         goodStudent.evaluation(personality);
  19.         // 外层
  20.         GoodStudent<String>  result = goodStudent.evaluation2(personality);
  21.     }
复制代码
泛型方法


  • 介绍范型方法之前,我们先看看普通方法,我们经常写的方法就是这样
正经方法
  1. // 无返回值,无入参
  2. public void test(){
  3.    
  4. }
  5. // 无返回值,有入参
  6. public void test(String s){
  7.    
  8. }
  9. // 有返回值,无入参
  10. public String test(){
  11.     return "";
  12. }
  13. // 有返回值,有入参
  14. public String test(String s){
  15.     return s;
  16. }
复制代码
范型方法结构
  1. // 范型方法就是加上一个范型声明
  2. public <泛型类型> 返回类型 方法名(泛型类型 变量名) {
  3.    // todo
  4. }
复制代码
范型演示(注意和之前正常的对比)
  1. // 无返回值,无入参(无意义)
  2. public <T> void test(){
  3.    
  4. }
  5. // 无返回值,有入参(不常用)
  6. public <T> void test(T s){
  7.    
  8. }
  9. // 有返回值,无入参(不太常用)
  10. public <T> T test(){
  11.     retrn null;
  12. }
  13. // 有返回值,有入参(经常用)
  14. public <T> T test(T s){
  15.     return s;
  16. }
复制代码
案例


  • 正经案例
  1. public class GoodStudent implements Student {
  2.     // 无返回值,无入参
  3.     public void test() {
  4.     }
  5.     // 无返回值,有入参
  6.     public void test2(String s) {
  7.     }
  8.     // 有返回值,无入参
  9.     public String test3() {
  10.         return "";
  11.     }
  12.     // 有返回值,有入参
  13.     public String test4(String s) {
  14.         return s;
  15.     }
  16. }
复制代码

  • 正经调用
  1. public static void main(String[] args) {
  2.     GoodStudent goodStudent = new GoodStudent();
  3.     goodStudent.test();
  4.     String s = "";
  5.     goodStudent.test2(s);
  6.     String s1 = goodStudent.test3();
  7.     String s2 = goodStudent.test4(s);
  8. }
复制代码

  • 范型案例
  1. public class GoodStudent implements Student {
  2.     // 无返回值,无入参(无意义)
  3.     public <T> void test(){
  4.     }
  5.     // 无返回值,有入参(不常用)
  6.     public <T> void test2(T s){
  7.     }
  8.     // 有返回值,无入参(不太常用)
  9.     public <T> T test3(){
  10.         return null;
  11.     }
  12.     // 有返回值,有入参(经常用)
  13.     public <T> T test4(T s){
  14.         return s;
  15.     }
  16. }
复制代码

  • 范型调用
  1. public static void main(String[] args) {
  2.            // String 范型
  3.      GoodStudent goodStudent = new GoodStudent();
  4.      goodStudent.test();
  5.      String s = "";
  6.      goodStudent.test2(s);
  7.      String s1 = goodStudent.test3();
  8.      String s2 = goodStudent.test4(s);
  9.   
  10.      // Integer 范型
  11.      GoodStudent goodStudent = new GoodStudent();
  12.      goodStudent.test();
  13.      Integer s = "";
  14.      goodStudent.test2(s);
  15.      Integer s1 = goodStudent.test3();
  16.      Integer s2 = goodStudent.test4(s);
  17.   
  18.      // Student<String> 范型
  19.      GoodStudent goodStudent = new GoodStudent<>();
  20.      goodStudent.test();
  21.      Student<String> s = new GoodStudent<>();
  22.      goodStudent.test2(s);
  23.      Student<String> s1 = goodStudent.test3();
  24.      Student<String> s2 = goodStudent.test4(s);
  25.   
  26. }
复制代码
范型方法是传什么参数,就是什么返回值
泛型通配符(上下界)

你以为这就完了?要放大招了。
Java泛型的通配符是用于解决泛型之间引用传递问题的特殊语法, 主要有以下三类:

  • 无边界的通配符,使用精确的参数类型
  • 关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类
  • 关键字声明了类型的下界,表示参数化的类型可能是指定的类型,或者是此类型的父类
无边界更多是服务于上届和下届的
  1. // 表示类型参数可以是任何类型
  2. public class B<?> {
  3. }
  4. // 上界:表示类型参数必须是A或者是A的子类
  5. public class B<T extends A> {
  6. }
  7. // 下界:表示类型参数必须是A或者是A的超类型
  8. public class B<T supers A> {
  9. }
复制代码
正常类
  1. public class GoodStudent implements Student{
  2.     // String参数
  3.     private String personality;
  4.                 // String 作为入参
  5.     public void evaluation(String t){
  6.         
  7.     }
  8.           // String作为入参和返回值
  9.     public String evaluation2(String t){
  10.         return t;
  11.     }
  12. }
复制代码

  • 范型类
  1. public class GoodStudent<T> implements Student<T>{
  2.     // 范型参数
  3.     private T personality;
  4.                 // 范型接口1,作为入参
  5.     public void evaluation(T t){
  6.         
  7.     }
  8.           // 范型接口2,作为入参和返回值
  9.     public T evaluation2(T t){
  10.         return t;
  11.     }
  12. }
复制代码

  • 下界范型
  1. public class GoodStudent<T extends String> implements Student<T> {
  2.     // 范型参数
  3.     private T personality;
  4.     // 范型接口1,作为入参
  5.     public void evaluation(T t){
  6.     }
  7.     // 范型接口2,作为入参和返回值
  8.     public T evaluation2(T t){
  9.         return t;
  10.     }
  11. }
复制代码
到这里,我已经走火入魔了,后续的后面在写了,从这里我们也能看出,一个“正派”的类,经过”魔教“功法范型的改造之后,已经具备一定的复杂性了。这就是 魔功-范型 带来的威力。
  1. // 改造前public class GoodStudent implements Student{
  2.     // String参数
  3.     private String personality;
  4.                 // String 作为入参
  5.     public void evaluation(String t){
  6.         
  7.     }
  8.           // String作为入参和返回值
  9.     public String evaluation2(String t){
  10.         return t;
  11.     }
  12. }// 改造后public class GoodStudent<T extends String> implements Student<T> {
  13.     // 范型参数
  14.     private T personality;
  15.     // 范型接口1,作为入参
  16.     public void evaluation(T t){
  17.     }
  18.     // 范型接口2,作为入参和返回值
  19.     public T evaluation2(T t){
  20.         return t;
  21.     }
  22. }
复制代码
出处:https://www.cnblogs.com/LoveBB/本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

刘俊凯

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表