Java SE(七)之泛型(泛型类,泛型接口,泛型方法)

泛型概述

JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
将类型由原来的具体类型参数化,然后在使用/调用时传入具体的类型

这个参数化可以用在类,方法,接口中

1.泛型的引入

先来看看泛型的背景:

(1)需要一个排序算法,能对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?——Java 泛型。

(2)如果在创建ArrayList集合时没有指定数据类型,则会默认为所有的数据类型都是object类型,此时可以往集合添加任意的数据类型。

// 创建时没有指定数据类型(即Object类型)
ArrayList list = new ArrayList();

// 此时可以添加任意数据类型
list.add(123);
list.add("hello");

// 如果我们想要获取元素,此时就会报错(即使强转有时也不行)
String s = (String)list.get(0);

这样做的坏处:在获取/使用数据时,不知道强转为什么类型,并且无法使用他的特有行为。

此时推出了泛型,可以在添加数据的时候就把类型进行统一。而且我们在获取数据的时候,也省的强转了,非常的方便。

2.泛型的定义

<类型>:指定一种类型的格式
<类型1,类型2>:指定多种类型的格式

这里的类型在定义的时候可以看成形参
而在之后调用时给定的类型可以看成实参,实参只能是引用数据类型

如果要基本数据类型,需要用到他们的包装类:
(关于基本类型和引用类型区别,可参见:http://t.csdn.cn/xCg4M

3.泛型的好处

  • 统一数据类型
  • 把运行时期的问题提前到了编译期间,避免了强制数据类型转换

4.泛型标记符

符号含义
E - Element在集合中使用(集合中存放的是元素)
T - TypeJava 类
K - Key
V - Value
N - Number数值类型
不确定的 java 类型

泛型类

当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类

class 类名<E> {
}

创建该类对象时,E就确定类型

可以定义自己的泛型类,例如:

public class MyArrayList <E>{
    int size;
    Object[] object = new Object[10];

    // E表示不确定的类型,在类名后已经声明
    // e 是形参
    public boolean add(E e)
    {
        object[size] = e;
        size++;
        return true;
    }
    public E get(int index)
    {
        return (E)(object[index]);
    }
}

创建对象(和ArrayList操作很相似):

MyArrayList<Integer> list = new MyArrayList<>();
list.add(12);
list.add(23);
int num = list.get(0);

泛型方法

方法中形参类型不确定时,采用泛型方法

定义格式:

修饰符 <类型> 返回值类型 方法名(类型 变量名){ }
e.g. public <T> void show(T t) { }

e.g.

public static < E > void printArray( E[] inputArray )
   {
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }

在调用时指定数据类型即可

Integer[] intArray = { 1, 2, 3, 4, 5 };
printArray( intArray  ); // 传递一个整型数组

Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 }; 
printArray( doubleArray ); // 传递一个双精度型数组

泛型接口

定义格式:

修饰符 interface 接口名<类型>{ }
e.g. public interface List<T>{ }

使用泛型接口的两种方式:

1.实现类给出具体的类型

public class MyArrayList1 implements List<String> {
}

此时需要重写List接口中的抽象方法,并且原本List接口中的泛型E都要用String进行代替,即用具体类给出具体类型

在创建对象时,也不用像泛型那样创建,可以直接和普通类对象一样(因为泛型已经被确定了)

MyArrayList1 myArrayList = new MyArrayList();

2.实现类延续泛型,在创建对象时再确定类型

public class MyArrayList2<E> implements List<E> {
}

那么在创建对象时就需要指定泛型类型

MyArrayList2<String> myArrayList = new MyArrayList2<>();

通配符

定义一个方法,形参是集合,但是集合中的类型不确定,此时可以采用泛型方法

public static<E> void method(ArrayList<E> list){

}

使用泛型方法有个缺点,就是它可以接受任意的数据类型,比如这里有四个类,分别是有继承关系的三个类Ye,Fu,Zi和另一个普通类Student类

class Ye {}

class Fu extends Ye{}

class Zi extends Fu{}

class Student{}

当只希望传递限定的类型时,可以使用通配符

通配符:?

具体用法:

? extends E:表示可以传递E或者E的所有子类类型
? super E : 表示可以传递E或者E的所有父类类型

例如当我只传递Ye Fu Zi 这三个类时,可以用通配符限定

public static void method(ArrayList<? extends Ye> list){

}

注意:
泛型不能继承,但是数据能继承

泛型指定类型后只能是该类型,他的子类或者父类是不允许的
但是数据可以有继承性:

// 声明一个方法,形参是 ArrayList 集合,集合对象是Ye对象
public static void method(ArrayList<Ye> list){
}

public static void main(String[] args) {
    // 创建三个对象集合
	ArrayList<Ye> list1 = new ArrayList<>();
	ArrayList<Fu> list2 = new ArrayList<>();
	ArrayList<Zi> list3 = new ArrayList<>();
    
	method(list1);
	
	/*
	报错 ,因为需要的是Ye类型的对象,其他的类型对象不可以
	也就是说泛型不能继承。
	*/
	// method(list2);
}
// 添加对象时可以
list1.add(new Ye());
list1.add(new Fu());
list1.add(new Zi());

与C++模板类

java泛型和C++模板类很像,两者都支持参数化类型的语言功能,具体细节如果以后遇到再来补充

可变参数

(之后遇到再详细写一下)
在这里插入图片描述

参考链接:
https://www.bilibili.com/video/BV17F411T7Ao?p=1&share_source=copy_web&vd_source=fa075f0e5dab81ef7c98b9eb4c47d9a7
https://www.runoob.com/java/java-tutorial.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值