栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java学习笔记十八——集合类之泛型(人学废了系列)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java学习笔记十八——集合类之泛型(人学废了系列)

Java编程基础倒数第二篇,感谢没有放弃的自己。此专栏暂时已完结,接下来就是搞定算法。
学习笔记参考书籍《Java编程基础》主编 张焕生。本书内容比较适合没有什么基础的入门小白,学完一章还有习题,比较适合初学者。
自律、积极、勤奋以及先从一个怎么样都不可能不会实现的小目标开始。

本文已收录于[ 专栏 ]


《Java入门》系列

前面[ 章节 ]:


 Java学习笔记十七——集合类详细总结各自对比
✌ Java必备基础十六——三万字总结输入与输出流
Java必备基础十五——万字长文总结异常处理基本知识点
Java必备基础十四——内部类详细知识点归纳
爛Java必备基础十三——接口详细知识点归纳
✨Java必备基础十二——抽象类
✌Java必备基础十一——多态详解以及多态原则
Java必备基础十——类的继承详解
Java必备基础九——包装类
Java必备基础八——Math类、Random类、日期时间类
Java必备基础七——字符串的基本常用方法
Java必备基础六——一维数组
Java必备基础五——类的封装
盧Java必备基础四——成员变量和局部变量
Java必备基础三——方法的声明与调用,递归
Java必备基础二——类和对象
Java必备基础一——Java语言基础

文章目录
  • 一、泛型是什么
    • 1.1泛型的由来
    • 1.2 泛型的优点
  • 二、泛型的简单使用
    • 2.1 泛型菱形语法
    • 2.2 泛型简单举例
    • 2.3 定义一个泛型类
      • 2.3.1 基本写法
      • 2.3.2 举个例子
    • 2.4 定义一个泛型接口
      • 2.4.1 基本写法
      • 2.4.2 举个例子
    • 2.4 定义一个泛型方法
      • 2.5.1 基本写法
      • 2.5.2 举个例子
      • 2.5.3 总结
    • 2.5 泛型通配符

一、泛型是什么 1.1泛型的由来

在没有泛型之前,集合中加入特定的对象时,就会被当成Object类型。当从集合中取出对象后,需要进行强制类型转换如何打印相应的对象。这种操作的弊端很容易引起异常,并且代码臃肿。

举个简单的被说了无数遍的例子:

public class Example1_1 {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        arrayList.add("a");
        arrayList.add(1);

        for (int i=0;i 

输出的结果是:ClassCastException异常

a
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at com.chapter8.Example1_1.main(Example1_1.java:17)

集合类ArrayList添加了String类型和Integer类型,但是输出时把这两个类型强转了,因此程序崩溃了。为了解决这样的问题 ,引入泛型。

引入泛型的集合可以记住元素类型,在编译时检查元素类型,如果集合中添加了不满足类型的对象时编译器就会提示错误。可以看到下图中定义了泛型元素为String类型,添加int类型的对象时编译器提示要求String类型对象。


需要额外注意的一点是:泛型的集合可以记住元素类型,在编译时检查元素类型,举个例子理解这句话:

public class Example1_1 {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList<>();
        ArrayList arrayList1 = new ArrayList<>();
        arrayList1.add(1);
        arrayList.add("2");

        Class classStringArrayList = arrayList.getClass();
        Class classStringArrayList1 = arrayList1.getClass();

        if(classStringArrayList.equals(classStringArrayList1)){
            System.out.println("类型相同");
        }
    }
}

可以猜测一下程序的输出结果,程序会打印出类型相同。虽然两个类添加了不同类型的泛型,但是这两个类依旧是相同的类别。于是我们可以大胆的猜测一下:泛型只在编译阶段有效,在检验泛型结果后,程序会将泛型的相关信息擦除,泛型信息不会进入到运行时阶段。

1.2 泛型的优点

在由来中已经简单提到了没有泛型时的缺点,那么有了泛型时,缺点就是优点:

  • 减少代码臃肿,使代码变得简洁
  • 消除源代码中许多强制类型转换,提高Java中的类型安全。
二、泛型的简单使用 2.1 泛型菱形语法
List list = new linkedList<>();
Set set = new HashSet<>();
Map map = new HashMap<>();
2.2 泛型简单举例

泛型对于集合类非常重要,在集合中引入泛型能够提供编译时的类型安全,并且从集合中取出元素后不必再强制转换,简化了程序代码。

public class Demo1 {
    public static void main(String[] args) {
        List ar=new ArrayList<>();
        Map map = new HashMap<>();
        ar.add("a");
        ar.add("b");
        map.put(1,"c");
        map.put(2,"d");
        System.out.println("ar的集合元素为:"+ar);
        //遍历Map集合中的元素的一种方法
        Iterator> map1=map.entrySet().iterator();

        while (map1.hasNext()){
            Map.Entry next = map1.next();
            System.out.println(next.getKey()+""+next.getValue());
        }
    }
}

输出的结果为:

ar的集合元素为:[a, b]
1c
2d
2.3 定义一个泛型类 2.3.1 基本写法
class 类名<泛型标识>{
  private 泛型标识 标识名
}
2.3.2 举个例子
public class Example1_1{

    
    private T key;

    
    public Example1_1(T key){//泛型构造方法形参key的类型也为T,T的类型也由外部决定
        this.key = key;
    }

    
    public T getKey() {
        return key;
    }

