Java泛型

一. 为什么要使用泛型?

  public class Test{
  
      public static void main(String[] args) {
         ArrayList list = new ArrayList();
          list.add("name");
          list.add("location");
          list.add(18956);
  
          for (int i = 0; i < list.size(); i++) {
             String name = (String) list.get(i); // 1
             System.out.println("name:" + name);
         }
     }
 }

此时list默认的类型为Object类型,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。在之后的输出中,之前加入了一个Integer类型,所以出现//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。

那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常呢?答案就是使用泛型。

二.什么是泛型?

泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

 public class Test {
  
      public static void main(String[] args) {
 
         List<String> list = new ArrayList<String>();
         list.add("name");
         list.add("location");
         list.add(100);   //1
         for (int i = 0; i < list.size(); i++) {
             String name = list.get(i); // 2
             System.out.println("name:" + name);
         }
     }
 }

采用泛型写法后,在//1处想加入一个Integer类型的对象时会出现编译错误,通过List,直接限定了list集合中只能含有String类型的元素,此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。


三.自定义泛型接口、泛型类和泛型方法

自定义泛型类:

格式:

class 类名<字母列表>{

修饰符 字母 属性;

修饰符 构造器(字母){ }

修饰符 返回类型 方法(字母)

}
//不能使用在静态属性、静态方法上

eg:

public class Test {
		 public static void main(String[] args) {
		 B<String> b=new B<String>("ray2580");
		 System.out.println("name:" + b.get());
		 }	
}
class B<T>{
	 public T data;	
	 public B() {
		 
	}
	public  B(T data) {
		this.data = data;
	 }
	 public T get(){
		 return data;
	}
}

在泛型接口、泛型类和泛型方法的定义过程中,我们常见的如T、E、K、V等形式的参数常用于表示泛型形参。

泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。


自定义泛型方法:
定义使用:<字母>

修饰符<字母>返回类型 方法名(字母){ }

要定义泛型方法,将于泛型参数列表置返回值前。

public class Method {
    public static void main(String[] args){
        test("a");  //T----->String
    }
    
    //泛型方法
    public static <T> void test(T a){
        System.out.println(a);
    }
}

四.类型通配符

有时我们需要一个在逻辑上可以用来表示同时是Box和Box的父类的一个引用类型,由此,类型通配符应运而生。

类型通配符一般是使用 ? 代替具体的类型实参。且Box<?>在逻辑上是Box、Box…等所有Box<具体类型实参>的父类。

  public class Test {
 
      public static void main(String[] args) {
  
          Box<String> name = new Box<String>("ray2580");
          Box<Integer> age = new Box<Integer>(71);
          Box<Number> number = new Box<Number>(34);
  
          getData(name);
         getData(age);
         getData(number);
     }
 
     public static void getData(Box<?> data) {
         System.out.println("data :" + data.getData());
     }
 
 }

我们还需要类型通配符上限和类型通配符下限。具体有是怎么样的呢?

在上面的例子中,如果需要定义一个功能类似于get()的方法,但对类型实参又有进一步的限制:只能是Number类及其子类。此时,需要用到类型通配符上限。

  public class Test {
  
      public static void main(String[] args) {
  
          Box<String> name = new Box<String>("ray2580");
          Box<Integer> age = new Box<Integer>(712);
          Box<Number> number = new Box<Number>(314);
  
          getData(name);
         getData(age);
         getData(number);
         
         //getUpperNumberData(name); // 1
         getUpperNumberData(age);    // 2
         getUpperNumberData(number); // 3
     }
 
     public static void getData(Box<?> data) {
         System.out.println("data :" + data.getData());
     }
     
    public static void getUpperNumberData(Box<? extends Number> data){
         System.out.println("data :" + data.getData());
    }
 
 }

此时,显然,在代码//1处调用将出现错误提示,而//2 //3处调用正常。

类型通配符上限通过形如Box<? extends Number>形式定义,相对应的,类型通配符下限为Box<? super Number>形式,其含义与类型通配符上限正好相反。


泛型中的约束和局限性

1,不能实例化泛型类
2,静态变量或方法不能引用泛型类型变量,但是静态泛型方法是可以的
3,基本类型无法作为泛型类型
4,无法使用instanceof关键字或==判断泛型类的类型
5,泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的
6,泛型数组可以声明但无法实例化
7,泛型类不能继承Exception或者Throwable
8,不能捕获泛型类型限定的异常但可以将泛型限定的异常抛出
9,对于泛型参数是继承关系的泛型类之间是没有继承关系的
10,泛型类可以继承其它泛型类,例如: public class ArrayList extends AbstractList
11,泛型类的继承关系在使用中同样会受到泛型类型的影响

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值