一、泛型

1、泛型定义

泛型(generics)是JDK5.0以后的特性,提供了编译期间安全监测机制,它是将数据类型参数化的一种方式。 例如:在对方法进行编写参数列表时,以前我们需要知道方法的参数类型 ,现在使用泛型机制可以将方法的参数类型也作为 “未知的类型” ,在调用该方法时传递该类型。

2、泛型的使用

2.1 泛型类(generic class)

它是一种具有一个或多个类型变量的类,(一个变量可以有多种类型)

语法

public  class  类<T>{
      // 类里面的数据类型 和 方法返回值,以及方法的参数都可以使用T  
      // <>里面可以是任意大写字母
      
  }
public class People<T> {
    private T name;
    private T sex;

    public T getName() {
        return name;
    }
       public People(T name,T sex){
        this.name= name;
        this.sex = sex;
    }
    public People(){

    }
}
// 创建没有指定泛型的对象 ,它默认是Object类型
        People  obj= new People();
        obj.setName("李四");
        System.out.println(obj);
        System.out.println(((String)obj.getName()).length());

        // 创建泛型类的对象
        People<String> people = new People<String>("张三","男");
        System.out.println(people);
        System.out.println(people.getName().length());

定义泛型的字母

T : Type: 变量类型

K: Key : 任意键的类型

V: Value : 任意值的类型

E:ELement 用于定义集合的元素类型

2.2 泛型接口(generic interface)

在接口中定义泛型,使接口的方法可以使用该泛型,实现类实现该接口时需要指定接口的类型、

语法:

public interface Genarator<T> {
    public T getValue();

    public void setValue(T s);


}
public class StringGenarator implements  Genarator<String> {
   private String name;

    @Override
    public String getValue() {
        return name;
    }

    @Override
    public void setValue(String s) {
        this.name=s;
    }
public class StudentGenarator implements Genarator<Student> {
    private Student  stu;

    @Override
    public Student getValue() {
        return stu;
    }

    @Override
    public void setValue(Student s) {
        this.stu = s;
    }
}

泛型接口的好处:

让接口的方法的返回值或参数类型 也参数化 (泛型)

2.3 泛型方法

a、为什么会使用泛型方法

当一个类中 只有某个方法需要使用泛型,而不是类的全部方法使用泛型,这时可以将泛型定义的范围缩小,通常我们可以定义进行泛型方法。

b、定义泛型方法

语法:

public  class 普通类{
      
      public <T>  T  getValue(){
          
      }
      public <T> void setValue(T t){
          
      }  
      
  }
public class Convert {
    /**
     * 转成字符串的方法
     * @param <T> : 任意类型

     * @return
     */
    public <T> String convertString(T t){
        return  t.toString();
    }

    public <K,V> V converted(K k){
        return (V)k;// 强转的前提 是k -v 有关系
    }

泛型的好处:

1、 可以对类的数据类型 写通用类型,提高代码的复用性 和 可扩展性

2.4 泛型通配符

在定义泛型时除了可使用大写字母表示一种泛型类以外,还可以使用通配符表示泛型类型,如下三种表示方法

:表示一种通用的泛型类,与相似 :表示 泛型类型是T的子类,或者是T : 表示泛型类型是T的父类,或者是T 问题: 与

T t = new T() // 语法满足
  ? t = new ?()  // 语法不满足

"< T >" 是一种确定的类型 , 可以表示定义泛型类或泛型方法

"<?>"是一种不确定的类型, 不能定义泛型类或泛型方法, 通常用于作为方法的形参

public class Dept<T> {
    // 第一个员工
     private T first;
     // 第二个员工
     private T second;
public class Employee {
    private String ename;

    public String getEname() {
        return ename;
    }
public class Manager extends  Employee {

    // 通过经理对象 给经理赋值名称
    public Manager(String ename){
        super(ename);
    }
// 使用不确定的泛型类型 <?>

    /**
     *
     * 这里的部门的泛型可以是任意类型
     */
    public void showInfo(Dept<?> dept){

        System.out.println(dept.getFirst());

    }

    /**
     * @param dept 的泛型可以是Employee  或者继承自Employee
     * @param dept
     */
    public void showInfo2(Dept<? extends Employee> dept){

        System.out.println(dept.getFirst());
        System.out.println(dept.getSecond());

    }

    /**
     *
     * @param dept 的泛型必须是 Manager 或者 Manager的父类
     */
    public void showInfo3(Dept<? super Manager> dept){

        System.out.println(dept.getFirst());
        System.out.println(dept.getSecond());

    }

    public static void main(String[] args) {
         TestDept obj = new TestDept();

         //创建部门对象
        Dept<String> dept = new Dept();
        dept.setFirst("员工1");
        dept.setSecond("员工2");
         obj.showInfo(dept);

         // 在部门中添加 员工对象
        Dept<Employee> dept2 = new Dept();
        dept2.setFirst(new Employee("小强"));
        dept2.setSecond(new Employee("小花"));
        //这里的dept2的泛型是 Employee
        obj.showInfo2(dept2);

        Dept<Manager> dept3 = new Dept();
        dept3.setFirst(new Manager("张经理"));
        dept3.setSecond(new Manager("王经理"));
        //这里的dept3的泛型是  Manager
        obj.showInfo2(dept3);

        //  调用时 参数的泛型必须是 Manager 或Manager的父类
        obj.showInfo3(dept3);
        obj.showInfo3(dept2);
    }