iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java泛型的解析
  • 322
分享到

Java泛型的解析

2023-06-15 08:06:32 322人浏览 泡泡鱼
摘要

这期内容当中小编将会给大家带来有关Java泛型的解析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、泛型简介1.1 泛型的概念 所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是

这期内容当中小编将会给大家带来有关Java泛型的解析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

一、泛型简介

1.1 泛型的概念

  • 所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返 回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、 创建对象时确定(即传入实际的类型参数,也称为类型实参)。

  • jdk 5.0以后,Java引入了“参数化类型(Parameterized type)”的概念,允许我们在创建集合时再指定集合元素的类型,正如:List,这表明该List只能保存字符串类型的对象。

  • JDK 5.0改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持,从而可以在声明集合变量、创建集合对象时传入类型实参。

1.2 泛型的引入背景

集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。Collection,List,ArrayList 这个就是类型参数,即泛型。

1.3 引入泛型的目的

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

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

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

二、泛型在集合中的应用

2.1 在集合中没有使用泛型的例子

@Testpublic void test1(){    ArrayList list = new ArrayList();    //需求:存放学生的成绩    list.add(78);    list.add(76);    list.add(89);    list.add(88);    //问题一:类型不安全    //        list.add("Tom");    for(Object score : list){        //问题二:强转时,可能出现ClassCastException        int stuScore = (Integer) score;        System.out.println(stuScore);    }}

图示:

Java泛型的解析

2.2 在集合中使用泛型的例子1

//在集合中使用泛型,以ArrayList为例@Testpublic void test1(){    ArrayList<String> list = new ArrayList<>();    list.add("AAA");    list.add("BBB");    list.add("FFF");    list.add("EEE");    list.add("CCC");//遍历方式一:    Iterator<String> iterator = list.iterator();    while (iterator.hasNext()){        System.out.println(iterator.next());    }    System.out.println("-------------");    //便利方式二:    for (String str:         list) {        System.out.println(str);    }}

图示:

Java泛型的解析

2.3 在集合中使用泛型例子2

@Test//在集合中使用泛型的情况:以HashMap为例public void test2(){    Map<String,Integer> map = new HashMap<>();//jdk7新特性:类型推断    map.put("Tom",26);    map.put("jarry",30);    map.put("Bruce",28);    map.put("Davie",60);    //嵌套循环    Set<Map.Entry<String, Integer>> entries = map.entrySet();    Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();    while (iterator.hasNext()){        Map.Entry<String, Integer> entry = iterator.next();        String key = entry.geTKEy();        Integer value = entry.getValue();        System.out.println(key+"="+value);    }}

2.4 集合中使用泛型总结:

① 集合接口或集合类在JDK 5.0时都修改为带泛型的结构。

② 在实例化集合类时,可以指明具体的泛型类型

③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。

比如:add(E e) —>实例化以后:add(Integer e)

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

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

三、自定义泛型结构

泛型类、泛型接口、泛型方法

3.1 泛型的声明

  • interface List<T>class GenTest<K,V> 其中,T,K,V,不代表值,而是表示类型。这里使用任意字母都可以。

  • 常用T表示,是Type的缩写。

3.2 泛型的实例化:

一定要在类名后面指定类型参数的值(类型)。如:

List<String> strList =new ArrayList<String>();

Iterator<Customer> iterator = customers.iterator();

  • T只能是类,不能用基本数据类型填充。但可以使用包装类填充

  • 把一个集合中的内容限制为一个特定的数据类型,这就是 generics背后的核心思想

//JDK 5.0以前Comparable c = new Date();System.out.println(c.comparaTo("red");//JDK 5.0以后Comparable <Date> c = new Date();System.out.println(c.comparaTo("red");

总结:使用泛型的主要优点在于能够在编译时而不是在运行时检测错误

3.3 注意点

泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如<E1,E2,E3>

泛型类的构造器如下: public GenericClass(){}

而下面是错误的: public GenericClass<E>{}

实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致。

泛型不同的引用不能相互赋值。

尽管在编译时 ArrayList和ArrayList是两种类型,但是,在运行时只有一个ArrayList被加载到JVM中。

泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价于Object。

建议:泛型要使用一路都用。要不用,一路都不要用。

如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。

JDK 7.0,泛型的简化操作: ArrayList<Fruit>first= new ArrayList<>();(类型推断)

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

在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。

异常类不能是泛型的。

不能使用 new E[]。但是可以:E[] elements= (E[])new Object[capacity];

> 参考:ArrayList源码中声明:`Object[] elementData`,而非泛型参数类型数组

父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:

-   子类不保留父类的泛型:按需实现    -   没有类型---擦除    -   具体类型-   子类保留父类的泛型:泛型子类    -   全部保留    -   部分保留-   结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自己的泛型

代码示例:

class Father<T1, T2> {}//1.没有指明类型  擦除class Son1<A, B> extends Father {//等价于class Son1 extends Father<Object,Odject>{}}//2.指定具体类型class Son2<A, B> extends Father<Integer, String> {}//1.全部保留class Son3<T1, T2, A, B> extends Father<T1, T2> {}//2.部分保留class Son4<T2, A, B> extends Father<Integer,T2>{}

3.4 自定义泛型结构

自定义泛型类

代码示例:

class Order<T> {    private String orderName;    private int orderId;    //使用T类型定义变量    private T orderT;    public Order() {    }    //使用T类型定义构造器    public Order(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;    }    //这个不是泛型方法    @Override    public String toString() {        return "Order{" +                "orderName='" + orderName + '\'' +                ", orderId=" + orderId +                ", orderT=" + orderT +                '}';    }//    //静态方法中不能使用类的泛型。//    public static void show(T orderT){//        System.out.println(orderT);//    }//    //try-catch中不能是泛型的。//    public void show(){//        try {////        }catch (T t){////        }//    }    //泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。    //换句话说,泛型方法所属的类是不是泛型类都没有关系。    //泛型方法,可以声明为静态的。    // 原因:泛型参数是在调用方法时确定的。并非在实例化类时确定。    public static <E> List<E> copyFromArryToList(E[] arr) {        ArrayList<E> list = new ArrayList<>();        for (E e :                list) {            list.add(e);        }        return list;    }}

自定义泛型类Order的使用

@Testpublic void test1() {    //如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型    //要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型。    Order order = new Order();    order.setOrderT(123);    System.out.println(order.getOrderT());    order.setOrderT("abc");    System.out.println(order.getOrderT());    //建议:实例化时指明类的泛型    Order<String> order1 = new Order<>("Tom", 16, "male");    order1.setOrderT("AA:BBB");    System.out.println(order1.getOrderT());}@Test//调用泛型方法public void test2(){    Order<String> order = new Order<>();    Integer [] arr = new Integer[]{1,2,3,4,5,6};    List<Integer> list = order.copyFromArryToList(arr);    System.out.println(list);}

自定义泛型接口

代码示例:

public interface DemoInterface <T> {    void show();    int size();}//实现泛型接口public class Demo implements DemoInterface {    @Override    public void show() {        System.out.println("hello");    }    @Override    public int size() {        return 0;    }}@Test//测试泛型接口public void test3(){    Demo demo = new Demo();    demo.show();}

自定义泛型方法

方法,也可以被泛型化,不管此时定义在其中的类是不是泛型类。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。

泛型方法的格式: [访问权限]<泛型>返回类型 方法名(泛型标识 参数名称])抛出的异常

泛型方法声明泛型时也可以指定上限

代码示例:

//泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。//换句话说,泛型方法所属的类是不是泛型类都没有关系。//泛型方法,可以声明为静态的。// 原因:泛型参数是在调用方法时确定的。并非在实例化类时确定。public static <E> List<E> copyFromArryToList(E[] arr) {    ArrayList<E> list = new ArrayList<>();    for (E e :         list) {        list.add(e);    }    return list;}

总结:

  •  泛型实际上就是标签,声明时不知道类型,再使用时指明

  • 定义泛型结构,即:泛型类、接口、方法、构造器时贴上泛型的标签

  • 用泛型定义类或借口是放到类名或接口名后面,定义泛型方法时在方法名前加上

3.5 泛型的应用场景

DAO.java:定义了操作数据库中的表的通用操作。 ORM思想(数据库中的表和Java中的类对应)

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;    }    //泛型方法    //举例:获取表中一共有多少条记录?获取最大的员工入职时间?    public <E> E getValue(){        return null;    }}

CustomerDAO.java:

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

StudentDAO.java:

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

四、泛型在继承上的体现

泛型在继承方面的体现:

虽然类A是类B的父类,但是 G<A>G<B> 二者不具备子父类关系,二者是并列关系。

补充:类A是类B的父类,A<G>B<G> 的父类

代码示例:

@Testpublic void test1(){    Object obj = null;    String str = null;    obj = str;    Object[] arr1 = null;    String[] arr2 = null;    arr1 = arr2;    //编译不通过    //        Date date = new Date();    //        str = date;    List<Object> list1 = null;    List<String> list2 = new ArrayList<String>();    //此时的list1和list2的类型不具子父类关系    //编译不通过    //        list1 = list2;        show(list1);    show1(list2);}public void show1(List<String> list){}public void show(List<Object> list){}@Testpublic void test2(){    AbstractList<String> list1 = null;    List<String> list2 = null;    ArrayList<String> list3 = null;    list1 = list3;    list2 = list3;    List<String> list4 = new ArrayList<>();}

五、通配符

5.1 通配符的使用

  • 使用类型通配符:?

比如:List<?>Map<?,?>

List<?>List<String>List<Object> 等各种泛型 List 的父类。

  • 读取 List<?> 的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object

  • 写入list中的元素时,不可以。因为我们不知道c的元素类型,我们不能向其中添加对象。 除了添加null之外。

说明:

  • 将任意元素加入到其中不是类型安全的

Collection<?> c = new ArrayList<String>()

c.add(new Object());//编译时错误

因为我们不知道c的元素类型,我们不能向其中添加对象。add 方法有类型参数 E 作为集合的元素类型。我们传给add的任何参数都必须是一个已知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。

  • 唯一的例外的是 null,它是所有类型的成员。

  • 我们可以调用 get() 方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object。

代码示例:

@Testpublic void test3(){    List<Object> list1 = null;    List<String> list2 = null;    List<?> list = null;    list = list1;    list = list2;    //编译通过    //        print(list1);    //        print(list2);    //    List<String> list3 = new ArrayList<>();    list3.add("AA");    list3.add("BB");    list3.add("CC");    list = list3;    //添加(写入):对于List<?>就不能向其内部添加数据。    //除了添加null之外。    //        list.add("DD");    //        list.add('?');    list.add(null);    //获取(读取):允许读取数据,读取的数据类型为Object。    Object o = list.get(0);    System.out.println(o);}public void print(List<?> list){    Iterator<?> iterator = list.iterator();    while(iterator.hasNext()){        Object obj = iterator.next();        System.out.println(obj);    }}

5.2 注意点

//注意点1:编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?public static <?> void test(ArrayList<?> list){}//注意点2:编译错误:不能用在泛型类的声明上class GenericTypeClass<?>{}//注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象ArrayList<> list2 new ArrayList<?>();

5.3 有限制的通配符

  • <?>:允许所有泛型的引用调用

  • 通配符指定上限

上限 extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即 <=

  • 通配符指定下限

下限 super:使用时指定的类型不能小于操作的类,即 >=

举例:

  • <?extends Number>(无穷小, Number\]

只允许泛型为Number及Number子类的引用调用

  • <?super Number>\[Number,无穷大)

只允许泛型为Number及Number父类的引用调用

  • <? extends Comparable>

只允许泛型为实现 Comparable接口的实现类的引用调用

代码示例:

@Testpublic void test4(){    List<? extends Person> list1 = null;    List<? super Person> list2 = null;    List<Student> list3 = new ArrayList<Student>();    List<Person> list4 = new ArrayList<Person>();    List<Object> list5 = new ArrayList<Object>();    list1 = list3;    list1 = list4;    //        list1 = list5;    //        list2 = list3;    list2 = list4;    list2 = list5;    //读取数据:    list1 = list3;    Person p = list1.get(0);    //编译不通过    //Student s = list1.get(0);    list2 = list4;    Object obj = list2.get(0);    编译不通过    //        Person obj = list2.get(0);    //写入数据:    //编译不通过    //        list1.add(new Student());    //编译通过    list2.add(new Person());    list2.add(new Student());}

上述就是小编为大家分享的Java泛型的解析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网精选频道。

--结束END--

本文标题: Java泛型的解析

本文链接: https://www.lsjlt.com/news/279282.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java泛型的解析
    这期内容当中小编将会给大家带来有关Java泛型的解析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、泛型简介1.1 泛型的概念 所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是...
    99+
    2023-06-15
  • Java 泛型详解(超详细的java泛型方法解析)
    目录2. 什么是泛型3. 使用泛型的好处4. 泛型的使用4.1 泛型类4.2 泛型方法4.3 泛型接口5. 泛型通配符5.1 通配符基本使用5.2 通配符高级使用6. 总结1. 为什...
    99+
    2024-04-02
  • JAVA泛型浅析
    本文主要列举了在使用Java泛型时应该注意的问题。Java泛型是Java5的一个重要特性,它和自动装箱、变长参数等新特性一起,提升了Java代码的健壮性和易用性,但SUN本身过分强调向前的兼容性,也引入了不少问题和麻烦。[@more@]JA...
    99+
    2023-06-03
  • 详细全面解析Java泛型
    1.概述 作为一个面向对象的编程语言,Java可以通过实现一些类,作为我们各种需求的一个模板,方便我们的使用。但有时候,这个类的范围可能比我们想要的范围要大,我们只想限定于满足类的某...
    99+
    2024-04-02
  • Java详细分析讲解泛型
    目录1.泛型概念2.泛型的使用2.1泛型类语法2.2泛型方法语法2.3泛型接口语法2.4泛型在main方法中的使用3.擦除机制4.泛型的上界5.通配符5.1通配符的上界5.2通配符的...
    99+
    2024-04-02
  • Java 泛型考古 泛型擦除 包装类详细解析
    目录一. 什么是泛型二. 为什么要有泛型 ?示例三、泛型考古四、泛型擦除五、包装类六、装箱拆箱一. 什么是泛型 泛型(generic type)其本质是将类型参数化,也就是说所操作的...
    99+
    2024-04-02
  • Java泛型实例分析
    这篇文章主要介绍“Java泛型实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java泛型实例分析”文章能帮助大家解决问题。首先,我们来看看泛型Java的经典用法:import java.ut...
    99+
    2023-06-03
  • 详解Java中的泛型
    目录一.什么是泛型二.泛型类的使用2.1泛型类的定义2.2泛型类的数组使用三.泛型的上界四.泛型的方法五.泛型与集合一.什么是泛型 当我们不确定数据类型时,我们可以暂时使用一个字母 ...
    99+
    2023-05-19
    Java泛型 Java泛型类
  • Java中泛型的示例分析
    小编给大家分享一下Java中泛型的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1. 为什么使用泛型早期的Object类型可以接收任意的对象类型,但是在实...
    99+
    2023-06-20
  • Java泛型与注解全面分析讲解
    目录1.什么是泛型2.为何使用泛型2.1.如何定义泛型2.2.通配符2.3.受限泛型2.4.泛型接口2.5.泛型方法3.java高级--注解3.1.预定义注解3.2.自定义注解(初级...
    99+
    2024-04-02
  • 一篇文章带你了解java泛型--泛型类,泛型方法,泛型接口
    目录Java 泛型Java 泛型是什么泛型类泛型类的格式泛型类举例泛型方法泛型方法的格式泛型方法举例泛型接口泛型接口的格式泛型接口举例泛型接口实现类:测试接口类:打印结果:总结Jav...
    99+
    2024-04-02
  • Java泛型
    Java泛型 🧳1. 泛型类的定义🧳1.1 语法1.2 简单示例1.3 加入静态内部类的示例1.4 加入继承或实现的示例1.5泛型的上界1.5.1复杂举例1.6泛型的下界 🌂2. ...
    99+
    2023-08-22
    java 数据结构
  • java 泛型
    概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。 泛型,就是类型参数。 一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。 那么类型参数理解呢? 顾名思义,就是将原来的具体的类型...
    99+
    2023-08-30
    java
  • 怎么解析Java泛型与等价实现
    怎么解析Java泛型与等价实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。说起泛型,也许有很多人不明白或是不懂。泛型是Java SE 1.5的新特性,泛型的本...
    99+
    2023-06-17
  • Java中的泛型
    目录1. 什么是泛型2. 为什么需要泛型3. 如何使用泛型3.1 泛型使用3.2 自定义泛型类3.2.1 Java 源码中泛型的定义3.2.2 自定义泛型类实例13.2.3 自定义泛...
    99+
    2024-04-02
  • Java泛型使用实例分析
    本篇内容主要讲解“Java泛型使用实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java泛型使用实例分析”吧!1.概述作为一个面向对象的编程语言,Java可以通过实现一些类,作为我们各种...
    99+
    2023-06-29
  • Java的类型擦除式泛型详解
    Java选择的泛型类型叫做类型擦除式泛型。什么是类型擦除式泛型呢?就是Java语言中的泛型只存在于程序源码之中,在编译后的字节码文件里,则全部泛型都会被替换为原来的原始类型(Raw...
    99+
    2024-04-02
  • Java基础泛型实例分析
    这篇“Java基础泛型实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java基础泛型实例分析”文章吧。一、泛型概述:...
    99+
    2023-06-29
  • 重新理解Java泛型
    这篇文章的目的在于介绍Java泛型,使大家对Java泛型的各个方面有一个最终的,清晰的,准确的理解,同时也为下一篇《重新理解Java反射》打下基础。简介泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从...
    99+
    2023-05-30
    java 泛型的理解 ava
  • Java中泛型擦除的示例分析
    小编给大家分享一下Java中泛型擦除的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.问题引出源码: public static&n...
    99+
    2023-05-31
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作