Java泛型知识点总结

Java泛型知识点总结

一、为什么要使用泛型

同一段代码,可以被很对不同类型的对象所重用,但我们并不希望为两个不同的对象设计不同的代码块。以ArrayList为例,AraryList可以存储任何类型的对象,JDK会为每一种类型都写一个ArrayList类吗??显然不可能。
那Java语言如何解决这个问题呢?在JavaSe 5.0之前,ArrayList类维护一个Object类的数组,如下

public class ArrayList{
	private Object [] elementDate;
	public Object get(int i){...}
	//在一个Object类型的数组下进行操作
	public void add(Object o){...}
	...
}

这样实现有个问题,当获取一个值时必须进行强制类型转换

ArrayList files = new ArrayList();
String str = (String)files.get(2);

对于这个强转,编译不会报错,但运行时会出现转换异常:java.lang.ClassCastException,这给程序员带来很大困扰。所以在Java5之后,从 Java 5 之后,Java 引入了参数化类型parameterized type的概念。ArrayList类有一个类型参数指示元素类型。

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

这使得代码大大提高可读性,让人们一眼就看出来操作的是String类型的对象。
借助泛型,可以事先指定 List 中的元素类型,这样编译器在编译阶段就能够发现问题。如下图
在这里插入图片描述

二、泛型实例

1、泛型类

1.1泛型类的定义语法

class 类名称<泛型标识>{
    private 泛型标识 成员变量名;
    ……
}

泛型标识

可以随意指定,尽量使用单个大写英文字母。
但尽量做到见名知意,常用有以下几个:
T:type
E:Element
K:key
V:value
1.2 泛型类实例演示

public class Generic<T> {
    private T key;

    public Generic(T key) {
        this.key = key;
    }

    public T getKey() {
        return key;
    }

    public static void main(String[] args) {
    //注意:泛型的类型参数只能是类类型(包括自定义类),不能是基本数据类型。
        Generic<Integer> generic = new Generic<>(10);
        Integer value = generic.getKey();
        System.out.println(value);
        //传入的实参类型也要和泛型的类型参数相同。即String类型
        Generic<String > generic1 = new Generic<>("我爱Java");
        String str = generic1.getKey();
        System.out.println(str);
    }
}

思考:定义了泛型类就一定要传入泛型类型参数吗?
并不是这样,如果不传入泛型类型参数,在泛型类中使用泛型的方法或成员变量定义的类型可以是任何类型,例如:
ArrayList list = new ArrayList();
等价于:ArrayList<Object> List = new ArrayList<>();

1.3泛型类的注意事项
●对类型进行自动检查注意:不是替换仅仅是在编译期用来进行类型安全检查! !! ! ! !
●自动对类型进行类型转换
●泛型的类型参数只能是引用数据类型,不能是基本数据类型。
●不能对确切的泛型类型使用instanceof操作。
●不能直接new泛型数组。
●不能产生泛型类型对象。
●在static方法中,是不能用泛型类型参数的。因为static方法是不依赖对象存佐的,所以无法排知static泛型参数类型。

2、泛型接口

泛型接口的定义和实例演示

public interface Generator<T>{
	T next();
}
 、、、
 class FruitGenerator<E> implements Generator<E>{
 	@Override
 	public E next(){
 		return null;
 	}

接口实现类定义时,也需要将泛型的声明加上。如果不加,例如public class FruitGenerator implements Generaotr<T>,这样就会报错,cannot resolve symbol T

//泛型接口实现类,传入泛型实参,比如 String
public class FruitGenerator implements Generaotr<String> {

此时,接口实行类就不用加上泛型声明了,加入的话,反而会提示 attempting to use incompatible return type错误。

3、泛型方法

我们在此之前看到的泛型都是应用在整个类上,但方法同样可以包含参数化方法,而这个方法所在的类可以是泛型类也可以不是泛型类。也就是说,是否拥有泛型方法与其所处的类是否是泛型类毫无关系。方法中,通过指定类型参数,可以声明泛型方法,从而提高其可复用性。泛型方法的参数化类型列表放在方法类符的后面返回值之前。

修饰符 <T,S,...> 返回值类型 方法名(形参列表){
    // 方法体
}
public genericTest{
//只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
//<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
	public <T> String genericMethod(Class<T> gClass){
		return gClass.getName();
	}
	public static void main(String[] args) {
		String result = genericMethod(String.class);
		System.out.println(result);
	}
}

注意:
如果泛型方法的泛型参数与类的泛型参数相同,编译器会发生警告。

public class Generic<T> {//泛型类
    public <T> void show(){//泛型方法。此时会在<T>处发出警告。
        System.out.println("你好");
    }

三、类型擦除

定义:Java的泛型是伪泛型,为什么称为伪泛型呢?因为在编译期间,所有的泛型信息都会被擦除掉。Java 中的泛型基本上都是在编译期这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。

import java.util.ArrayList;
public class TestDemo{
	public static void main(String[] args) {
		ArrayList< String> arrayList1=new ArrayList<String> ();
		arrayList1.add("abc");
		ArrayList < Integer> arrayList2=new ArrayList< Integer> ();
		arrayList2.add(123);
		System.out.printIn(arrayList1.getClass()== arrayList2.getClass();
	}
}

我们通过arrayList1 对象和arrayList2对象的getClass方法获取
它们的类的信息,最后发现结果为true。
说明泛型类型String和Integer都被擦除掉了,只剩下了原
始类型(Object类型)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值