泛型..

1.泛型

所谓泛型 其实就是一种类型参数(我们平常所见到的参数指的就是方法中的参数 他接收有外界传递来的值 然后在方法中进行使用) 并且还提高了代码的复用率
何以见得提高了代码的复用率 其实就是通过对比使用了泛型技术和没有使用泛型技术之间的区别:
以下是没有使用泛型技术的案例

public class Student1 {
   
    // 第一个学生类他的分数接收的是一个浮点类型的数据
    double score;
    // 定义getter、setter方法
    void setScore(double score){
   
        this.score = score;
    }
    double getScore(){
   
        return score;
    }
}
public class Student2 {
   
    // 这个学生类接收的是字符串类型的分数
    String score;
    // 定义getter、setter方法
    void setScore(String score){
   
        this.score = score;
    }
    String getScore(){
   
        return score;
    }
}
public class Student3 {
   
    // 第三个学生类的分数就定义为整型
    int score;
    // 定义相关的getter、setter方法
    void setScore(int score){
   
        this.score = score;
    }
    int getScore(){
   
        return score;
    }
}

从以上代码中我们可以看出 定义了三种不同类型的分数 就要定义三份逻辑相似的代码 如果分数的类型规模一旦庞大起来 那么其实效率是十分低下的
现在引入了泛型技术以后 就不会出现以上这种局面 并且会提高同一份代码的复用率

public class Student<T>{
   
    // 泛型是一种类型参数 有外界的实参所决定 并且可以在类中使用
    T score;
    // 定义一个getter、setter方法
    void setScore(T score){
   
        this.score = score;
    }
    T getScore(){
   
        return score;
    }
}

我们可以在主函数中测试一下这个代码的正确性

public class Main {
   
    public static void main(String[] args) {
   
        // 我们来试用一下泛型好不好用吧
        Student<String> s1 = new Student<>();
        Student<Integer> s2 = new Student<>();
        Student<Double> s3 = new Student<>();
        s1.setScore("优秀");
        s2.setScore(100);
        s3.setScore(99.5);
        System.out.println(s1.getScore());
        System.out.println(s2.getScore());
        System.out.println(s3.getScore());
    }

}

从结果可以看出 这个泛型类型是写的很成功的 并且从中我们还能够得知 从java7开始 右边<>内就可以不用写出具体的泛型了

而且我们的泛型名称是有命名建议的:
T Type
E Element
K Key
N Number
V Value
S、U、V 当你想要表示连续类型中的第二个、第三个、第四个泛型的时候的命名建议

类名后面不仅可以支持一个泛型 也可以支持多个泛型

public class Student<N, S>{
   
    private N no;
    private S score;
    public Student(N no, S score){
   
        this.no = no;
        this.score = score;
    }
}
public class Main {
   
    public static void main(String[] args) {
   
        Student<Integer, Double> s = new Student<>(1, 100.0);
    }
}

何为泛型类型?其实就指的是哪些使用了泛型的类或者接口
比如一些诸如java.util.Comparator、java.util.Comparable之类的接口

2.泛型类型的继承

我们从前面的多态都知道 如果类或者接口之间存在父子关系的话 那么让父类引用指向子类对象是可以编译成功的
以下的案例中 从结果可以明显发现strBox和intBox不存在父子关系 objBox和strBox之间不存在父子关系
有些人可能会以泛型的继承关系来作为泛型类型的继承关系 那好 我们可以超这个方向继续往下想 如果结论果真是如此的话 那么第一对关系肯定不符合 因为String和Integer压根不存在父子关系 只有第二对中的String和Object之间存在父子关系 好 接着往下想 如果是父子关系的话 多态是可以编译通过 也就是说 strBox和objBox指向的是同一个对象 然后我通过objBox设置了所指对象的element值 他的类型为Object类型 然后通过strBox获取所指对象的element值 并且通过一个String变量进行获取 但是我们可以清楚的发现由于之前element已经被设置为Object类型 所以导致Object赋值给了String 其实如果没有强制转换的话 这个语句是不能通过编译的 但是实际上这个语句是编译通过的 所以说我们刚才的strBox和objBox之间是不存在父子关系的

public class Main {
   
    public static void main(String[] args) {
   
        Box<String> strBox = new Box<>();
        Box<Integer> intBox = new Box<>();
        Box<Object> objBox = new Box<>();
        strBox = intBox;// error
        objBox = strBox;// error
        // 如果上面代码是正确的话 那么思考一下下面的代码
        objBox.setElement(new Object());
        String str = strBox.getElement();
    }
}

所以说下面这张图其实清楚的阐明了Number和Integer以及Box之间的关系
在这里插入图片描述

接着一个案例
在这里插入图片描述
在这里插入图片描述

