第十五章:泛型

泛型

好处:

  • 编译时,检查添加元素的类型,提高安全性
  • 减少了类型转换的次数,提高效率

不使用泛型:

		Dog - 加入 - > Object - 取出 - > Dog

使用泛型:

		 Dog - 加入 - > Dog - 取出 - > Dog

介绍:


使用:

package com.lcz.generic;

import java.util.*;

/**
 * @author lcz
 * @version 1.0
 * 需求:
 *      泛型举例使用
 *          1.创建3个对象
 *          2.将学生对象放入到HashSet中
 *          3.放入到HashMap中,要求Key是String name、Value是学生对象
 *          4.使用两种方式遍历
 */
public class Generic {
    public static void main(String[] args) {
        //1.HashSet
        HashSet<Student> students = new HashSet<>();
        students.add(new Student("lhc",24));
        students.add(new Student("lcz",20));
        students.add(new Student("wdm",20));
        //迭代器遍历
        System.out.println("迭代器遍历");
        Iterator<Student> iterator = students.iterator();
        while (iterator.hasNext()) {
            Student student =  iterator.next();
            System.out.println(student);
        }
        //增强for
        System.out.println("增强for");
        for (Student student :students) {
            System.out.println(student);
        }
        //2.HashMap
        HashMap<String, Student> hm = new HashMap<>();
        hm.put("lhc",new Student("lhc",24));
        hm.put("lcz",new Student("lcz",20));
        hm.put("wdm",new Student("wdm",20));
        //获取entry集合
        Set<Map.Entry<String, Student>> entries = hm.entrySet();
        //迭代器遍历
        System.out.println("迭代器遍历");
        Iterator<Map.Entry<String, Student>> iterator1 = entries.iterator();
        while (iterator1.hasNext()) {
            Map.Entry<String, Student> student =  iterator1.next();
            System.out.println(student);
        }
        //增强for
        System.out.println("增强for");
        for (Map.Entry entry :entries) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }


    }
}
class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

自定义泛型

自定义泛型类

语法:

class 类名<T,R...>{//...表示可以有多个泛型
	成员
}

细节:

1.普通成员可以使用泛型(属性、方法)
2.使用泛型的数组,不能初始化
	因为数组在new 不能确定T的类型,就无法在内存开辟空间
3.静态方法中不能使用类的泛型
	因为静态是和类相关的,在类加载时,对象还没有创建
	所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化
4.创建对象时需指定泛型类的类型
  若没有指定,默认为Object
package com.lcz.generic.customgeneric;

import java.util.ArrayList;

/**
 * @author lcz
 * @version 1.0
 * 需求:
 *      自定义泛型类
 *
 */
public class CustomGeneric {
    public static void main(String[] args) {
        A<String, Integer, Double> lhc = new A<String, Integer, Double>("lhc", 24, 2000.0);
        System.out.println(lhc);
    }
}
class A<T,R,M>{
    private T t;//属性使用泛型
    private R r;
    private M m;

    public A(T t, R r, M m) {//参数使用泛型
        this.t = t;
        this.r = r;
        this.m = m;
    }

    public T getT() {//方法返回值使用泛型
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public R getR() {
        return r;
    }

    public void setR(R r) {
        this.r = r;
    }

    public M getM() {
        return m;
    }

    public void setM(M m) {
        this.m = m;
    }

    @Override
    public String toString() {
        return "A{" +
                "t=" + t +
                ", r=" + r +
                ", m=" + m +
                '}';
    }
}

自定义泛型接口

语法:

interface 接口名<T,R...>{
	
}

细节:

1.静态成员不能使用泛型
2.泛型接口的类型,在继承接口或者实现接口时确定
3.没有指定类型,默认为Object
package com.lcz.generic.customgeneric;

/**
 * @author lcz
 * @version 1.0
 * 需求:
 *      自定义泛型接口
 */
public class CustomGeneric01 {
    public static void main(String[] args) {
        
    }
}
interface IUsb<T,R>{
    void f1(T t,R r);
}
interface IA extends IUsb<String,Integer>{
    
}
class A1 implements IUsb<String,Double>{


