专业的JAVA编程教程与资源

网站首页 > java教程 正文

关于Java中的泛型使用你不知道的那些事?

temp10 2024-10-16 15:56:40 java教程 13 ℃ 0 评论

泛型应用值传递的问题?

在Java开发中像是如下的两种操作方式是不被允许的

public static void main(String[] args) {
    //会出现编译错误
    ArrayList<String> arrayList1 = new ArrayList<Object>();
    //会出现编译错误
    ArrayList<Object> arrayList2 = new ArrayList<String>();
}

首先来分析一下第一种情况

关于Java中的泛型使用你不知道的那些事?

public static void main(String[] args) {
    ArrayList<Object> objectArrayList = new ArrayList<Object>();
    objectArrayList.add(new Object());
    objectArrayList.add(new Object());
    //会出现编译错误
    ArrayList<String> arrayList1 = objectArrayList;
}

定义了一个Object的数组,然后添加两个Object对象之后将其赋值给了一个String类型的数组,这个时候编译会报错。这是为什么?

假设编译没有保存,当我们使用get方法获取数组对象的时候那么应该返回的是String类型的对象,但是在上面的代码中objectArrayList数组放入的是Object类型的对象,这样就会出现类型不配的异常。在Java中是不允许这样的操作的。

第二种情况可以写成如下的这种方式

public static void main(String[] args) {
    ArrayList<String> stringArrayList = new ArrayList<String>();
    stringArrayList.add(new String());
    stringArrayList.add(new String());
    //会出现编译错误
    ArrayList<Object> arrayList1 = stringArrayList;
}

假设编译不会报错,那么在进行类型转换的时候,就是将String类型转换成了Object,我们也知道Object是Java中所有对象的父类,应该没啥问题?但是这样做的意义是什么呢?不如全部的对象都用Object代替好了。何必要转一圈回来还是使用Object代替呢?

所以在Java中为了避免这种情况的出现,在编译时候就对以上操作进行提示。

泛型变量不能是基本数据类型?

例如如下的操作在Java中是不允许的。

ArrayList<int> stringArrayList = new ArrayList<int>();

因为在进行类型擦除之后,ArrayList中的具体的对象会被替换为Object,但是对于基本数据类型来讲,它不是对象,所以需要使用它对应的引用类型来进行设置。

ArrayList<Integer> stringArrayList = new ArrayList<Integer>();

在静态方法和静态类中使用泛型?

在静态类或者静态方法中是不可以使用泛型类去声明泛型的参数,如下所示。

public class Test<T> {
    public static T one;
    public static T print(T one){
        return null;
    }
}

因为在泛型类中对于泛型的实例化是在定义的时候指定的,而对于静态变量或者是静态方法来讲,它是可以直接通过类类名进行调用的,所以不需要具体的对象,这个时候就会出现对象还没有确定,如何能够判断泛型类型是什么呢?所以就会编译报错。

如果将其泛型操作改成如下这种则是可以的。

public class Test<T> {
    public static <T> T print(T one){
        return null;
    }
}

这是因为该方法是一个泛型的方法,在泛型方法中使用的T是自己在方法中定义的,而不是在泛型中的T。这个需要读者自己理解一下。

泛型相关面试题

1、Java中的泛型是什么?使用泛型的好处是什么?

泛型是泛化参数的类型机制,可以使得代码适用于各种数据类型,从编码的角度来讲,可以使得代码更加通用,例如在Java中的集合类型都是使用泛型。

泛型操作是一种在编译的时候进行类型确定的机制,它提供的机制是在编译时的类型安全,也就是说保证了泛型在编译的时候使用到正确的类型,避免出现在使用的时候出现类型不匹配的问题。

2、泛型是如何工作的?什么是类型擦除?

上面也提到了,泛型的正常执行是依赖在编译的时候对类型进行了检查,这样在进行类型擦除之后可以通过强制类型转换来进行相关的操作。

在编译的时候会擦除所有的类型相关的信息,所以在运行的时候不会存在任何的类型相关信息,例如List<String>在完成类型擦除之后只会存在一个List,至于List中的内容就是根据具体实际使用来决定了。

为什么要进行类型擦除?是为了防止类型膨胀。

3、什么是限定性通配符?什么是非限定性通配符?

在使用泛型的时候限定性的通配符是对类型进行进行了限定,有如下两种

  • <? extends T> 通过这种方式来确保参数必须是T的子类型。
  • <? super T> 通过这种方式来限定参数类型必须是T的父类型。

上面两种方式一种限定了上界,一种限定了下界。在进行泛型设置的时候必须采用指定的类型来进行初始化,否则就会编译错误。

而<?>就表示非限定性通配符,也就是说它可以用任意类型来代替。

4、List<Object>、List<String>和原始的List之间有什么区别?

主要的区别就是对于参数类型安全性的检查,如果带了参数则会对参数类型进行检查,如果使用的是Object则会接受任意类型的参数。主要是大家要理解原始类型与泛型的区别。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表