Java泛型

improve改善

public 公共的

personal===private 私人的

cast 投

exception 异常

integer 整形

泛型

使用传统方法的问题分析

1.不能对加入到集合 ArrayList 中的数据类型进行约束(不安全)

2.遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响

  • 泛型快速体验 - 用泛型来解决前面的问题

不使用泛型:

  • Dog -> 加入 -> Object -> 取出 -> Dog // 放入到ArrayList时会先转换成Object,在取出时,还需要转换成Dog。

使用泛型:

  • Dog -> Dog -> Dog // 放入时,和取出时,不需要类型转换,提高效率。

不再提示编译警告。

解释:

  • 不使用泛型:在Java早期版本中,集合类如ArrayList是不带泛型的,这意味着你可以向ArrayList中添加任何类型的对象,因为它们都被视为Object类型。当你从集合中取出对象时,需要显式地将Object类型转换为实际的对象类型(如Dog)。这种做法不仅繁琐,而且容易出错,因为如果集合中包含了非Dog类型的对象,运行时就会抛出ClassCastException

  • 使用泛型:泛型(Generics)是Java 5引入的一个特性,它允许在编译时检查类型安全。通过使用泛型,你可以指定集合中可以存储的对象类型,这样在编译时就能确保类型安全,避免了类型转换的需要。例如,你可以声明一个ArrayList<Dog>,这样就只能向其中添加Dog类型的对象,取出时也直接是Dog类型,无需进行类型转换。这不仅提高了代码的可读性和安全性,也提升了运行效率。

  • 不再提示编译警告:使用泛型后,由于类型安全在编译时就已经得到保证,因此不会再出现因为类型转换而产生的编译警告。

  •  package com.improve;
     ​
     import java.util.ArrayList;
     ​
     public class Generic02 {
         public static void main(String[] args) {
             ArrayList<dog> arrayList = new ArrayList<dog>();
     //        当我们ArrayList<dog>,表示我们存放在ArrayList集合的元素是dog类型
     //        如果编译器发现添加的类型不满足要求会报错
             arrayList.add(new dog("ss",12));
     //        遍历的时候可以直接取出dog类型而不是object
             for(dog o : arrayList) {
                 System.out.println(o.getName()+ - + o.getAge());
             }
         }
     }
     ​
     class Cat {
         private String name;
         private int age;
         public Cat(String name, int age) {
             this.name = name;
             this.age = age;
         }
     ​
         public String getName() {
             return name;
         }
     ​
         public void setName(String name) {
             this.name = name;
         }
     ​
         public int getAge() {
             return age;
         }
     ​
         public void setAge(int age) {
             this.age = age;
         }
     ​
         @Override
         public String toString() {
             return "Cat{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     '}';
         }
     }
     ​
     ​
     class dog{
         private String name;
         private int age;
         public dog(String name, int age) {
             this.name = name;
             this.age = age;
         }
     ​
         public String getName() {
             return name;
         }
     ​
         public void setName(String name) {
             this.name = name;
         }
     ​
         public int getAge() {
             return age;
         }
     ​
         public void setAge(int age) {
             this.age = age;
         }
     }
     ​

泛型的说明

泛型的理解:泛型(泛型类型)指的是像IntegerStringDog这样的具体类型。

  1. 泛型,也称为参数化类型,是Java 5.0引入的一个新特性,它解决了数据类型安全性问题。

  2. 使用泛型时,在类声明或实例化时指定具体的类型即可。

  3. Java泛型确保如果程序在编译时没有发出警告,那么运行时就不会产生ClassCastException异常。同时,使用泛型可以使代码更加简洁和健壮。

  4. 泛型的作用包括:在类声明时通过一个标识符表示类中某个属性的类型、方法的返回值类型或参数类型。

泛型是Java语言中用于处理集合和其他数据结构时提供类型安全的一种机制。它允许你在编译时期就检查类型错误,避免了在运行时进行类型转换的需要,从而提高了代码的可读性和稳定性。

泛型的具体数据类型在编译时,确定

泛型的语法

泛型的声明

  • interface 接口<T>{ } 和 class 类<K,V>{ }

  • //比如:List,ArrayList

  • 说明:

    1.其中,T,K,V不代表值,而是表示类型。

    2.任意字母都可以。常用T表示,是Type的缩写

  • 泛型的实例化:

    • 要在类名后面指定类型参数的值(类型)。如:

      1.List<String> strList = new ArrayList<String>(); [举例说明]

      2.Iterator<Customer> iterator = customers.iterator();

