美文网首页
1、java 中的泛型

1、java 中的泛型

作者: 我要离开浪浪山 | 来源:发表于2021-07-30 00:48 被阅读0次

1、为什么要学泛型?

通过两段代码我们就可以知道为何我们需要泛型

图片.png

实际开发中,经常有数值类型求和的需求,例如实现int类型的加法, 有时候还需要实现long类型的求和, 如果还需要double类型的求和,需要重新在重载一个输入是double类型的add方法。

2、泛型类:

注意:泛型一定要加<T>

public class NormalGeneric<T> {
    private T data;

    public NormalGeneric() {
    }

    public NormalGeneric(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static void main(String[] args) {
        NormalGeneric<String> normalGeneric = new NormalGeneric<>();
        normalGeneric.setData("OK");
        //normalGeneric.setData(1);
        System.out.println(normalGeneric.getData());
        NormalGeneric normalGeneric1 = new NormalGeneric();
        normalGeneric1.setData(1);
        normalGeneric1.setData("dsf");
    }
}

3、泛型接口:

//泛型接口
public interface Genertor<T> {
    public T next();
}
//泛型接口实现泛型接口
public class ImplGenertor<T> implements Genertor<T> {
    @Override
    public T next() {
        return null;
    }
}
//泛型接口最终实现
public class ImplGenertor2 implements Genertor<String> {
    @Override
    public String next() {
        return null;
    }
}

4、泛型方法:

//普通类中的泛型方法
public class GenericMethod {

    public <T> T genericMethod(T...a){
        return a[a.length/2];
    }

    public void test(int x,int y){
        System.out.println(x+y);
    }

    public static void main(String[] args) {
        GenericMethod genericMethod = new GenericMethod();
        genericMethod.test(23,343);
        System.out.println(genericMethod.<String>genericMethod("mark","av","lance"));
        System.out.println(genericMethod.genericMethod(12,34));
    }
}
//泛型类里的泛型方法
public class GenericMethod2 {
    //这个类是个泛型类,在上面已经介绍过
    public class Generic<T>{
        private T key;

        public Generic(T key) {
            this.key = key;
        }

        //虽然在方法中使用了泛型,但是这并不是一个泛型方法。
        //这只是类中一个普通的成员方法,只不过他的返回值是在声明泛型类已经声明过的泛型。
        //所以在这个方法中才可以继续使用 T 这个泛型。
        public T getKey(){
            return key;
        }

        /**
         * 这个方法显然是有问题的,在编译器会给我们提示这样的错误信息"cannot reslove symbol E"
         * 因为在类的声明中并未声明泛型E,所以在使用E做形参和返回值类型时,编译器会无法识别。
         */
//        public E setKey(E key){
//            this.key = key;
//        }
    }

    /**
     * 这才是一个真正的泛型方法。
     * 首先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且声明了一个泛型T
     * 这个T可以出现在这个泛型方法的任意位置.
     * 泛型的数量也可以为任意多个
     *    如:public <T,K> K showKeyName(Generic<T> container){
     *        ...
     *        }
     */


    //这也不是一个泛型方法,这就是一个普通的方法,
    // 只是使用了Generic<Number>这个泛型类做形参而已。
    public void show(Generic<Number> obj){

    }

    /**
     * 这个方法是有问题的,编译器会为我们提示错误信息:"UnKnown class 'E' "
     * 虽然我们声明了<T>,也表明了这是一个可以处理泛型的类型的泛型方法。
     * 但是只声明了泛型类型T,并未声明泛型类型E,因此编译器并不知道该如何处理E这个类型。
     */
//    public <T,E> T show(E ab){
//        //
//    }

    /**
     * 这个方法也是有问题的,编译器会为我们提示错误信息:"UnKnown class 'T' "
     * 对于编译器来说T这个类型并未项目中声明过,因此编译也不知道该如何编译这个类。
     * 所以这也不是一个正确的泛型方法声明。
     }
     */
//    public void show(T obj){
//
//    }

    public static void main(String[] args) {


    }
}

//泛型使用
public class GenericMethod3 {
    static class Fruit{
        @Override
        public String toString() {
            return "fruit";
        }
    }

    static class Apple extends Fruit{
        @Override
        public String toString() {
            return "apple";
        }
    }

    static class Person{
        @Override
        public String toString() {
            return "Person";
        }
    }

    static class GenerateTest<T>{
        //普通方法
        public void show_1(T t){
            System.out.println(t.toString());
        }

