JDK5泛型和可变参数

JDK5泛型和可变参数

泛型和可变参数在我们学习类,集合时是必不可缺的,我们可以通过泛型和可变参数简化编译代码以便于更好地达到目的

泛型概述

泛型:

  • JDK5引入的特性,提供了编译时类型安全检测机制,该机制允许在变成时检测到非法的类型;
  • 它的本质是参数化类型,操作数的数据类型被指定为一个参数
  • 将类型由原本的具体的类型参数化,然后在使用和调用时传入具体的 类型

泛型定义格式:

  • <类型>:指定一种类型的格式;这里的类型可以看成形参
  • <类型1,类型2...>:指定多种类型的格式,多种类型之间用逗号隔开
  • 将来具体调用的时候给的类型可以看作实参,并且实参的类型只能是引用数据类型

泛型的好处:

  • 把运行时期的问题提前到了编译期间
  • 避免了强制类型转换

下面给出代码实例:

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;


public class Demo1 {
    public static void main(String[] args) {
        //泛型就是集合后面的<>,你可以在里面提前标记集合的类型,防止编译后报错,可以将报错信息提前至编译时

        //这里没有使用泛型,在后续add中,你可以添加int,double类型但编译器不提示,直到你运行时产生报错
        Collection c = new HashSet();
        //这里使用泛型,在后续add中,你无法可以添加除String以外的类型,若添加后编译器报错
        Collection<String> cc =new HashSet<>();

        //包括迭代器Iterator也有泛型
        //这里没有使用泛型,在后续的赋值中,你需要采用强制转换(int)it.next()才能赋值或使用;
        Iterator<String> it = c.iterator();
        //这里使用泛型,在后续的赋值中,你不需要采用强制转换(int)it.next()赋值就可以直接使用
        Iterator<String> itt = cc.iterator();
    }

}

泛型类

泛型类的定义格式:

//模板:
修饰符 class 类名<类型>{
    
}

下面给出泛型类和应用泛型类的实例:

public class Demo2 {
    public static void main(String[] args) {
        //这里首先用String作为T
        testClass1<String> tc = new testClass1<String >();
        tc.setT("Jorry");
        tc.printT();

        //这里使用int作为T
        testClass1<Integer> tcc = new testClass1<Integer>();
        tcc.setT(10);
        tcc.printT();
    }
}
//在这里设置T作为泛型,整个类变成泛型类
public class testClass1<T> {
    //内部定义时,T作为一种数据类型来使用
    public T t;

    public void setT(T t){
        this.t = t;
    }

    public void printT(){
        System.out.println(t);
    }
}

编译结果:

Jorry
10

我们可以看到,我们在类上定义的T后来在main中直接赋值并使用

泛型方法

泛型方法的定义格式:

public class 类名 {
    //泛型方法:
    public<T> void 方法名(T t){
        ......
    }
}

下面给出泛型方法和应用泛型方法的实例:

public class Demo1 {
    public static void main(String[] args) {
        Demo2 d = new Demo2();
        d.show("s");
        d.show(10);
    }
}
public class Demo2 {
    //泛型方法:
    public<T> void show(T t){
        System.out.println(t);
    }
}

编译结果:

s
10

我们可以看到,通过一个方法就可以输出各种类型的数值

泛型接口

泛型接口的定义格式:

public interface Demo3<T> {
    void show(T t);
}

泛型接口需要由泛型类来继承才可使用:

public class Demo2<T> implements Demo3<T>{
    public void show(T t){
        ......
    }
}

下面给出泛型接口和应用泛型接口的实例:

public class Demo1 {
    public static void main(String[] args) {
        Demo2 d = new Demo2();
        d.show(10);
        d.show("Jorry");
    }
}
public class Demo2<T> implements Demo3<T>{

    public void show(T t){
        System.out.println(t);
    }

}
public interface Demo3<T> {
    void show(T t);
}

编译结果:

10
Jorry

我们通过泛型接口定义方法头,在泛型类中重写方法,最后在main中使用

类型通配符

为了表示各种泛型List的父类,可以采用类型通配符:

  • 类型通配符:<?>
  • List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
  • 这种带通配符的List仅表示各种泛型List的父类,并不能把元素添加其中

如果我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限:

  • 类型通配符上限:<? extends 类型>
  • List<? extends Number>:它表示的类型是Number或子类

除了指定类型通配符的上限还可以指定下限:

  • 类型通配符下限:<? super 类型>
  • List<? super Number>:他表示的类型是Number或父类

下面给出类型通配符的代码解释:

import java.util.ArrayList;
import java.util.List;

public class Demo1 {

    public static void main(String[] args) {
        //正常类型通配符
        List<?> l1 = new ArrayList<Object>();
        List<?> l2 = new ArrayList<Number>();
        List<?> l3 = new ArrayList<Integer>();

        //上限类型通配符
        List<? extends Number> l4 = new ArrayList<Integer>();//这里上限是Number,所以Object不能用

        //下限类型通配符
        List<? super Number> l5 = new ArrayList<Object>();//这里下限是Number,所以Integer不能用
    }
}

可变参数

可变参数又称参数个数可变,用作方法的形参出现,那么方法参数的个数就是可变的了

格式:

修饰符 返回值类型 方法名(其他类型 类型名,数据类型... 变量名){
    
}

下面给出实例:

public class Demo1 {
    
    public static void main(String[] args) {
        //调用sum方法
        sum(10,20);
        sum(10,20,30,50);

    }
    
    //书写sum可变参数方法(a实际上是数组)
    public static void sum(int... a){
        int sum=0;
        for (int i : a){
            sum += i;
        }
        System.out.println(sum);
    }
}

结束语

好的,关于泛型和可变参数的话题就到这里

posted @ 2022-07-06 15:28  秋落雨微凉  阅读(42)  评论(0编辑  收藏  举报