Java中的泛型

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());//只能直接输出 
} 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值