        //在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型。
        // 可以类型与T相同,也可以不同。
        //由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,
        // 编译器也能够正确识别泛型方法中识别的泛型。
        public <E> void show_3(E t){
            System.out.println(t.toString());
        }

        //在泛型类中声明了一个泛型方法,使用泛型T,
        // 注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。
        public <T> void show_2(T t){
            System.out.println(t.toString());
        }
    }

    public static void main(String[] args) {
        Apple apple = new Apple();
        Person person = new Person();

        GenerateTest<Fruit> generateTest = new GenerateTest<>();
        generateTest.show_1(apple);
        //generateTest.show_1(person);

        generateTest.show_2(apple);
        generateTest.show_2(person);

        generateTest.show_3(apple);
        generateTest.show_3(person);
    }
}

5、限定类型变量

1、extends:类型变量的限定-方法上

//T extends ArrayList&Comparable,继承的类只能有一个,可以多个接口,使用&连接符。
public class ArrayAlg {
//    public static <T> T min(T a,T b){
//        if(a.comapareTo(b)>0) return a; else return b;
//    }

    public static <T extends ArrayList&Comparable> T min(T a, T b){
        if(a.compareTo(b)>0) return a; else return b;
    }
    static class Test{}
    public static void main(String[] args) {
        //ArrayAlg.min(new Test(),new Test());


    }
}

2、类型变量的限定-类上

//泛型类中使用 extends 也是一样的
public class ClassBorder<T extends Comparable> {
    private T data;

    public T min(T outter){
        if(this.data.compareTo(outter)>0)
            return outter;
        else
            return this.data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static void main(String[] args) {
        ClassBorder<String> classBorder = new ClassBorder<>();
        classBorder.setData("mark");
        System.out.println(classBorder.min("av"));
    }
}

6、泛型的约束和局限性

1、不能实例化类型变量;
2、静态域或者方法里不能引用类型变量;
3、静态方法 本身是泛型方法就行;
4、所有的基础类型,必须是包装类才行;
5、泛型不支持instanceof使用;
6、可以定义数组,不能使用数组;
7、泛型类不能 extends Exception/Throwable;
8、不能捕获泛型类对象;

public class Restrict<T> {
    private T data;

    //不能实例化类型变量
//    public Restrict() {
//        this.data = new T();
//    }
    //静态域或者方法里不能引用类型变量
    //private static T instance;
    //静态方法 本身是泛型方法就行
    //private static <T> T getInstance(){}


    public static void main(String[] args) {
        //Restrict<double>
        Restrict<Double> restrict = new Restrict<>();

//        if(restrict instanceof  Restrict<Double>)
//        if(restrict instanceof  Restrict<T>)

        Restrict<String> restrictString= new Restrict<>();

    //返回为 true,不管你传入什么类型,它都是 Restrict类型   System.out.println(restrict.getClass()==restrictString.getClass());
        System.out.println(restrict.getClass().getName());
        System.out.println(restrictString.getClass().getName());
        Restrict<Double>[] restrictArray;
        //Restrict<Double>[] restricts = new Restrict<Double>[10];
        //ArrayList<String>[] list1 = new ArrayList<String>[10];
        //ArrayList<String>[] list2 = new ArrayList[10];

    }
}
public class ExceptionRestrict {

    /*泛型类不能extends Exception/Throwable*/
    //private class Problem<T> extends Exception;

    /*不能捕获泛型类对象*/
//    public <T extends Throwable> void doWork(T x){
//        try{
//
//        }catch(T x){
//            //do sth;
//        }
//    }


    public <T extends Throwable> void doWorkSuccess(T x) throws T{
        try{

        }catch(Throwable e){
            throw x;
        }
    }
}

6、泛型类型的继承规则

1、Pair<Employee>和Pair<Worker>没有任何继承关系

public class Employee {
    private String firstName;
    private String secondName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getSecondName() {
        return secondName;
    }

    public void setSecondName(String secondName) {
        this.secondName = secondName;
    }
}
public class Worker extends Employee {
}
public class Pair<T> {
    private T one;
    private T two;

    public T getOne() {
        return one;
    }

    public void setOne(T one) {
        this.one = one;
    }

    public T getTwo() {
        return two;
    }

    public void setTwo(T two) {
        this.two = two;
    }

    private static <T> void set(Pair<Employee> p){
    }

    public static void main(String[] args) {
        //Pair<Employee>和Pair<Worker>没有任何继承关系
        Pair<Employee> employeePair = new Pair<>();
        Pair<Worker> workerPair = new Pair<>();

        Employee employee = new Worker();
        //Pair<Employee> employeePair2 = new Pair<Worker>();


        Pair<Employee> pair = new ExtendPair<>();


        set(employeePair);
        //不可以,通配符可以
        //set(workerPair);
    }