    @Override
    public void f1(String s, Double aDouble) {
        
    }
}
class B1 implements IA{

    @Override
    public void f1(String s, Integer integer) {
        
    }
}

自定义泛型方法

语法:

修饰符<T,R...> 返回类型 方法名(参数列表){

}

细节:

1.泛型方法,可以定义在普通类中,也可以定义在泛型类中
2.当泛型方法被调用时,类型也会确定
3.public void eat(E e){},修饰符后没有<T,R...>,eat方法不是泛型方法,而是使用了泛型
package com.lcz.generic.customgeneric;

/**
 * @author lcz
 * @version 1.0
 * 需求:
 *      自定义泛型方法
 */
public class CustomGeneric03 {
    public static void main(String[] args) {
        new C().f1("saf",10);
        System.out.println("=====");
        new C().f1('f',10.0);
    }
}
class C{
    public <T,R> void f1(T t,R r){
        System.out.println(t.getClass().getSimpleName());
        System.out.println(r.getClass().getSimpleName());
    }
}

泛型的继承和通配符

细节:

1.泛型不具备继承性
ArrayList<Object> alt = new ArrayList<String>()//不具备继承性,会报错
2.<?>:支持任意泛型类型
3.<? extends A>:支持A类以及A类的子类,规定了泛型的上限
4.<? super A>:支持A类以及A类父类,规定了泛型的下限
package com.lcz.generic.customgeneric.extend;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lcz
 * @version 1.0
 * 需求:
 *      泛型的继承和通配符
 */
public class Extends_ {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        ArrayList<Integer> integers = new ArrayList<>();
        ArrayList<AA> aas = new ArrayList<>();
        ArrayList<BB> bbs = new ArrayList<>();
        ArrayList<CC> ccs = new ArrayList<>();
        printCollection1(aas);
    }

    public static void printCollection(List<?> c){
        for (Object o :c) {
            System.out.println(o);
        }

    }

    public static void printCollection1(List<? extends AA> c){
        for (Object o :c) {
            System.out.println(o);
        }

    }

    public static void printCollection2(List<? super AA> c){
        for (Object o :c) {
            System.out.println(o);
        }

    }
}
class AA{

}
class BB extends AA{

}
class CC extends BB{

}

本章作业

package com.lcz.generic.customgeneric.homework;


import org.junit.jupiter.api.Test;

import java.util.*;

/**
 * @author lcz
 * @version 1.0
 * 需求:
 *      定义一个泛型类DAO<T>,在其中定义一个Map成员变量,Map的键为String类型,值为T类型
 *      分别创建一下方法:
 *      (1):public void save(String id,T entity):保存T类型的对象到Map成员变量中
 *      (2):public T get(String id):从map中获取id对应的对象
 *      (3):public void update(String id,T entity):替换map中key为id 的内容,改为entity对象
 *      (4):public List<T> list():返回map中存放的所有T对象
 *      (5):public void delete(String id):删除指定id对象
 *
 *      定义一个User类:
 *          包含:int id,age;String name;
 *      创建DAO类的对象,分别调用其save、get、update、list、delete方法来操作User对象,
 *      使用JUnit单元测试类进行测试
 */
public class Homework01 {
    public static void main(String[] args) {

    }
    @Test
    public void testList(){
        DAO<User> userDAO = new DAO<User>();
        userDAO.save("1",new User(1,24,"lhc"));
        System.out.println(userDAO.get("1"));
        userDAO.update("1",new User(2,20,"lcz"));
        List<User> list = userDAO.list();
        for (User user :list) {
            System.out.println(user);
        }
        userDAO.delete("1");
    }
}
class DAO<T>{
    private Map<String,T> map = new HashMap<>();


    public void save(String id, T entity){
        map.put(id,entity);
    }
    public T get(String id){
        return map.get(id);
    }
    public void update(String id,T entity){
        map.put(id,entity);
    }
    public List<T> list(){
        Collection<T> values = map.values();
        return new ArrayList<>(values);
    }
    public void delete(String id){
        map.remove(id);
    }
}
class User{
    private int id;
    private int age;
    private String name;

    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

更多编程学习资源

编程学习公众号【程序员论周】

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