这段内容解释了泛型声明和泛型实例化的概念:

  • 泛型的声明:泛型可以用于接口和类中,通过在接口或类名后面添加尖括号<>并放入类型参数(如TKV)来声明。这些类型参数代表了泛型类型,可以在接口或类的定义中使用。TKV是类型参数的常用标识,T是Type的缩写,但可以使用任何字母来表示。

  • 泛型的实例化:在创建泛型类的实例时,需要指定具体的类型参数值(类型),这称为泛型实例化。例如,创建一个List集合,存储String类型的元素,可以声明为List<String>,并实例化为new ArrayList<String>()。同样,如果有一个customers集合,其元素类型为Customer,可以使用customers.iterator()来获取一个Iterator<Customer>类型的迭代器。

练习:

1.创建 3 个学生对象

2.放入到 HashMap 中,要求 Key 是 String name, Value 就是 学生对象

3.使用两种方式遍历

 package com.improve;
 ​
 import java.util.*;
 ​
 public class GenericExercise {
     public static void main(String[] args) {
 //        使用泛型,给hashmap放入三个学生对象
         HashSet<Student> student = new HashSet<Student>();
         student.add(new Student("nihao",14));
         student.add(new Student("nhao",15));
         student.add(new Student("niho",16));
 ​
 //        1.增强for循环遍历
         for(Student s : student){
             System.out.println(s);
         }
         HashMap<String,Student> hashMap = new HashMap<String,Student>();
         hashMap.put("nihao",new Student("nihao",14));
         hashMap.put("nhao",new Student("nhao",15));
         hashMap.put("niho",new Student("niho",16));
 ​
         Set<Map.Entry<String, Student>> entries = hashMap.entrySet();
         Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
         while (iterator.hasNext()) {
             Map.Entry<String, Student> next =  iterator.next();
             System.out.println(next.getKey());
         }
     }
 }
 ​
 class Student {
     private String name;
     private int age;
 ​
     public Student(String name, int age) {
         this.name = name;
         this.age = age;
     }
 ​
     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 "Student{" +
                 "name='" + name + '\'' +
                 ", age=" + age +
                 '}';
     }
 }

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

 interface List<T> ,public class HashSet<E>{}.. 

等等说明:TE只能是引用类型看看下面语句是否正确?:

 List<Integer> list = new ArrayList<Integer>(); //OK
 List<int>list2 = new ArrayList<int>();//错误

2在给泛型指定具体类型后,可以传入该类型或者其子类类型3.泛型使用形式

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

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

泛型课堂练习题

  1. 定义Employee类

    • 1.该类包含:private成员变量name, sal, birthday,其中 birthday 为 MyDate 类的对象;

    • 2.为每一个属性定义 getter, setter 方法;

    • 3.重写 toString 方法输出 name, sal, birthday;

    • 4.MyDate类包含:private成员变量month, day, year;并为每一个属性定义 getter, setter 方法;

    • 5.创建该类的 3 个对象,并把这些对象放入 ArrayList 集合中(ArrayList 需使用泛型来定义),对集合中的元素进行排序,并遍历输出:

    排序方式:调用ArrayList的sort 方法,传入 Comparer对象(使用泛型),先按照name排序,如果name相同,则按生日日期的先后排序。【即:定制排序】

自定义泛型

自定义泛型3类(难度)

基本语法

 class 类名<T,R...>{}
 成员

注意细节

  • 1.普通成员可以使用泛型(属性、方法)

  • 2.使用泛型的数组,不能初始化

  • 3.静态方法中不能使用类的泛型

  • 4.泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)

  • 5.如果在创建对象时,没有指定类型,默认为Object

自定义泛型接口

基本语法

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

注意细节

  • 1.接口中,静态成员也不能使用泛型(这个和泛型类定义一样)

  • 2.泛型接口的类型,在继承接口或者实现接口时确定

  • 3.没有指定类型,默认为Object

自定义泛型方法

  • 基本语法

     修饰符<T,R> 返回类型 方法名(参数列表) {
     }
  • 注意细节

    • 1.泛型方法,可以定义在普通类中,也可以定义在泛型类中

    • 2.当泛型方法被调用时,类型会确定

    • 3.public void eat(E e) { },修饰符后没有 <T,R> eat方法不是泛型方法,而是使用了泛型

泛型的继承和通配符

1)泛型不具备继承性List<Object> list = new ArrayList<String>(); // 对吗?

2)<?>:支持任意泛型类型 3)<?extends A>:支持A类以及A类的子类,规定了泛型的上限 4)<?super A>: 支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值