    /*泛型类可以继承或者扩展其他泛型类,比如List和ArrayList*/
    private static class ExtendPair<T> extends Pair<T>{

    }
}

7、通配符类型

1、?extends Object:只能传入它自己和它的子类,限定你的上界;
2、?super Object:只能传入它自己和它的父类,限定你的下界;

//关系:Food 是父类;Fruit extends Food
// HongFuShi extends  Apple;  Apple extends  Fruit
// Orange extends  Fruit
public class WildChar{

    public static void print(GenericType<Fruit> p){
        System.out.println(p.getData().getColor());
    }

    public static void use(){
       GenericType<Fruit> a = new GenericType<>();
        print(a);
       GenericType<Orange> b = new GenericType<>();
        //print(b);
    }


    public static void print2(GenericType<? extends Fruit> p){
        System.out.println(p.getData().getColor());
    }

    public static void use2(){
        GenericType<Fruit> a = new GenericType<>();
        print2(a);
        GenericType<Orange> b = new GenericType<>();
        print2(b);
        //print2(new GenericType<Food>());
        GenericType<? extends Fruit> c =  new GenericType<>();

        Apple apple =  new Apple();
        Fruit fruit = new Fruit();
        //c.setData(apple);
        //c.setData(fruit);
        Fruit x = c.getData();
    }

    public static void printSuper(GenericType<? super Apple> p){
        System.out.println(p.getData());
    }

    public static void useSuper(){
        GenericType<Fruit> fruitGenericType = new GenericType<>();
        GenericType<Apple> appleGenericType = new GenericType<>();
        GenericType<HongFuShi> hongFuShiGenericType = new GenericType<>();
        GenericType<Orange> orangeGenericType = new GenericType<>();
        printSuper(fruitGenericType);
        printSuper(appleGenericType);
//        printSuper(hongFuShiGenericType);
//        printSuper(orangeGenericType);


        //表示GenericType的类型参数的下界是Apple
        GenericType<? super Apple> x = new GenericType<>();
        x.setData(new Apple());
        x.setData(new HongFuShi());
        //x.setData(new Fruit());
        Object data = x.getData();

    }

}

8、Java 虚拟机如何使用泛型:

1、泛型擦除:
注意:类型擦除之后,类型是一样的。

public class Conflict {

    public static String method(List<String> stringList){
        System.out.println("List");
        return "OK";
    }

//    public static Integer method(List<Integer> stringList){
//        System.out.println("List");
//        return 1;
//    }

    /*
    * Signature (弱记忆)
    *
    * ? super xxxx
    *
    * */
}

相关文章

  • Android 开发也要掌握的Java知识 - Java泛型

    如果需要看泛型擦除Java泛型擦除 1.Java泛型有什么用?为啥要使用泛型? Java中数组的类型是定义的时候就...

  • java 泛型解析

    Java 泛型 1、泛型的精髓是什么 2、泛型方法如何使用 概述: 泛型在java中具有重要地位,在面向对象编程模...

  • 泛型(一)

    1. Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化...

  • 赢在面试之Java泛型篇

    1、Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化类...

  • Java泛型面试题

    1.Java中的泛型是什么 ? 使用泛型的好处是什么?以及各个版本有何区别? 答:泛型是 Java SE 1.5 ...

  • 泛型常见的面试题

    1. Java中的泛型是什么 ? 使用泛型的好处是什么? 这是在各种Java泛型面试中,一开场你就会被问到的问题中...

  • JAVA泛型的理解

    泛型大家都接触的不少,但是由于Java历史原因,Java中泛型一直被称为伪泛型,因此对Java中的泛型,有很多不注...

  • Kotlin泛型的高级特性(六)

    泛型的高级特性1、泛型实化2、泛型协变3、泛型逆变 泛型实化 在Java中(JDK1.5之后),泛型功能是通过泛型...

  • Kotlin 泛型

    Kotlin 支持泛型, 语法和 Java 类似。例如,泛型类: 泛型函数: 类型变异 Java 的泛型中,最难理...

  • java的泛型机制

    <1>:java的泛型机制是javase1.5引入的 <2>:泛型擦除的概念:java中的泛型在编译之后生成的字节...

网友评论

      本文标题:1、java 中的泛型

      本文链接:https://www.haomeiwen.com/subject/qftqvltx.html