一、泛型介绍
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视频,如有侵权,请私信删除文章。