工作中需要用到的Java知识(泛型篇)

在过去的一段时间中,虽然一直在工作,但是也进行过了几次面试,对于面试会询问的问题还是有一些心得的。其中JavaSE的内容会考很多,所以需要个人对于基础十分扎实。在工作中我们使用到泛型的时候并不多,但是基本每次面试都会有这部分的内容,所以今天也来学习一下Java中泛型的作用。

泛型是在Java1.5版本加入的,那么为什么需要有泛型呢?他是用来做什么的呢?

1.泛型的产生原因

在没有泛型之前,我们创建一个ArrayList集合的时候是这样的

集合中的数据都是Object类型的变量

有兴趣的同学可以执行一下如下代码,这里我就不执行了

ArrayList list = new ArrayList();
list.add("helloworld");
list.add(100);

for(Object o : list) {
    //假设我们需要打印集合中的元素,强转为字符串
    String str = (String) o
    System.out.println(str)
}

这段代码执行以后会报ClassCastException异常,也就是类型转换异常。

原因是数字类型不能转换为字符串类型。

 这时候就有问题了,当我们向集合中放入多种类型的元素的时候,就会需要每个元素都需要判断类型后才能进行使用,否则很容易出现类型转换异常。

//获取对象的数据类型
对象.getClass().getSimpleName()

所以在Java1.5提出了泛型,来提供编译时的安全监测,当我们编译代码时可以监测到非法的数据类型。

2.泛型的使用

// 集合后面用<类型>,确定集合所用的泛型,限定为字符串类型
ArrayList<String> list = new ArrayList<>();
list.add("helloworld");
list.add(100);//此时添加int类型值就会报错,需要删除此行
list.add("100");

for(String o : list) {
    // 此时我们循环打印集合数据,就没有问题了
    System.out.println(o)
}

如上图代码,泛型为我们在编写代码时就限定了集合类可放入的元素的类型,避免了工作中很多人用了一个集合,有可能大家放入的数据就出现了多种数据类型,导致运行的时候报错。

3.泛型类的创建

/**
  * 
  * T 泛型标识,代表形参 用于创建对象的时候指定具体的数据类型
  *
  */
public class 自定义类名<T> {

    private T name;

}

在这里穿插一个面试的问题,上面的泛型类我使用了T的泛型标识,那么其他的泛型标识还有E、T、K、V、N、?。

面试中有一个问题,就是这些泛型标识都代表什么意思,又或者说什么时候用哪个标识符呢?

泛型标识运用场景
EElement   表示元素,在集合中使用
TType    表示Java类
KKey    表示键,一般用于map集合
VValue    表示值,一般用于map集合
NNumber     表示数值类型
?表示不确定的java类型

我们创建了以后使用时需要像如下方式使用

// Java1.7以前,需要前后都写上类型
// 此方法说明这个类的泛型被确定为字符串类型
// 需要注意,泛型不支持基本数据类型,如int、long、boolean、double等
自定义类名<String> data = new 自定义类名<String>();

// 1.7以后可以省略后面的类型,被称为菱形语法
自定义类名<String> data = new 自定义类名<>();

// 如果没有限制泛型,则默认为Object类型
自定义类名 data = new 自定义类名();

4.泛型类的继承与实现

// 子类如果是泛型类,继承或实现泛型的父类时,需要与父类泛型标识一致
// 因为创建子类对象时,需要先创建父类对象,但如果泛型标识不一致,就无法判断父类的类型
// 子类的泛型标识可以放入多个,但是必须要有一个是父类的泛型标识
class child<T> extend parent<T>

class child<T> implements parent<T>

------------------------------------------------------------------------------

// 子类如果非泛型类,继承或实现泛型的父类时,需要确定父类的泛型数据类型
class child extend parent<String>

class child implements parent<String>

5.泛型方法的创建

public <泛型标识符> 返回值类型 方法名(方法参数) {
    方法体;
}

// 以泛型T为例的泛型方法
public <T> void test(T t) {
    方法体;
}

//可以使用 & 符号来说明T类为A,B的共同子类
//但是不能使用?通配符来说明,因为他不是一个确定的类型
public <T extends classA & classB> void test(T t){
    方法体;
}

// 泛型方法对可变参数的支持,加上...说明此类型的参数的个数是不确定的
public <T> void test(T... t) {
    方法体;
}

6.类型通配符

类型通配符一般是使用“?”来代替具体的类型实参。

当我们创建方法,需要传入泛型对象时,如果此时我们确定了具体的数据类型,那么就变得很局限。

1.泛型中的类型,不能通过多态来理解,泛型假定定义为String就必须传入String类型。

2.泛型中的类型不同,但是本质上都是同一类型,所以不可以通过泛型类型来重载方法。

此时就需要使用?来代表任意类型的具体类型实参

// 如下为类型通配符的用法,获取的对象为Object类型
public void test(ArrayList<?> list) {
    Object data0 = list.get(0)
}

// 我们可以通过extends关键字来限定类型通配符的 上限
// 来缩小类型通配符可放入的类型种类
// 限定后限制只能放入此类型或此类型的 子类
public void test(ArrayList<? extends String> list) {
    String data0 = list.get(0)
}

// 我们可以通过extends关键字来限定类型通配符的 下限
// 来缩小类型通配符可放入的类型种类
// 限定后限制只能放入此类型或此类型的 父类
public void test(ArrayList<? super String> list) {
    String data0 = list.get(0)
}

7.T与?的区别

T用来声明泛型类与方法;?用来使用泛型类与泛型方法。

T不能确定下限,?可以用super关键字来确定下限。

T可以用来确定类型的一致性,?由于是不确定的类型,所以不可以用来确定类型的一致性。

T可以使用&来多重确定上限,但是?不能多重确定上限。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值