    public static void main(String[] args) {
        //泛型的类型参数只能是引用类型,并且传入的实参类型必须要与定义的泛型对象的类型相同
        Example1_1 exampleInt= new Example1_1<>(0);
        //错误,定义泛型对象类型要和传入的实参类型相同
        Example1_1 exampleInt1= new Example1_1("1"); 
        
        Example1_1 exampleString = new Example1_1<>("2");
        System.out.println("exampleInt的key值:"+exampleInt.getKey());
        System.out.println("exampleString的key值:"+exampleString.getKey());


 //下面这些写法都是正确的,定义的泛型类不用都传入泛型的实参,实际上的泛型类可以被定义成任何类型,如果有定义,就会像上面一下做出限制
        Example1_1 a = new Example1_1(2);
        Example1_1 b = new Example1_1("hello");
        Example1_1 c = new Example1_1(false);

    }
}

输出结果为:

exampleInt的key值:0
exampleString的key值:2
2.4 定义一个泛型接口 2.4.1 基本写法
//定义一个泛型接口
public interface Example1_2 {
    T next();
}
2.4.2 举个例子
//定义一个泛型接口Example1_2
public interface Example1_2 {
    T fly();
}

//接下来实现这个接口


class Bird implements Example1_2{
    @Override
    public T fly() {
        return null;
    }
}


class Bird1 implements Example1_2{
    @Override
    public T fly() {
        return null;
    }
}



class Bird2 implements Example1_2{
    @Override
    public String fly() {
        return null;
    }
}
2.4 定义一个泛型方法 2.5.1 基本写法
    
public T genericMethod(Class tClass) throws Exception{
    T instance = tClass.newInstance();//newInstance方法抛出了异常
    return instance;
}

看到上面的例子说明一下泛型的方法:

  • public 与返回值终中间的,可以李佳节为声明此方法的泛型方法
  • 只有声明了的方法才是泛型方法
  • 表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T
2.5.2 举个例子

✨✨✨下面这个例子概括了很多正确的泛型方法和不正确的泛型方法:自己在电脑上敲一遍,泛型方法就大致ok了。

   public class Generic {

    private T key;

    public Generic(T key) {
        this.key = key;
    }

    
    public T getKey() {
        return key;
    }

    
    public E setKey(E key) {
        return key;
    }

    
    public  T showKeyName(Generic generic) {
        return generic.key;
    }

    
    public void showKeyName1(Generic generic) {
    }

    
    public void showKeyName2(Generic generic) {
    }

    
    public  T showKeyName3(Generic generic) {
    }

    
    public  void showKeyName3(E t) {
    }

    
    public  void showKeyName4(T t) {
    }
    
  
    public static   void showKeyName4(T... args) {
        for (T t :args){
            System.out.println(t);
        }
    }

   
    public static void showKeyName5(T t) {
    }
}
2.5.3 总结
  • 泛型方法能使方法独立于类而产生变化
  • 泛型方法前面一定要声明泛型 ,除了非静态的void修饰的无返回值方法外,其它都要声明
  • 对于静态的无返回值的泛型方法,必须要声明泛型,并且方法的形参的类型一定与声明的泛型保持一致
2.5 泛型通配符

先来看一个例子:

class Bird2 {

    public static void showValue(Bird2 bird2) {
        System.out.println("这是Integer类型");

    }

    public static void main(String[] args) {

        Bird2 bird2 = new Bird2();
        Bird2 bird1 = new Bird2();

        showValue(bird2);
        showValue(bird1);//这里会报错

    }
}
    

上面的 showValue(bird1)会报错:解决办法就是:将原来的Integer类型修改为?,问题就可以解决。

  public static void showValue(Bird2<?> bird2) {
        System.out.println(bird2.fly());

类型通配符一般使用?代替具体的类型实参,此处的?是类型实参,不是形参。可以解决诸如上面的当具体类型不确定的时候,使用?代替,在使用的时候给这个类型实参赋真正的类型。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/327467.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号