文章目录

目录

零、概念

一、泛型的优点

1.1优点

1.2为什么要使用泛型

二、泛型使用与不使用的区别

1、泛型的没有使用会造成什么后果呢?

2.添加泛型的使用会发生什么效果呢?

【一、二】 知识点小结

关于包装类的延伸知识点

包装类

三、自定义泛型结构

3.1泛型类举个栗子

3.1.1 OrderTest类

3.2自定义泛型类的子类怎么处理?

3.3、在继承情况中使用泛型

3.4自定义泛型方法

3.4.1泛型⽅法说明: ⽅法也可以被泛型化,不管此时定义在其中的类是不是泛型类。 在泛型⽅法中可以定义泛型参数,此时,参数的类型就是传⼊数据的类型。 泛型⽅法在调⽤时候确定类型。

3.4.2泛型⽅法的格式

3.4.3、子类重写泛型方法

3.5、泛型类和泛型方法的使用情景

四、通配符的使用

4.1概念

4.2使用场景

4.3具体使用说明

总结:



零、概念

泛型:

他是 JDK5 中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数
    
# 常见的泛型的类型表示
上面的 T 仅仅类似一个形参的作用,名字实际上是可以任意起的,但是我们写代码总该是要讲究可读性的。常见的参数通常有 :
    E - Element (在集合中使用,因为集合中存放的是元素)
    T - Type(表示Java 类,包括基本的类和我们自定义的类)
    K - Key(表示键,比如Map中的key)
    V - Value(表示值)
    ? - (表示不确定的java类型)

但是泛型的参数只能是类类型,不能是基本的数据类型,他的类型一定是自Object的

————————————————
原文链接:https://blog.csdn.net/bjweimengshu/article/details/117793971


一、泛型的优点

1.1优点

1.提交了java的类型安全
    泛型在很大程度上来提高了java的程序安全。例如在没有泛型的情况下,很容易将字符串 123 转成 Integer 类型的 123 亦或者 Integer 转成 String,而这样的错误是在编译期无法检测。而使用泛型,则能很好的避免这样的情况发生。
 
 2.不需要烦人的强制类型转换
    泛型之所以能够消除强制类型转换,那是因为程序员在开发的时候就已经明确了自己使用的具体类型,这不但提高了代码的可读性,同样增加了代码的健壮性。
    
3. 提高了代码的重用性
    泛型的程序设计,意味着编写的代码可以被很多不同类型的对象所重用

1.2为什么要使用泛型

1、解决元素存储的安全性问题,好⽐商品、药品标签,不会弄错。

2.解决获取数据元素时,需要类型强制转换的问题,好⽐不⽤每回拿商品、药品都要辨别。

2、Java泛型可以保证如果程序在编译时没有发出警告,运⾏时就不会产⽣ClassCastException异常。同时,代码更加简洁、健壮。


二、泛型使用与不使用的区别

1、泛型的没有使用会造成什么后果呢?

import org.junit.Test;
import java.util.ArrayList;
/*** 泛型的使⽤* 1.jdk5.0新增的特征*/public class GenericTest {//在集合中使⽤泛型之前的情况:@Testpublic void test(){ArrayList list = new ArrayList();//需求:存放学⽣的成绩list.add(78);list.add(49);list.add(72);list.add(81);list.add(89);//问题⼀:类型不安全// list.add("Tom");for(Object score : list){//问题⼆:强转时可能出现类型转化异常int stuScore = (Integer)score;System.out.println(stuScore);}}
}

那我们发现,没有添加泛型的时候呢,我们可以向list集合添加各种各样类型的数据,那么就会导致在数据类型转换的时候发生异常,那么我们添加泛型的好处也是很明显的了。

2.添加泛型的使用会发生什么效果呢?

