泛型——简要概述

泛型——简要概述,第1张

泛型——简要概述

引用:

B站韩顺平 零基础30天学会java

菜鸟教程-Java泛型

泛型介绍

  Java泛型(genetics)是JDK 5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是所 *** 作的数据类型被指定为一个参数。

  Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常(也就是类型安全检测机制),同时,代码更加简洁、健壮。

下面用一个实例详细分析:
  编写程序,在ArrayList中,添加3个Dog对象。Dog对象中有name属性,并输出name(要求使用getName())

  • 这里的ArrayList没有<>,其中存储的类型是Object
import java.util.ArrayList;

public class Demo01 {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        arrayList.add(new Dog("来福"));
        arrayList.add(new Dog("旺财"));
        arrayList.add(new Dog("狗蛋"));
        //如果程序员不小心添加了其他类!
        arrayList.add(new Cat("小花"));
        for(Object o : arrayList){
            //向下转型 Object ==> Dog
            Dog dog = (Dog) o;
            System.out.println("这里有狗!叫"+dog.getName());
        }
    }
}

class Dog{
    private String name;
    public Dog(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}
class Cat{
    private String name;
    public Cat(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }
}
  • 这里假如!假如!程序员在编写代码时,不小心多添加了一个别的类的实例对象到ArrayList中,代码显示时是没有异常的!这样是存在隐患的,同时编译器是发现不了。在运行之后,会发生报错,类型转换异常!

  • 使用这种传统的方法不能对加入到集合ArrayList中的数据类型进行约束(不安全)。同时在遍历时,需要进行类型转换,如果集合中的数据量较大,对效率会存在影响

当使用泛型之后

  • 编译器发现了ArrayList添加到类型不满足要求,会报错(没使用泛型是发现不了的),这样在编译时就提高了安全性
  • 遍历时,可以直接取出Dog类型,不用类型转换,节省效率!


那么,泛型到底是什么?简单来说,泛型就是——一个表示数据类型的数据类型!

泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值类型,或者是参数类型。

class Person{
    E s;// E表示 s 的数据类型,该数据类型在定义Person对象时指定,即在编译期间,就确定E是什么类型
    
    public Person(E s) {//E也可以是参数类型
        this.s = s;
    }
    
    public E f(){//也可以是返回类型
        return s;
    }
}	

假定有这样一个需求:写一个排序方法,能够对整形数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?

答案是使用Java泛型

使用Java泛型的概念,可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整数型数组、浮点数数组、字符串数组等进行排序。

泛型方法

定义泛型方法的规则

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数部分在方法返回类型前

  • 每一个类型参数声明部分包括一个或多个类型参数,参数键用逗号隔开。一个泛型参数,也被称为一个类型变量,适用于指定一个泛型类型名称的标识符

  • 类型参数能被用来声明返回值类型,并且作为泛型方法得到的实际参数类型的占位符

  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用类型,不能是原始类型(像int、double、char等)

java中的泛型标记符

  • E Element(在集合中使用,因为集合中存在放的是元素

  • T Type(java类)

  • K key(键)

  • V Value(值)

  • N Number(数值类型)

  • ? 表示不确定的java类型

实例

下面的列子演示如何使用泛型方法打印不同类型的元素

public class Demo02 {
    //泛型方法
    public static  void printArray(E[] inputArray){
        //输出元素数组
        for(E element : inputArray){
            System.out.print(element+"  ");
        }
    }

    public static void main( String args[] ) {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };

        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组

        System.out.println( "n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组

        System.out.println( "n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    }
}

运行结果为:

有界的参数类型

  指限制被允许传递到一个类型参数的类型范围。例如,一个 *** 作数字的方法可能只接受Number或者Number子类的实例。这就是有界类型参数参数的目的。要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,然后跟紧他的上界。

public class Demo03 {
    // 比较三个值并返回最大值
    public static > T maximum(T x, T y, T z) {
        T max = x; // 假设x是初始最大值
        if ( y.compareTo( max ) > 0 ){
            max = y; //y 更大
        }
        if ( z.compareTo( max ) > 0 ){
            max = z; // 现在 z 更大
        }
        return max; // 返回最大对象
    }
    public static void main( String args[] ) {
        System.out.println( "3,4,5 中最大的数为"+ maximum( 3, 4, 5 ) );
        System.out.println( "6.6, 8.8, 7.7 中最大的数为" + maximum( 6.6, 8.8, 7.7 ));
        System.out.println( "pear,apple,orange中最大的数为" + maximum( "pear", "apple", "orange" ));
    }
}
泛型类

  泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。

  和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。

public class Box {
    private T t;
    public void add(T t){
        this.t = t;
    }
    public T get(){
        return t;
    }

    public static void main(String[] args) {
        Box box1 = new Box<>();
        Box box2 = new Box<>();

        box1.add(13);
        box2.add("mikasa");

        System.out.println("整数型值为:" + box1.get());
        System.out.println("字符串型值为:" + box2.get());
    }
}

​ 运行结果:

类型通配符

  类型通配符一般是使用?代替具体的类型参数。例如List在逻辑上是List,List等所有List<具体类型实参>的父类

  类型通配符的上限通过形如List来定义,如此定义就是通配符泛型值接受Number及其下子层类类型。

import java.util.ArrayList;
import java.util.List;

public class Demo04 {
    public static void main(String[] args) {
        List name = new ArrayList();
        List age = new ArrayList();
        List number = new ArrayList();

        name.add("mikasa");
        age.add(13);
        number.add(624);

//        getUperNumber(name); 
        getUperNumber(age);
        getUperNumber(number);

    }

    public static  void getData(List data){
        System.out.println("data:" + data.get(0));
    }

    public static void getUperNumber(List data){
        System.out.println("data:" +data.get(0));
    }
}

//输出结果
//data:18
//data: 314

//getUperNumber(name); 会出现错误,因为 getUperNumber() 方法中的参数已经限定了参数泛型上限为 Number,所以泛型为 String 是不在这个范围之内,所以会报错。

  类型通配符下限通过形如List来定义,表示类型只接受Number及其上层父类类型,如Object类型的实例

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5574660.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存