欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 八卦 > java9-泛型

java9-泛型

2024/11/30 8:55:29 来源:https://blog.csdn.net/zhaogodzero/article/details/140934942  浏览:    关键词:java9-泛型

1.泛型的简介

1.1 什么是泛型

        泛型是一种特殊的数据类型。 它是Java 的一个高级特性。在 Mybatis、Hibernate 这种持久化框架,泛型更是无处不在。

在这之前,不管我们在定义成员变量时,还是方法的形参时,都要规定他们的具体类型。所以提出猜想,有没有一种可能,一次声明,就可以给各种各样的值呢?所以,泛型这个概念就出来了。

泛型的定义:        

        我们在定义一个语法结构时,不用指明具体类型,而是先定义一个类型变量,在真正使用的时候再确定该变量的具体类型。

总结: 类型参数化

两个参数化:

        数据参数化:  就是使用形参接收具体数据(实际参数)
        类型参数化:  就是使用形参接收具体类型。

1.2 泛型的定义

 泛型,定义在一对尖括号中,也是一个标识符遵循大驼峰命名法通常都是用一个大写字母

public class Test1<T> {
}
class Person<T,M>{
}
class Calculate<T>{public T calculate(T a, T b){return a;}
}

2.泛型的应用 

2.1 泛型类的应用

        当我们将泛型用在类上时,这个类就叫做泛型类。

        泛型类:  泛型应用在类上。一般在类名后,使用尖括号括起来。用大写字母作为泛型参数。

演示代码:

import java.util.Date;public class Person<T> {private T idCard;public Person(){}public Person(T idCard){this.idCard = idCard;}public static void main(String[] args) {//创建一个Person对象。需要给泛型参数赋值具体类型Person p = new Person<String>("cds123");Person<String> p2 = new Person<>("cds122");// 泛型参数,只能赋值引用类型,不能赋值八大基本数据类型Person<Long> p3 = new Person<>(3215466L);Date date = new Date();//小贴士:    实例化过程中,泛型只在一边给泛型参数赋值,但是两遍的尖括号都不能省略。Person<Date> p4 = new Person<>(date);}
}/*
当一个子类继承带有泛型的父类时,一般情况下要给泛型参数赋值具体类名*/class Student extends Person<Integer>{public Student(Integer idCard){super(idCard);}
}
/*
子类的泛型参数可以给父类的泛型参数赋值。
下面的例子就是E赋值给了T。*/class Teacher<E> extends Person<E>{public Teacher(E idCard){super(idCard);}
}/*
如果子类在定义期间,没有给泛型父类的泛型参数赋值,那么默认就是Object类型*/
class Persident extends Person{public Persident(Object idCard){super(idCard);}}

总结:

在实例化时,要给泛型参数赋具体值。实例化时两边的类名都可以赋值,也可以一边赋值,但是两边的尖括号不能去掉。在继承时也要赋值,如果没有赋值,那就默认object类型。也可以将子类的泛型赋值给父类。

2.2 泛型接口的应用

         将泛型用在接口上时,这个接口就叫做泛型接口。 泛型定义在接口名后。 用法和泛型类,一模一样。

测试代码:

import java.util.Arrays;
import java.util.Comparator;/*** 泛型接口,泛型用在接口上,就叫泛型接口。* @param <T>*/
public interface MyComparable<T,M> {/*** 两种类型进行比较* @param o1* @param o2* @return*/public int mycompare(T o1, M o2);public static void main(String[] args) {Employee[] employees = new Employee[3];employees[0] = new Employee("佐伊",18);employees[1] = new Employee("建模",19);employees[2] = new Employee("ez",17);//使用比较器接口,来重新定义比较规则:  从泛型的角度来说,在实例化接口时,要给泛型参数传具体类型。Comparator c = new Comparator<Employee>(){//重写比较器里面的compare方法public int compare(Employee o1, Employee o2) {//调用了自定义的员工类里的比较方法。return o1.name.compareTo(o2.name);}};Arrays.sort(employees);System.out.println(Arrays.toString(employees));}}
//子类实现接口 : 通常子类要给泛型接口的泛型参数赋值具体类型名。
//下面案例,就是给T和M都赋值了Employee这个类型。
class Employee implements MyComparable<Employee,Employee>, Comparator<Employee> {String name;int age;public Employee(String name, int age) {this.name = name;this.age = age;}public String toString(){return "["+name+","+age+"]";}// 在我们自己定义的方法中来实现比较规则。public int mycompare(Employee o1, Employee o2) {return o1.age - o2.age;}@Overridepublic int compare(Employee o1, Employee o2) {return mycompare(o1,o2);}}

2.3 泛型方法的应用

        泛型不仅能用在类和接口上,还可以用在方法上。 需要把泛型定义在返回值类型前面。

测试代码:

import java.util.Objects;public class MyUtil {public static <T> boolean equals(T t1,T t2){return t1.equals(t2);}public static void main(String[] args) {Cat cat = new Cat("咪咪");Cat cat1 = new Cat("咪咪");//泛型方法在调用期间,不需要指定具体类型,只需要传入具体对象//泛型方法调用期间,并没有给泛型参数赋值。下面的案例是c1给t1,c2给t2赋值,没有给T赋值。boolean a = MyUtil.equals(cat, cat1);System.out.println("equals"+a);}
}class Cat{String name;public Cat(){}public Cat(String name){this.name = name;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Cat cat = (Cat) o;return Objects.equals(name, cat.name);}@Overridepublic int hashCode() {return Objects.hashCode(name);}
}

注意:

在方法调用期间,不需要给泛型具体赋值,只需要传入变量即可。

3.泛型通配符

3.1 简介

        泛型通配符用 ? 表示,代表不确定的类型,是泛型的一个重要组成。 在调用时,表示我不关心具体类型。也可以使用通配符规定调用时,传入的类型的范围,即上边界,和下边界

3.2 简单应用 

import java.util.ArrayList;
import java.util.List;/*泛型通配符: ?  用于表明不关心调用时的具体类型。*/public class MyUtil {/*** 将集合元素打印到控制台上*/public static void print(List<?> lists){for(int i = 0; i<lists.size();i++){System.out.println(lists.get(i));}}/*** 上边界的定义: <? extends Number>*              具体使用的时候,可以是上边界的任何子类型或者是本类型。* @param list*/public static void print2(List<? extends Number> list){}/*** 下边界的定义: <? super 具体类名>*              具体使用的时候,可以是下边界的任何父类型或者本类型。* @param list*/public static void print3(List<? super Integer> list){for(int i = 0; i<list.size();i++){System.out.println(list.get(i));}}public static void main(String[] args) {List<Long> ns = new ArrayList<Long>();ns.add(1L);ns.add(2L);//注意 L 是Long类型不是long。ns.add(3L);MyUtil.print(ns);print2(new ArrayList<Long>());print2(new ArrayList<Number>());
//        print2(new ArrayList<Object>());最高到达Number类型//下边界的测试print3(new ArrayList<Number>());print3(new ArrayList<Object>());print3(new ArrayList<Integer>());
//        print3(new ArrayList<Long>());//Long和Integer没有关系。}}

3.3 总结

        泛型是一种特殊的类型,你可以把泛型用在类、接口、方法上,从而实现一些通用算法。

        此外,使用泛型有三个步骤:定义类型变量使用类型变量确定类型变量

确定类型变量这一步中,你可以用泛型通配符来限制泛型的范围,从而实现一些特殊算法。(方法 <? extends 类名>上边界、 <? super 类名>下边界(都包括类名))。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com