45、泛型

泛型

泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型。泛型也可以看作是一个变量,用来接收数据类型。

    E e:Element 元素

    T t:Type 类型

public class ArrayList<E>{
    public boolean add(E e){}
    public E get(int index){}
}

创建集合对象的时候,就会确定泛型的数据类型

ArrayList<String> list = new ArrayList<String>();

创建集合对象,不使用泛型

  好处:集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据.

  弊端: 不安全,会引发异常.

ArrayList list=new ArrayList();


创建集合对象,使用泛型
好处

  1. 避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
  2. 把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码时候就会报错)

弊端

​    泛型是什么类型,只能存储什么类型的数据

ArrayList<String> list = new ArrayList<String>();


含有泛型的类

定义和使用含有泛型的类

    泛型可以接收任意的数据类型,所以在不确定是什么数据类型的时候,可以创建一个泛型的类。

//泛型类的创建:
public class GenericClass<E> {
	private E name;

 	public E getName() {
     	return name;
 	}

 	public void setName(E name) {
     	this.name = name;
	}
}

//泛型类的使用:
public class DemoGeneric {
 public static void main(String[] args) {
     //不写泛型默认为Object类型
     GenericClass gc1 = new GenericClass();
     gc1.setName("字符串");
     Object obj = gc1.getName();
     System.out.println(obj);

     //创建GenericClass对象,泛型使用Integer类型
     GenericClass<Integer> gc2 = new GenericClass<>();
     gc2.setName(1);
     Integer name = gc2.getName();
     System.out.println(name);

     //创建GenericClass对象,泛型使用String类型
     GenericClass<String> gc3 = new GenericClass<>();
     gc3.setName("小明");
     String name1 = gc3.getName();
     System.out.println(name1);
	}
}

输出结果
字符串
1
小明


含有泛型的方法

创建和使用含有泛型的方法

    泛型定义在方法的修饰符和返回值类型之间

格式:
修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
	方法体;
}

    含有泛型的方法,在调用方法的时候确定泛型的数据类型,传递什么类型的参数,泛型就是什么类型。

//修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型))
public <M> void method01(M m){
 	System.out.println(m);//方法体
}

public class GenericMethod {
    //创建含有泛型的方法:
 	public <M> void method01(M m){
       	System.out.println(m);
 	}

 	//定义一个含有泛型的静态方法
 	public static <S> void methodStatic(S s){
   		System.out.println(s);
 	}
}
//使用含有泛型的方法:
public class DemoGeneric {
   	public static void main(String[] args) {
       	GenericMethod gm = new GenericMethod();

        //调用含有泛型的方法method01,传递什么类型,泛型就是什么类型
      		gm.method01(10);
       		gm.method01("abc");
       		gm.method01(8.8);
         	gm.method01(true);

        	gm.methodStatic("静态方法,不建议创建对象使用");
        	GenericMethod.methodStatic("静态方法,通过类名直接使用");
   	}
}
含有泛型的接口
格式:
修饰符 interface接口名<代表泛型的变量>{ }
public interface MyGenericInterface<E>{
}

使用方式
   way1:定义接口的实现类,实现类指定接口的泛型。
   way2:接口使用什么泛型,实现类就是用什么泛型,类跟着接口走。(定义一个含有泛型的类,创建对象的时候确定泛型的类型)

//定义含有泛型的接口:
public interface GenericInterface<I> {
   	public abstract void method(I i);
}

//使用way1的实现类:实现类指定接口的泛型
public class GenericInterfaceImpl01 implements GenericInterface<String>{

   	@Override
   	public void method(String s) {
       	System.out.println(s);
   	}
}

//使用way2的实现类:实现类也不指定接口的泛型,等到创建对象时再指定
public class GenericInterfaceImpl02<I> implements GenericInterface<I>{

   	@Override
   	public void method(I i) {
       	System.out.println(i);
   	}
}

//主函数调用
public class DemoMain {
   	public static void main(String[] args) {
       	//way1:实现类中指定了String型,所以此时只能接收字符串
       	GenericInterfaceImpl01 gi1 = new GenericInterfaceImpl01();
       	gi1.method("字符串");
		
       	//way2:实现类中没指定泛型,创建对象时指定泛型,就可以接收不同种类的数据了
       	GenericInterfaceImpl02<Integer> gi2 = new GenericInterfaceImpl02<>();
       	gi2.method(10);
       	GenericInterfaceImpl02<Double> gi3 = new GenericInterfaceImpl02<>();
        gi3.method(8.8);
   	}
}
泛型的通配符

    当使用泛型类或接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身的方法无法使用。

泛型的通配符
    ?:代表任意的数据类型
使用方式
    不能创建对象使用,只能作为方法的参数使用

public class Demo {
    public static void main(String[] args) {
        ArrayList<Integer> list01 = new ArrayList<>();
        list01.add(1);
        list01.add(2);

        ArrayList<String> list02 = new ArrayList<>();
        list02.add("a");
        list02.add("b");

        printArray(list01);
        printArray(list02);
    }

    /*
    定义一个方法,能遍历所有类型的ArrayList集合
    由于不知道ArrayList集合使用什么数据类型,可以使用泛型的通配符?来接收数据类型
  */

    public static void printArray(ArrayList<?> list){//只能作为方法的参数使用
        Iterator<?> it = list.iterator();//定义迭代器
        while(it.hasNext()) {//使用迭代器进行遍历
            System.out.println(it.next());
        }
    }
}
通配符高级使用–受限泛型

之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但JAVA的泛型中可以指定一个泛型的上限下限。(懂啥意思能看明白即可,使用的相对较少)

泛型的上限

  • 格式类型名称 <? extends 类 > 对象名称
  • 意义:只能接收该类型及其子类

泛型的下限

  • 格式类型名称 <? super 类 > 对象名称
  • 意义:只能接收该类型及父类
public class DemoGeneric {
    public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        Collection<Number> list3 = new ArrayList<>();
        Collection<Object> list4 = new ArrayList<>();

        getElement1(list1);
        getElement1(list2);//报错
        getElement1(list3);
        getElement1(list4);//报错

        getElement2(list1);//报错
        getElement2(list2);//报错
        getElement2(list3);
        getElement2(list4);

        /*
        类与类之间的继承关系
        Integer extends Number extends Object
        String extends Object
         */
    }

    //泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
    private static void getElement1(Collection<? extends Number> coll) {
    }

    //泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
    private static void getElement2(Collection<? super Number> coll) {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值