Java--泛型篇

一、泛型介绍

1)泛型又称参数化类型,是jdk5.0出现的新特性,解决数据类型的安全性问题
2)在声明或实例化时,只要指定好需要的具体的类型即可
3)Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮
4)泛型的作用是:可以在声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值类型,或者是参数类型.重点

二、泛型语法

2.1 泛型的声明

interface 接口<T>{} 和 class 类<K,V>{}
说明:
1)其中,T,K,V不代表值,二是表示类型
2)任意字母都可以。常用T表示,是Type的缩写

2.2 泛型的实例化

要在类名后面指定类型参数的值(类型)。比如:
1)~~~List<String> strList = new ArrayList<String>~~~
2)~~~Iterator<Customer> iterator = customers.iterator();

代码演示

@SuppressWarnings({"all"})
public class GenericExercise {
    public static void main(String[] args) {
        //使用泛型给HashSet放入3个学生对象
        HashSet<Student> students = new HashSet<>();
        students.add(new Student("迪丽热巴",18));
        students.add(new Student("古力娜扎",19));
        students.add(new Student("马儿扎哈",20));


        for (Student student : students) {
            System.out.println(student.getName()+"-"+student.getAge());
        }

        //使用泛型给HashMap添加3个学生对象
        HashMap<String, Student> hashMap = new HashMap<>();
        hashMap.put("北京",new Student("张三",18));
        hashMap.put("上海",new Student("李四",18));
        hashMap.put("英雄联盟",new Student("王五",18));

        System.out.println(hashMap);

        Set<String> strings = hashMap.keySet();
        for (String string : strings) {
            System.out.println(string+"-"+hashMap.get(string));
        }

        Set<Map.Entry<String, Student>> entries = hashMap.entrySet();
        Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Student> entry = iterator.next();
            System.out.println(entry.getKey()+"-"+entry.getValue());
        }

    }
}

//学生对象
class Student{
    private String name;
    private Integer age;

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

泛型使用的注意事项和细节

1、泛型在指定类型的时候,例:interface<T>{}和public class HashSet<E>{}等等
其中T和E只能是引用数据类型,不能是基本数据类型
2、在指定泛型具体类型后,可以传入该类型或者其子类类型
3、泛型使用形式

List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<>();

4、如果我们这样写 List list3 = new ArrayList();默认给它的泛型是[<E> E就是Object]

4.1自定义泛型类

  • 基本语法
    class 类名<T,R...>{//...表示可以有多个泛型
    成员
    }
  • 注意细节
    1)普通成员可以使用泛型(属性、方法)
    2)使用泛型的数组不能初始化
    3)静态方法中不能使用类的泛型
    4)泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定的类型)
    5)如果在创建对象时,没有指定类型,默认为Object
    *示例:
class Dog{
String name;
R r;
M m;
T t;
public Dog(String name){
this.name = name;
}
public Dog(R r,M m,T t){
this.r = r;
this.m = m;
this.t = t;
}

public static void main(String[] args){
//R = Double,M = String,T = Integer
Dog<Double,String,Integer> dog = new Dog("马儿扎哈");
}
}

4.2自定义泛型接口

  • 基本语法
interface 接口名<T,R...>{}
  • 注意细节
    1)接口中,静态成员也不能使用泛型(这个和泛型类一样,因为泛型的类型是在创建对象或者实现、继承接口时指定的)
    2)泛型接口的类型,在继承几口或者实现接口时确定
    3)没有指定类型,泛型接口的类型默认为Object
    *示例:
interface Usb<T,R>{
R get(T t);

void hi(R r);

void Run(R r1,R r2,T t1,T t2);

//在JDK8中,可以在接口中使用默认方法,也可以是使用泛型
default R method(T t){
return null;
  }
}

4.3自定义泛型方法

  • 基本语法
    修饰符 <T,R> 返回类型 方法名(参数列表){}
  • 注意细节
    1)泛型方法,可以定义在普通类中,也可以定义在泛型类中
    2)当泛型方法被调用时,类型会确定
    3)public void eat(E e){},修饰府后没有<T,R...> eat方法不是泛型方法,而是使用了泛型
    *示例:
//将泛型方法定义在普通类中
Class Car {
public void run(){}  //普通方法

//1.<T,R>就是泛型,是提供给fly使用的
public <T,R> void fly(T t,R r){  //泛型方法
System.out.println(t.getClass);
System.out.println(r.getClass);
  }    
}

//将泛型方法定义在泛型类中
Class Dog<T,R...>{
public void run(){}  //普通方法

public <U,M> void eat(U u,M m){}  //泛型方法

//泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型
public <T t> void hello(R r,K k){
System.out.println(r.getClass);
System.out.println(k.getClass);
  }
}

public static void main(String args[]){
 Car car = new Car();
car.fly("宝马",100)    //当调用方法时,传入参数,编译器就会确定泛型的类型

//测试,T->String  R->ArrayList
Dog<String,ArrayList> dog = new Dog();
dog.hello(new ArrayLsit(),11.0)

}

4.4泛型的继承和通配符

  • 泛型的继承和通配符说明
    1)泛型不具备继承性
    List<Object> list = new ArrayList<String> 这种写法是不对的
    2)<?>:支持任意泛型类
    3)<? extend A>:支持A类以及A类的子类。规定了泛型的上限
    4)<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

泛型作业

作业需求:创建一个DAO泛型接口,使用HashMap来封装数据,key为id,value为泛型类型,泛型类型指定为User类型,可以实现User对象的CRUD,最后在单元测中完成测试

以下为作业代码:

User类

package GenericHomework;

public class User {
        private Integer id;
        private String name;
        private Integer age;

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

        public Integer getId() {
            return id;
        }

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

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

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

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

自定义泛型接口

package GenericHomework;

import java.util.*;

//自定义泛型接口
public 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(){
        ArrayList<T> list = new ArrayList<>();
        //使用entrySet+Iterator遍历map集合,当然还可以用keySet
        Set<Map.Entry<String, T>> entries = map.entrySet();
        Iterator<Map.Entry<String, T>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, T> entry = iterator.next();
            list.add(entry.getValue());
        }
        return list;
    }

    public void delete (String id){
        map.remove(id);
    }
}

主方法

package GenericHomework;

import org.junit.jupiter.api.Test;

import java.util.List;

public class Homework01 {

    @Test
    public void test(){
        //给泛型指定为user
        DAO<User> userDAO = new DAO<>();
        userDAO.save("001",new User(1,"jack",10));
        userDAO.save("002",new User(2,"bob",11));
        userDAO.save("003",new User(3,"smith",19));
        userDAO.save("004",new User(4,"tom",16));

        List<User> list = userDAO.list();
        System.out.println(list);
    }
}

该文章仅用于学习,借此希望该文章能对大家有所帮助!! 感觉可以点个赞赞呗~

该文章笔记内容源自B站韩顺平零基础30天学Java视频,如有侵权,请私信删除文章。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容