我们都知道jdk中存在这这样如图所示的这样一种关系
由于上述各种接口或者类之间存在这父子关系 所以以下的代码其实都是可以编译通过的

public class Main {
   
    public static void main(String[] args) {
   
        Iterable<String> it = null;
        Collection<String> col = null;
        List<String> li = null;
        ArrayList<String> al = null;
        it = col;
        col = li;
        li = al;
    }
}

但是如果是以下代码的话 就不能够编译通过了
假设我们的List和ArrayList都是自定义的(就是非jdk源码 是允许的) 并且他们类或者接口的结构是一样的 那么如果按照刚才那个反例来看的话 那么list和al是父子关系 那么list和al所指对象是一致的(假设list的泛型为Object al的泛型是String) 并且我通过list设置所指对象的no 这个no就是Object类型的 然后通过al获取所指对象的no 并且通过String变量保留 而Object是不能够在没有强制转换的前提下完成这个赋值的 但是实际上这个操作是允许的 所以说list和al其实不是父子关系

public class Main {
   
    public static void main(String[] args) {
   
        List<Object> list = null;
        ArrayList<String> al = null;
        list = al;// error
    }
}

我可以总结一下就是说
当泛型不一致的话 那么泛型类型就一定不存在父子关系
当泛型一致的话 那么泛型类型也不一定存在父子关系 只有当泛型类型是有继承或者实现关系的话 那么泛型类型才有父子关系

前面说到泛型可以支持连续多个的 当我们两个类或者接口中的第一个泛型是一致的 并且子类可以存在第二个泛型的时候 那么这时候子类和父类之间是存在父子关系的

public interface MyList<E, T> extends List<E> {
   
    void setNo(T no);
}
public class Main {
   
    public static void main(String[] args) {
   
        List<String> li = null;
        MyList<String, Integer> ml1 = null;
        MyList<String, Double> ml2 = null;
        MyList<String, String> ml3 = null;
        li = ml1;
        li = ml2;
        li = ml3;
    }
}

从结果显示 编译是通过的 说明其实上述的这种操作是完全被允许的

3.原始类型

何为原始类型 其实就是没有为泛型提供一个具体的类型
在这里插入图片描述
从上图中 我们想说的是:
当我们使用了原始类型的时候 那么编译器就会警告我们这是一个原始类型 发出rawtypes警告
当我们将非原始类型赋值给原始类型的时候 编译器是很正常的
但是当我们将原始类型赋值给非原始类型的时候 编译器会发出unchecked警告
我们对于以上这些由编译器发出的警告可以通过@SuppressWarnings这个注解进行消除

public class Box<T>{
   
    private T no;
    public T getNo(){
   
        return no;
    }
    public void setNo(T no){
   
        this.no = no;
    }
}
public class Main {
   
    public static void main(String[] args) {
   
        Box box = new Box();
        box.setNo(new Object());
        Object o = box.getNo();
    }
}

通过上面这段代码 我想说的是如果是原始类型的话 那么当我们进行getter和setter方法的时候 所涉及到的no都是Object类型的 那么我们可能会有一个疑惑 就是这不是和泛型为Object的泛型类型一样吗 那么这两个等价吗 其实他们两者是有着本质的区别的:
一个是原始类型 一个是非原始类型 只是原始类型的getter和setter方法中涉及到的no都是Object类型的

相关推荐

  1. <span style='color:red;'>泛</span><span style='color:red;'>型</span>..

    ..

    2024-01-22 09:02:04      33 阅读
  2. 14 # 类与约束

    2024-01-22 09:02:04       34 阅读
  3. (标签)

    2024-01-22 09:02:04       39 阅读
  4. Golang

    2024-01-22 09:02:04       25 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-22 09:02:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-22 09:02:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-22 09:02:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-22 09:02:04       18 阅读

热门阅读

  1. 编程羔才生-前端访问后端出现read ECONNRESET

    2024-01-22 09:02:04       38 阅读
  2. Oracle pagesize 和 linesize区别

    2024-01-22 09:02:04       31 阅读
  3. kafka入门(十):副本数据同步

    2024-01-22 09:02:04       38 阅读
  4. 聊聊PowerJob的UserService

    2024-01-22 09:02:04       38 阅读
  5. 微信小程序中使用自定义 icon 图标

    2024-01-22 09:02:04       34 阅读
  6. 三、安全工程—安全架构(CISSP)

    2024-01-22 09:02:04       36 阅读
  7. 《繁花》中服饰公司的股票开盘价如何涨到了18.8

    2024-01-22 09:02:04       36 阅读
  8. Angular:引领未来的前端框架

    2024-01-22 09:02:04       36 阅读
  9. 流畅的Python(四)- 文本和字节序列

    2024-01-22 09:02:04       24 阅读