【学习笔记】泛型

泛型

 

泛型概述

  • Java 泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递

  • 常见形式有泛型类、泛型接口、泛型方法

  • 语法:

    • <T,...> T称为类型占位符,表示一种引用类型

  • 好处:

    • 提高代码的重用性

    • 防止类型转换异常,提高代码的安全性

 

泛型类

  • 语法:在类名的后面加< T > T表示占位符,如果要写多个就用逗号隔开

  • 使用方法:

    • 创建变量

      • 注意:不能 new 一个 对象,因为我们不知道这个T到底是什么类型,所以它有没有构造方法,以及构造方法能不能访问,我们都不清楚,所以不能直接new 一个对象

    • 作为方法的形式参数

    • 作为方法的返回值

package com.generic;
​
public class MyGeneric<T> {
    //创建变量
    T t;
    //作为方法的参数
    public void show(T t){
        System.out.println(t);
    }
    //作为方法的返回值
    public T getT(){
        return t;
    }
}

 

  • 使用泛型类创建对象

package com.generic;
​
public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型类创建对象
        MyGeneric<String> myGeneric1 = new MyGeneric<>();
        myGeneric1.t = "hello";
        myGeneric1.show("java is good");
        String str = myGeneric1.getT();
        System.out.println(str);
        System.out.println("-------------------");
        MyGeneric<Integer> myGeneric2 = new MyGeneric<>();
        myGeneric2.t = 100;
        myGeneric2.show(200);
        Integer i = myGeneric2.getT();
        System.out.println(i);
    }
}

image-20220724111143780

 

  • 注意:

    • 泛型只能使用引用类型

    • 不同的泛型类型对象不能相互赋值

      • 也就是说,在上面的例子中 不能这样操作 myGeneric1 = myGeneric2

 

泛型接口

  • 语法:接口名< T >

  • 在接口中,我们可以定义静态常量和抽象方法

    • 我们可以使用泛型来作为抽象方法的参数和返回值

    • 但是不能使用泛型来定义静态常量,因为常量要求在定义时必须初始化,我们不知道这个泛型具体是什么类型,没有办法给它初始化,所以不可以定义静态常量

  • 在实现泛型接口时,有两种情况:

    • 在实现接口时,我们已经确定了类型

      • package com.generic;
        ​
        public class MyInterfaceImpl implements MyInterface<String>{
            @Override
            public String server(String s) {
                System.out.println(s);
                return s;
            }
        }
        package com.generic;
        ​
        public class TestGeneric {
            public static void main(String[] args) {
               MyInterfaceImpl myInterface1 = new MyInterfaceImpl();
               myInterface1.server("大家好");
        ​
        ​
            }
        }

     

    • 第二种情况是:我们在实现接口时,不确定这个类型,我们可以把这个实现类也变成泛型类,这个时候,实现类所对应的泛型就是接口所对应的泛型

      • package com.generic;
        ​
        public class MyInterfaceImpl2<T> implements MyInterface<T>{
        ​
            @Override
            public T server(T t) {
                System.out.println(t);
                return t;
            }
        }
        MyInterfaceImpl2<Integer> myInterface2 = new MyInterfaceImpl2();
        myInterface2.server(20000);

 

image-20220724114043683

 

泛型方法

  • 语法:在返回值前面加 < T >

  • 所定义的泛型方法,只能在该方法内使用,不能在方法外使用

  • 可以作为该方法的参数和返回值,也可以定义变量

package com.generic;
​
public class MyGenericMethod {
    //泛型方法
    public <T> T show(T t){
        System.out.println(t);
        return t;
    }
}
  • 它的类型是根据你传递的参数来决定的

package com.generic;
​
public class TestGeneric {
    public static void main(String[] args) {
      MyGenericMethod method = new MyGenericMethod();
      method.show("hello");
      method.show("200");
​
    }
}

image-20220724115300657

 

  • 在这个案例中,我们可以体会到泛型的好处之一就是:提高代码的重用性

如果不使用泛型,我们想要实现传递两种不同类型的参数,就要进行方法的重载

使用泛型就可以根据参数类型的不同,转换方法的泛型的类型

 

泛型集合

  • 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致

  • 特点:

    • 编译时即可检查,而非运行时抛出异常

    • 访问时,不必类型转换

    • 不同泛型之间引用不能相互赋值,泛型不存在多态

 

  • 简单来说,就是我们往集合中添加的各种类型元素都会被存成Object类型,当我们想要去遍历这个集合时,需要把它们强制类型转换为它们原来的类型,这个时候就需要去判断,每一个元素之前是什么类型

  • 如果我们使用泛型集合,相当于提前规定了我们可以往集合中放什么类型的数据,放其他类型的数据就会报错,最后遍历集合的时候,也不需要强制类型转换

 

不使用泛型集合:

package com.generic;
​
import java.util.ArrayList;
​
public class Demo01 {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        arrayList.add("xxxx");
        arrayList.add("aaaa");
        arrayList.add(100);
        arrayList.add(200);
​
        for (Object o:
             arrayList) {
            String str = (String) o;
            System.out.println(str);
        }
    }
}

image-20220724123145235

 

类型转换异常,不能把Integer转换成String

 

使用泛型集合:

package com.generic;
​
import java.util.ArrayList;
​
public class Demo01 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList();
        arrayList.add("aaaaa");
        arrayList.add("bbbbb");
        //arrayList.add(100);    不能添加非String类型的数据
​
    }
}

 

image-20220724123442674

 

for(String str:arrayList){
    System.out.println(str);
}

遍历集合时,不需要强制类型转换,直接遍历String类型

posted @ 2022-07-24 12:43  GrowthRoad  阅读(26)  评论(0编辑  收藏  举报