欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java中的泛型(基础篇)

程序员文章站 2022-04-11 13:13:45
这里写目录标题什么是泛型泛型的分类通配符? *通配符上界通配符 < ? extends E>(4) 下界通配符 < ? super E>?和 T 的区别Class 和 Class的区别什么是泛型泛型的分类?表示不确定的 java 类型T (type) 表示具体的一个java类型K V (key value) 分别代表java键值中的Key ValueE (element) 代表Element通配符? *通配符上界通配符 < ? exte...

什么是泛型

泛型即参数化类型,是JDK1.5中引入的一个新特性。 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。换句话说,"泛型"这个术语的意思是:“适用于许多的类型”。
(出自 java编程思想)

1:泛型的使用

在我们平时开发或者查看源码的时候,我们会发现很多的代码都会用到泛型,比如我们常用到的ArratList,为什么它能够同时创建 String,Double等等很多的类型的集合那?如果我们点进源码就会发现,在源码中使用了泛型。接下来我们就来看看泛型到底有哪些吧!

1.1: 字母规范

在定义泛型类时,我们已经提到用于指定泛型的变量是一个大写字母,当然不是的!!!!任意一个大写字母都可以。他们的意义是完全相同的,但为了提高可读性,大家还是用有意义的字母比较好,一般来讲,在不同的情境下使用的字母意义如下:

  • E — Element,常用在java Collection里,如:
  • List,Iterator,Set
  • K,V — Key,Value,代表Map的键值对
  • N — Number,数字
  • T — Type,类型,如String,Integer等等

1.2:泛型接口

// 接口上定义泛型,此处可以随便写标识符号
public interface Things<T> {
    T getThing();
    // 作为返回值

    void setThing(T t);
    //作为参数
}

泛型接口的使用
非泛型类

public class Coding implements Things<String> {

    private String str;

    public Coding(String str) {
        this.str = str;
    }

    @Override
    public String getThing() {
        return this.str;
    }

    @Override
    public void setThing(String s) {

    }

    public static void main(String[] args) {
        Coding coding = new Coding("写代码!");
        System.out.println(coding.getThing());
    }

泛型类

public class Work<T> implements Things<T> {

    private T var;

    public Work(T var) {
        this.setThing(var);
    }

    @Override
    public T getThing() {
        return this.var;
    }

    @Override
    public void setThing(T var) {
        this.var = var ;
    }

    public static void main(String[] args) {
        Work<String> work=new Work<>("工作中!");
        System.out.println(work.getThing());
    }
}

1.3:泛型类

public class DoSome<T> {
    private T x;
    private T y;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }

    public static void main(String[] args) {
        DoSome<String> doSome =new DoSome();
        doSome.setX("123");
        System.out.println(doSome.getX());
        DoSome<Integer> doSome1 =new DoSome();
        doSome1.setX(new Integer(100));
        System.out.println(doSome1.getX());
    }

}

尖括号中,你传进去的是什么,T就代表什么类型。这就是泛型的最大作用,我们只需要考虑逻辑实现,就能拿给各种类来用。

1.4:泛型方法

public class FanxingMethodTest {

    public <T> void normalMethod(T t){
        System.out.println("normalMethod: "+t.toString());
    }
    public void method(String str){
        System.out.println("method:"+str.toString());
    }

    public static void main(String[] args) {
        FanxingMethodTest fanxingMethodTest=new FanxingMethodTest();
        fanxingMethodTest.normalMethod(123);
        fanxingMethodTest.normalMethod("字符串");
        fanxingMethodTest.method("123");
    }

}

2: 通配符

2.1: 通配符

非限定通配符

  形如<?>,表示通配符泛型值接受所有类型。

限定通配符上限

  <? extends T>表示该通配符所代表的类型是T类型及T类型的子类。

限定通配符下限

 形如<? super T>,表示通配符所代表的类型是T类型的父类,只能接收T及其三层父类类型。

2.2: ?和 T 的区别

T 代表一种类型 (具体的java类型)
?是通配符,泛指所有类型,一般用于定义一个引用变量,这么做的好处是,如定义一个引用变量,就可以指向多个对象。表示不确定的java类型
T和?运用的地方有点不同,?是定义在引用变量上,T是类上或方法上

  • ArrayList al=new ArrayList();指定集合元素只能是T类型
  • ArrayList<?> al=new ArrayList<?>();集合元素可以是任意类型,这种没有意义,一般是方法中,只是为了说明用法
  • ArrayList<? extends E> al=new ArrayList<? extends E>();
    泛型的限定:
    ? extends E:接收E类型或者E的子类型。
    ?super E:接收E类型或者E的父类型。

2.3: Object跟泛型类区别

Object是所有类的根类,是具体的一个类,使用的时候可能是需要类型强制转换的,但是用T ?等这些的话,在实际用之前类型就已经确定了,不需要强制转换。
追问:
也就是说,这个方法能知道返回的是哪种类型(父类),就用T行了?如果完全不知道的就用?用T的得到的对象就不需要类型转换了,而用?的就必需用强转了!
追答:
第一种是固定的一种泛型,第二种是只要是Object类的子类都可以,换言之,任何类都可以,因为Object是所有类的根基类
固定的泛型指类型是固定的,比如:Interge,String. 就是
<? extends Collection> 这里?代表一个未知的类型,
但是,这个未知的类型实际上是Collection的一个子类,Collection是这个通配符的上限.
举个例子: class Test { }
其中,限定了构造此类实例的时候T是一个确定类型(具体类型),这个类型实现了Collection接口,但是实现 Collection接口的类很多很多,如果针对每一种都要写出具体的子类类型,那也太麻烦了,干脆还不如用Object通用一下。<? extends Collection>其中,?是一个未知类型,是一个通配符泛型,这个类型是实现Collection接口即可。

3: 泛型使用的注意事项

泛型类型参数不能使用基本数据类型指定,基本数据类型要写成其包装类型。
例如使用new ArrayList()是不合法的。因为类型擦除后会替换成Object(如果通过extends设置了上限,则替换成上限类型),int显然无法替换成Object,所以泛型参数必须是引用类型。泛型类型参数是使用new对象时确定。若不指定泛型类型,则默认使用Object类型。在JDK1.7以后,指定泛型可以省略最后"<>"中的类型。

4: 使用泛型的优势

  • 减少了强制类型转换的操作
  • 在编译时期进行类型检查,避免了很多运行时期才能发现的错误

本文地址:https://blog.csdn.net/qq_42843770/article/details/107343288