public class GenericTest {//!在集合中使⽤泛型的情况:以ArrayList为例@Testpublic void test2(){//注意点:泛型的类型必须是类,不能是基本数据类型。需要⽤到基本数据类型的位置,拿包装类替换//看图例这⾥规定泛型是Integer,使⽤add⽅法的时候也是IntegerArrayList<Integer> list = new ArrayList<Integer>();list.add(78);list.add(49);list.add(72);list.add(81);list.add(89)//编译时,就会进⾏类型检查,保证数据的安全
// list.add("Tom");//⽅式⼀:
// for(Integer score :list){
// //避免了强转的操作
// int stuScore = score;
//
// System.out.println(stuScore);
// }//⽅式⼆:Iterator<Integer> iterator = list.iterator();while(iterator.hasNext()){int stuScore = iterator.next();System.out.println(stuScore);}}//在集合中使⽤泛型的情况:以HashMap为例@Testpublic void test3(){// Map<String,Integer> map = new HashMap<String,Integer>();//jdk7新特性:类型推断, 实例化的时候就可以不⽤写泛型,空即可Map<String,Integer> map = new HashMap<>();map.put("Tom",87);map.put("Tone",81);map.put("Jack",64);
// map.put(123,"ABC");//泛型的嵌套Set<Map.Entry<String,Integer>> entry = map.entrySet();Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();while(iterator.hasNext()){Map.Entry<String, Integer> e = iterator.next();String key = e.getKey();Integer value = e.getValue();System.out.println(key + "----" + value);}}}

使用了泛型,就可以达到很多方便开发的效果,可以实现泛型的嵌套,也不用担心数据转换异常问题,有错误编译期间就会报错。


【一、二】 知识点小结

经过知识总结归纳,到目前的泛型学习,有几个知识点需要注意:

① 泛型是在JDK1.5版本之后出现的,改写了集合框架中所有的接口和类,为他们提供泛型的支持,从⽽可以在声明集合变量、创建集合对象时传⼊类型实参。

②泛型的出现使集合类型安全

需要注意的是,泛型的类型必须是类,不能是基本数据类型。需要⽤到基本数据类型的位置,拿包装类替换。

如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。

关于包装类的延伸知识点

包装类

每个基本数据类型都提供了一个包装类,使用对应的包装类对象,对对应类型的数据进行了封装,又提供相应的方法对其封装的数据可以进行一些操作。

包装类(基本概念和一些使用方法)_Vicali的博客-CSDN博客_什么是包装类

三、自定义泛型结构

有三种结构:泛型类、泛型接口,泛型方法

注意:↓

1.泛型类可以有多个参数,<E1,E2,E3>

2.泛型不同的引⽤不能相互赋值。尽管在编译时ArrayList和ArrayList是两种类型,但是,在运⾏时只有⼀个ArrayList被加载到JVM中。

@Testpublic void test3(){ArrayList<String> list1 = null;ArrayList<Integer> list2 = new ArrayList<Integer>();//泛型不同的引⽤不能相互赋值。//list1 = list2;Person p1 = null;Person p2 = null;p1 = p2;}

3.泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价于Object(继承⽅⾯的区别)。经验:泛型要使⽤⼀路都⽤。要不⽤,⼀路都不要⽤。

4.jdk1.7,泛型的简化操作类型推断:ArrayList flist = new ArrayList<>();

5.泛型的指定中不能使⽤基本数据类型,可以使⽤包装类替换。

6.静态⽅法中不能使⽤类的泛型。因为泛型是创建对象的时候指定的,静态结构早于对象创建。

public static void show(T orderT){
// System.out.println(orderT);
// }

但是泛型方法可以是静态方法!

3.1泛型类举个栗子

3.1.1 OrderTest类

1. 前提:订单名称和订单编号是确定的类型
2. 问题:以后再出现的属性,类型不能确定
3. 解决:使⽤泛型解决,在类名字后⾯添加, 这些字⺟常⽤的可以使⽤

4. 使⽤的时候 在变量名字使⽤T
5. 继续为泛型类型添加setter和getter⽅法
6. 写好泛型⽅法进⾏测试

public class OrderTest<T> {String orderName;int orderId;//类的内部结构就可以使⽤类的泛型T orderT;public OrderTest(){};public OrderTest(String orderName,int orderId,T orderT){this.orderName = orderName;this.orderId = orderId;this.orderT = orderT;}//如下的三个⽅法都不是泛型⽅法public T getOrderT(){return orderT;}public void setOrderT(T orderT){this.orderT = orderT;}@Overridepublic String toString() {return "Order{" +"orderName='" + orderName + '\'' +", orderId=" + orderId +", orderT=" + orderT +'}';}}
@Testpublic void test(){/*** 如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型* 要求:如果⼤家定义了类是带泛型的,建议在实例化时要指明类的泛型。*/OrderTest order = new OrderTest();order.setOrderT(123);order.setOrderT("ABC");//建议:实例化时指明类的泛型OrderTest<String> order1 = new OrderTest<String>
("orderAA",1001,"order:AA");order1.setOrderT("AA:hello");}

使用类的泛型就可以在需要一些新增的属性的时候匹配到它。

3.2自定义泛型类的子类怎么处理?

那么就会有几种情况

第一种:SubOrder不是泛型类

public class SubOrder extends OrderTest<Integer>{ //SubOrder:不是泛型类
}

第二种:SubOrder1是泛型类

public class SubOrder1<T> extends OrderTest<T> {//SubOrder1<T>:仍然是泛型类
}

3.3、在继承情况中使用泛型

⽗类有泛型,⼦类可以选择保留泛型也可以选择指定泛型类型:两种情况,了解⼀下
1. ⼦类不保留⽗类的泛型:按需实现
        1. 没有类型擦除
        2. 具体类型
 
2. ⼦类保留⽗类的泛型:泛型⼦类

1. 全部保留
        2. 部分保留

简单情况↓↓

//1.⼦类不保留⽗类的泛型
class Father<T1, T2> {}// 1)没有类型 擦除
class Son1 extends Father {// 等价于class Son extends Father<Object,Object>{}
}
// 2)具体类型
class Son2 extends Father<Integer, String> {}
//2.⼦类保留⽗类的泛型
// 1)全部保留
class Son3<T1, T2> extends Father<T1, T2> {}
// 2)部分保留
class Son4<T2> extends Father<Integer, T2> {}

复杂情况↓↓

①不保留

        父类没有类型,子类保留自己提供的

        父类有类型,子类保留自己提供的

        父类有,子类保留自己提供的和父类全部的一起保留

        父类有类型,子类保留自己提供的和部分父类的

//1.⼦类不保留⽗类的泛型
class Father<T1, T2> {}// 1)没有类型 擦除
//⾃⼰提供两个
class Son<A, B> extends Father {// 等价于class Son extends Father<Object,Object>{}
}
// 2)具体类型
//⽗类指定了,⾃⼰也有
class Son2<A,B> extends Father<Integer, String> {}
//2.⼦类保留⽗类的泛型
// 1)全部保留
class Son3<T1, T2, A, B> extends Father<T1, T2> {}
// 2)部分保留
class Son4<T2, A, B> extends Father<Integer, T2> {}

结论:⼦类必须是“富⼆代”,⼦类除了指定或保留⽗类的泛型,还可以增加⾃⼰的泛型。

>=比第一代更多更强的思路。

3.4自定义泛型方法

3.4.1泛型⽅法说明:
 ⽅法也可以被泛型化,不管此时定义在其中的类是不是泛型类。
 在泛型⽅法中可以定义泛型参数,此时,参数的类型就是传⼊数据的类型。
 泛型⽅法在调⽤时候确定类型。

3.4.2泛型⽅法的格式

[访问权限] <泛型> 返回类型 ⽅法名([泛型标识参数名称]) 抛出的异常例如:public <E> List<E> ⽅法名(E[] arr) throws Exception{//。。。。}

所以,需要在返回值类型前⾯加泛型,编译器才理解这个E不是类,是泛型。↓↓

public class OrderTest<T> {/*** 泛型⽅法:在⽅法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。* 换句话说,泛型⽅法所属的类是不是泛型类都没有关系。*/public <E> List<E> copyFromArrayToList(E[] arr){ArrayList<E> list = new ArrayList<>();for(E e : arr){list.add(e);}return list;}
}

那么,静态方法可以是泛型方法吗?

答:可以

原因:泛型参数是在调⽤⽅法时确定的。并⾮在实例化类时确定。

public static <E> List<E> copyFromArrayToList(E[] arr){//...
}

测试类↓↓

public class GenericTest1 {//测试泛型⽅法@Testpublic void test4(){OrderTest<String> order = new OrderTest<>();Integer[] arr = new Integer[]{1,2,3,4};//泛型⽅法在调⽤时,指明泛型参数的类型。List<Integer> list = order.copyFromArrayToList(arr);System.out.println(list);}
}

3.4.3、子类重写泛型方法

import java.util.ArrayList;
import java.util.List;
public class SubOrder extends OrderTest<Integer>{ //SubOrder:不是泛型类public static <E> List<E> copyFromArrayToList(E[] arr){//静态的泛型⽅法ArrayList<E> list = new ArrayList<>();for(E e : arr){list.add(e);}return list;}
}

3.5、泛型类和泛型方法的使用情景

* 1编写Dao类,实现增删改查方法

*2 编写Customer类,其实就是数据库中的Customer表

*3 编写Student类,其实就是数据库中的Student表

* 4编写StudentDao和CustomerDao类来操作各自对应的表(使用泛型实现操作对应的表)

* 5编写测试类

1↓

import java.util.List;
public class DAO<T> { //表的共性操作的DAO//添加⼀条记录public void add(T t){}//删除⼀条记录public boolean remove(int index){return false;}//修改⼀条记录public void update(int index,T t){}//查询⼀条记录public T getIndex(int index){return null;}//查询多条记录public List<T> getForList(int index){return null;}

2↓

public class Customer {
}

3↓

public class Student {
}

4.

public class CustomerDAO extends DAO<Customer>{
}public class StudentDAO extends DAO<Student> {//只能操作某⼀个表的DAO
}

5↓

import org.junit.Test;
import java.util.List;
public class DAOTest {@Testpublic void test(){CustomerDAO dao1 = new CustomerDAO();dao1.add(new Customer());List<Customer> list = dao1.getForList(10);StudentDAO dao2 = new StudentDAO();Student student = dao2.getIndex(1);}
}

四、通配符的使用

4.1概念

为了解决类型被限制死了不能动态根据实例来确定的缺点,引⼊了“通配符泛型”

例如使⽤通配泛型格式为<? extends Collection>,“?”代表未知类型,这个类型是实现Collection接⼝。

4.2使用场景

比如这两个方法都是用来遍历List集合,只是泛型不同,使用通配符就可以合二为一。

public void show2(List<String> list){}public void show(List<Object> list){}

4.3具体使用说明

使⽤类型: 通配符:?  ⼀个问号
* 通配符?后只允许出现⼀个边界。
* 泛型只存在于编译期中
* 通配符

参考:Java之通配符_橘泽的博客-CSDN博客

只允许出现在引⽤中(普通变量引⽤、形参),⼀般是⽤作<? extends 具体类型>或者

          <? super 具体类型>。

允许在泛型类或泛型⽅法的{ }⾥还有泛型⽅法的形参上,配合占位符,甚⾄可以使⽤

        ? extends T或者? super T这种形式来⽤作引⽤。经常⽤于边界

-------------------------------------------------------------------------------------------------------------------------

不允许出现在泛型定义中(泛型类、泛型接⼝、泛型⽅法的< >⾥)

不允许(类上):class one<? extends Integer> {  }

不允许出现在类定义时继承泛型类时的< >⾥。

不允许在泛型⽅法的显式类型说明使⽤通配符。

不允许在new泛型类的时候使⽤通配符,⽐如new ArrayList<?>()。↓↓↓

通配符这篇比较全面的解释Java通配符-详细篇--一通百通_万千青柳的博客-CSDN博客_通配符java

Collection<?> c = new ArrayList();
c.add(new Object()); //
❌编译时错误因为我们不知道c的元素类型,我们不能向其中添加对象。add⽅法
有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是⼀个未知类型的⼦类。
因为我们不知道那是什么类型,所以我们⽆法传任何东⻄进去。

总结:

1.使用泛型的好处集合类型安全,代码更健壮;

2.泛型标记符要认识,T->java类  E->集合元素  K->键  V->值   ?->不确定的java类型

3.泛型分为泛型类,泛型方法,泛型接口;这里面再细分就是

自定义泛型类->类定义了泛型的话,那么类的内部结构就可以使用类的泛型;

继承泛型类时的子类泛型 继承方式、使用方式等等...

泛型方法的格式,静态方法也可以是泛型方法,但是静态方法不能定义泛型

4.通配符? 上限通配符只能读,下限通配符只能写,又读又写不用通配符。

泛型的类型必须是类,不能是基本数据类型。需要⽤到基本数据类型的位置,拿包装类替换。

Java基础—泛型的使用(详细)相关推荐

  1. 靠java_基础不牢靠,何以争朝夕?Java基础面试82道详细解析!(一)

    基础不牢靠,何以争朝夕?Java基础面试82道详细解析!(一) 发布时间:2020-03-31 12:08:31 来源:51CTO 阅读:229 作者:wx5d9ed7c8443c3 题目的基本顺序是 ...

  2. Java基础 --- 泛型 Generics

    Java基础 --- 泛型 Generics 为什么需要泛型 泛型 Bounds for Type Variable Java虚拟机如何处理泛型 --- 泛型擦除 Restrictions and L ...

  3. JAVA基础4万字超详细总结

    目录 1.2.1 计算结果的数据类型,与最大类型一致 1.2.2 整数运算转换 1.2.3 浮点数转成整数,小数部分直接舍弃掉 1.2.4 其他 1.3 运算符 1.3.1 除法运算 1.4 流程控制 ...

  4. java基础之多态的详细解释_JAVA基础之多态

    下面我为大家讲解一下JAVA基础之多态,希望大家喜欢. 多态就是事物存在的多种形态,比如你在大街上看见一只藏獒,你可以说这只藏獒真凶猛,也可以说这只狗真凶猛,还可以说这个动物真凶猛,以上三种说法其实都 ...

  5. java基础-泛型举例详解

    泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...

  6. java基础知识总结 超详细

    1,JDK:Java Development Kit,java的开发和运行环境,java的开发工具和jre. 2,JRE:Java Runtime Environment,java程序的运行环境,ja ...

  7. 基础不牢靠,何以争朝夕?Java基础面试82道详细解析(更新中)

    题目的基本顺序是: 基本语法 类相关的语法 内部类的语法 继承相关的语法 异常的语法 线程的语法 集合的语法 io 的语法 虚拟机方面的语法 因文章篇幅的问题,本文分(一)(二)两篇进行讲解,知识点很 ...

  8. java 基础 泛型

    泛型是什么? 泛型,即"参数化类型".一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参.那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类 ...

  9. Java基础----泛型

    一,泛型机制介绍及为何要使用泛型 泛型机制是在Java SE5.0中增加的,使用泛型机制编写的程序代码要比那些杂乱地使用object变量,然后再进行强制转换的代码具有更好的安全性和可读性.泛型对于集合 ...

最新文章

  1. CVE-2019-0708复现
  2. js lottie 兼容 json、图片缓存问题、修改文字,图片
  3. java ee链接css_JavaEE——CSS3选择器
  4. python列表的存储结构_在python列表类型结构中合理地存储10亿个以上的值
  5. 文字识别(五)--自然场景文本检测技术综述(CTPN, SegLink, EAST)
  6. php相册上传和删除吗,php上传与删除图片的简单范例
  7. [转]体验:VC++ .NET 2003 –安装和使用STLport 4.5.3 和LokiPort
  8. Kata: 从随机的三字符列表组中恢复秘密字符串
  9. atitit.提升研发效率的利器---重型框架与类库的区别与设计原则
  10. wps计算机一级考试提纲,2012年计算机一级考试WPSOffice考试大纲
  11. DWZ 富文本编辑器 IE下失去焦点
  12. win7计算机自动关机设置在哪里设置方法,win7自动关机设置在哪?自动关机怎么设置具体方法...
  13. 发送QQ邮件报证书不被信任 Error in certificate
  14. redis单点故障方案
  15. Jenkins邮箱配置过程(qq + 163)
  16. 【Python】文本文件处理
  17. 电子琴节奏包制作_【买前必看】雅马哈kb291电子琴是杂牌吗音色怎么样?用后感受评测说【真实大揭秘】-欧阳倩倩的文章...
  18. 蓝桥杯同一类型题目汇总
  19. 武汉大学计算机技术VB试题,武汉大学_VB题目
  20. cmd命令符的php不是内部命令 phpStudy的解决方案

热门文章

  1. 垓下古战场发现龙山文化时期城址
  2. 基于MySQL的加密解密方式
  3. Prefix must be in canonical form(已解决)
  4. mysql 数据库军规_用尽洪荒之力整理的Mysql数据库32条军规
  5. WebMOOC 餐厅游戏
  6. java.math.BigDecimal类multiply的使用
  7. vue+Springboot+easyexecl 导出excel文件打不开
  8. 云枢子表里放入富文本,富文本里放a标签,点击无法触发事件问题
  9. VS2012坦克大战的部分源码
  10. 全球首个MR电视节目!The Future Group用MR打造真人秀