Java——泛型(最易懂的方式阐述泛型)

原创 2016年06月02日 21:08:02

来自:
代码大湿
代码大湿

写在前面:

只要认真看过,基本能很熟悉泛型的特性。泛型是JDK1.5之后出现的,比如JDK1.5之前,但是会出现2个问题

1:向ArrayList当中添加对象,添加String和Date都可以,但我们的本意是添加String,编译器不会检查错误,会导致不可预知的错误。

2:get()方法得到一个元素的时候要进行强制类型转换。
所以泛型的引入很好的解决了这2个问题。


1,泛型类

一个泛型类如下;


class Pair<T,E>{
    private T first;
    private E second;
    public T getFirst() {
        return first;
    }
    public void setFirst(T first) {
        this.first = first;
    }
    public E getSecond() {
        return second;
    }
    public void setSecond(E second) {
        this.second = second;
    }

}

尖括号中的T,E称为类型变量。


2. 泛型方法

一个泛型方法的签名:
public static T getV(T t)
类型变量在方法修饰符的后面,返回值的前面。


3.类型擦除

JVM中是不存在泛型这一说法的,即编译器在编译的时候,将类型变量擦除掉了,换成了Bounding Type。上面的Pair类在编译后,Pair变成这样了:

class Pair{
    private Object first;
    private Object second;
    public Object getFirst() {
        return first;
    }
    public void setFirst(Object first) {
        this.first = first;
    }
    public Object getSecond() {
        return second;
    }
    public void setSecond(Object second) {
        this.second = second;
    }

}

将类型变量替代成了Object。更多的类型替代请继续往下阅读;

类型擦除带来的问题:
定义一个Pair的子类

class extendsPair extends Pair<Date,Date>{
    public void setSecond(Date d){
        super.setSecond(d);
        System.out.println("我是字类的方法");
    }
}

Pair pair=new extendsPair();
        pair.setSecond(new Date());

执行结果是:
我是父类的方法
我是字类的方法

为什么会是这样呢?

因为子类自己定义了一个public void setSecond(Date d)
但是从父类继承了一个方法是public void setSecond(Object d),这是2个不同的方法。当用父类的引用指向子类的实例,然后调用词方法,对于编译器只会寻找父类的那个方法即public void setSecond(Object d)。而程序员的意图是调用子类的方法public void setSecond(Date d),所以此种情况,编译器会为我们生成一个桥方法
public void setSecond(Object d){
setSecond((Date)d);
}

所以正如结果中那样,先调用父类的setSecond方法,然后在此方法中调用子类的setSecond方法。


4.类型限定符

1.类型限定符,用关键字extends表示子类型限定

对于下面方法

public People getName(Pair<People,People> p){
        return p.getFirst();
    }

这个方法,我们无法传入Pair<Student,Studnet>类型的参数,此时我们就要用到子类型限定,将此方法改为:

public People getName(Pair<? extends People,? extends People> p){
        return p.getFirst();
    }

用关键字super表示超类型限定,<?>表示无类型限定。比如一个方法getPairs()我们要返回Pair<>[]。其中的元素有Pair<Student>,还有Pair<Scientist>Student和Scientist不存在继承关系。这是就只能用<?>

2:类型限定注意事项:

看下面代码

public People getName(Pair<? extends People,? extends People> p){
        Student student=new Student();
        p.setFirst(student);
        return p.getFirst();
    }

p.setFirst(student)会报错,因为Pair

public void setFirst(<? extends People first) {
        this.first = first;
    }

形参是People的某子类,但是编译器不能确定Student是不是这个子类的子类。但是对于get方法,总能将返回类型转型成People类。相应的使用超类型限定,get()方法会报错。


5:泛型的注意事项:

1:不能在泛型类的静态上下文中定义含有类型变量的静态成员,如:
class Pair<T,E>{
    private static T name;
    ....

只是对于泛型类来说,如上面普通类中可以存在静态方法。这个原因很简单,比如Pair<String,String>和Pair<Date,Date>这2个对象,那么这两个对象要共享name,那么变量name是什么类型呢?存在冲突。


2:泛型类不能继承异常类,也不能被抛出

因为泛型类不能继承Throwable,但是类型变量可以被抛出,如:

public static <T extends Throwable> T get(T t) throws T{
        return t;
    }

3:泛型数组是不合法的

不能创建这样的数组:

Pair<String,String>[] pairs=new Pair<String,String>[10];

因为实际上paris是Pair[]类型的,所以我们添加Date类型的元素,编译器是不会发现的。这会产生难以定位的错误。但是我们可以用下面的方式来定义泛型数组。

Pair<String,String>[] pairs=(Pair<String, String>[])(new Pair[10]);
4:不能实例化类型变量

不能出现 new T(),new T[]这样的src。因为经过类型擦除后,T均变为BoundingType。这样的操作没有意义。

5:类型变量不能是raw类型。 

关注更多好文:
代码大湿
代码大湿

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Java——泛型(最易懂的方式阐述泛型)

来自: 代码大湿 代码大湿写在前面:只要认真看过,基本能很熟悉泛型的特性。泛型是JDK1.5之后出现的,比如JDK1.5之前,但是会出现2个问题1:向ArrayList当中添加对象...

通俗易懂谈泛型

泛型非常有用,笑言之:『泛泛而谈』的类型,意思就是这个类型是一个不确定的类型,只有具体实现的时候才确定是什么类型。 有一种东西,可以是很多种类型都通用的,但只有使用的时候才确定这个到底是什么具体的...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

Java泛型

Java泛型详解,泛型的作用,泛型方法、泛型类的定义,泛型通配符

泛型之通俗易懂

看不少文章都没有弄得这个泛型到底是做什么的,怎么用?下面这篇文章就用最通俗的话来介绍...一看就明白规则和限制:       1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。   2、...

Java基础学习之泛型(泛型方法、泛型类、通配符的使用)

Java的泛型是在JDK5.0之后引入的新特性,泛型只是在程序编译期对代码的安全防范机制,这种机制是为了方便程序员在编写代码时快速有效的检查代码中的非法类型。1、集合的泛型在Java学习初期,我们最早...

泛型——泛型方法

最初学习泛型方法时,想到一个可以使用泛型方法的

【7】Java泛型:泛型类、泛型接口、泛型方法

根据《Java编程思想 (第4版)》中的描述,泛型出现的动机在于: 有许多原因促成了泛型的出现,而最引人注意的一个原因,就是为了创建容器类。一、泛型类容器类应该算得上最具重用性的类库之一。先来看一个...

Java泛型:泛型类、泛型接口和泛型方法

容器类应该算得上最具重用性的类库之一。 先来看一个没有泛型的情况下的容器类如何定义: 1、泛型类 public class Container { private String key; ...

Java 泛型简述

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定...

Java基础之我见——泛型

泛型,英文名为Generic Type或Generics,类型可变的意思。在Java SE1.5版本之前,Java世界中没有泛型概念,要使类型可变,一般都通过类型强转来实现。我分别用泛型和非泛型的方式...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)