1、了解什么是泛型
泛型就是,实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值。
通俗来讲,泛型,就是适用于许许多多类型
我们知道,Object 是Java默认提供的一个类。默认会继承 Object 父类。即所有类的对象都可以使用Object 的引用进行接收。
那么,所有的父类,都默认为 Object 类,那么数组可否也创建为 Object 类?
示例代码如下:
class Array{
public Object[] array = new Object[10];
public Object getArray(int pos) {
return this.array[pos];
}
public void setArray(int pos,int val) {
this.array[pos] = val;
}
}
public class Test {
public static void main(String[] args) {
Array array = new Array();
array.setArray(0,10);
//array.setArray(1,"hello"); //这里因为定义类型不同会出现报错
array.getArray(1);
}
}
不难发现,任何类型的数据都可以传输,所以,**泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。**让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。
泛型类的语法:
class 泛型类名称<类型形参列表> { // 这里可以使用类型参数 }
class ClassName<T1, T2, …, Tn> { }
泛型类的使用:
泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
示例如下
MyArray<Integer> list = new MyArray<Integer>();
使用泛型后的代码如下:
class Array<T>{
public T[] array = (T[])new Object[10];
public T getArray(int pos) {
return this.array[pos];
}
public void setArray(int pos,T val) {
this.array[pos] = val;
}
}
public class Test {
public static void main(String[] args) {
Array<Integer> myArray1 = new Array<>();//这里申请一个存放int类型的空间
myArray1.setArray(0,10);
myArray1.setArray(1,12);
int ret = myArray1.getArray(1);//
System.out.println(ret);
Array<String> myArray2 = new Array<>();//后尖括号内的数据类型可以省略
myArray2.setArray(2,"bit");//这里申请一个存放string类型的空间
}
}
这里不难看出,泛型可以存放各种类型数据,并且可以将不同元素分类型存放,便于后期维护。
2、泛型的上界
在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
语法如下
class 泛型类名称<类型形参 extends 类型边界> {
…
}
这里写一个简单的排序描述。
//首先写一个 person 类来实现 comparable 比较方法
class Person implements Comparable<Person>{
public int age;
public Person(int age) {
this.age = age;
}
@Override
public int compareTo(Person o) {
return this.age-o.age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
//定义一个泛型继承comparable方法并重写
class Alg<T extends Comparable<T>> {
public T findMax (T[] array) {
T max = array[0];
for (int i = 1; i < array.length; i++) {
//if(max < array[i]) {
if(max.compareTo(array[i]) < 0 ) {
max = array[i];
}
}
return max;
}
public class Test {
public static void main1(String[] args) {
Alg<Person> alg = new Alg<>(); //实例化
Person[] people = {new Person(10),new Person(15)}; // 定义数组存放信息
Person person = alg.findMax(people);
System.out.println(person);
}
//另一种实现
public static void main2(String[] args) {
Alg<Integer> alg = new Alg<>();
Integer[] array = {1,2,3,4};
Integer ret = alg.findMax(array);
System.out.println(ret);
3、泛型方法
语法
方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表)
public static <E> void swap(E[] array, int i, int j) {....}
class Alg2{
//泛型方法 <E> type (E[] array)
public static<T extends Comparable<T>> T findMax (T[] array) {
T max = array[0];
for (int i = 1; i < array.length; i++) {
//if(max < array[i]) {
if(max.compareTo(array[i]) < 0 ) {
max = array[i];
}
}
return max;
}
}
public class Test {
public static void main(String[] args) {
Integer[] array = {1,2,3,4};
Integer ret = Alg2.<Integer>findMax(array);
System.out.println(ret);
}
}
4、通配符
概念:通配符是用来解决泛型无法协变的问题的
首先写一个泛型代码
class Message<T> {
private T message ;
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
}
public class Test {
public static void main(String[] args) {
Message<String> message= new Message<>();
message.setMessage("hello world");
/*
Message<Integer> message = new Message() ;
message.setMessage(99); fun(message); // 出现错误,只能接收String
*/
fun(message);
}
public static void fun(Message<String> words){
System.out.println(words.getMessage());
}
}
不难发现,这样就出现了问题,但是又不可能每次都去修改,这里就可以引入通配符。
public class TestDemo {
public static void main(String[] args) {
Message<Integer> message = new Message() ;
message.setMessage(55);
fun(message);
}// 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
public static void fun(Message<?> temp){
System.out.println(temp.getMessage());
}
}
(1)泛型的上界
? extends 类:设置泛型上限。
语法如下:
<? extends 上界>
<? extends Number>//可以传入的实参类型是Number或者Number的子类
示例如下:
class Food{
}
class Fruit extends Food{
}
class Apple extends Fruit{
}
class Banana extends Fruit{
}
//设置上界
class Massage<T>{
private T massage;
public T getMassage(){
return massage;
}
public void setMassage(T massage){
this.massage = massage;
}
}
public class Test {
public static void fun(Massage<? extends Fruit> temp){
//出错
temp.setMassage(new Apple());
temp.setMassage(new Banana()); //无法设置添加相应的值
System.out.println(temp.getMassage());
}
public static void main(String[] args) {
Massage<Fruit> massage = new Massage<>();
massage.setMassage(new Fruit());
fun(massage);
}
}
如图,这里出错的原因是,因为temp接收的是Fruit和他的子类,此时存储的元素应该是哪个子
类无法确定。所以添加会报错!但是可以获取元素。
(2)通配符的下界
?super 类:指泛型下界。
语法如下:
<? super 下界>
<? super Integer>//代表 可以传入的实参的类型是Integer或者Integer的父类类型
示例如下:
class Food {
}
class Fruit extends Food {
}
class Apple extends Fruit {
}
class Message<T> {
private T message ;
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<Fruit> message = new Message<>() ;
message.setMessage(new Fruit());
fun(message);
Message<Food> message2 = new Message<>() ;
message2.setMessage(new Food());
fun(message2);
}//temp 接收Fruit及其子类的一个Message
public static void fun(Message<? super Fruit> temp){ // 此时可以修改!!添加的是Fruit 或者Fruit的子类
temp.setMessage(new Apple());//这个是Fruit的子类
temp.setMessage(new Fruit());//这个是Fruit的本身
//Fruit fruit = temp.getMessage(); 不能接收,这里无法确定是哪个父类
System.out.println(temp.getMessage());//只能直接输出
}
}