Java泛型及类型校验的应用

 更新时间:2026年03月26日 10:40:02   作者:Master_Azur  
泛型(Generics)是编程语言中的一种类型参数化机制,它允许在定义类、接口或方法时使用类型参数,本文给大家介绍Java泛型及类型校验的相关知识,感兴趣的朋友跟随小编一起看看吧

泛型是什么

  • 泛型(Generics)是编程语言中的一种类型参数化机制,它允许在定义类、接口或方法时使用类型参数。这些类型参数可以在实际使用时被具体的类型所替换,从而实现代码的复用性和灵活性。通过泛型,可以编写更加通用的组件,同时保持类型安全。

引入

  • 在实际的需求中,我们可能会遇见需要接收一个参数但是参数的类型不能确定,最简单的方法就是定义多个类型成员变量, 但随着接收参数的类型增加,去类中创建多个成员变量就会显得很麻烦,比如:当data变量可能为整型、浮点型、布尔型、字符型、字符串型的任何一种,总不能都去创建一个该类型的data成员变量吧,这时候就需要使用泛型了

泛型的应用

泛型在类中的应用

  • 如下方代码所示,我们使用了<T>给该类指定了一个需要接收的参数,这个参数实际上要接收的是一个类型值。这就是泛型参数,而后面的属性的类型,方法参数的类型就是由参数T来决定的:
package com.generic;
//public class Box{  
public class Box<T>{
    // private int data;  
    private T data;  
    // private String data;
    //public void setData(int data) {  
    //      this.data = data;        }
    public void setData(T data) {  
            this.data = data;  
    }  
    //public int getData() {  
    //  return data;  
    //}  
    public T getData() {  
        System.out.println("data类型是:" + this.data.getClass());    
        return data;  
    }  
}
  • 我们在GenericMain类中使用Box类,我们先指定Box的类型,在创建Box的对象,如下方代码所示:
public class GenericMain {  
    public static void main(String[] args){  
        Box <boxInter> = new Box<>();  
        boxInter.setData(9);
        Box<String> boxString = new Box<>();  
        boxString.setData("Hello World");
        //测试用例:
        int data = boxInter.getData();  
        System.out.println("data的值是:" + data); 
        String dataStr = boxString.getData();   
        System.out.println("data的值是" + dataStr); 
        //输出案例:  
        //data类型是:class java.lang.Integer  
        //data的值是:9
        //data类型是:class java.lang.String  
        //data的值是Hello World  
     }
}
  • 拓展:实际上我们平时使用的ArrayList容器就是利用率泛型来成为不同类型的容器,即为先指定类型后创建与类型匹配的对象,可以按住ctrl+右击查看ArrayList的源码,会发现实际上ArrayList的源码中也有一个泛型参数<E>
//ArrayList的源码开头 
public class ArrayList<E> extends AbstractList<E>{  ...  

泛型在接口的应用(多态--类型校验)

  • 可以创建一个接口,该接口用于实现,根据不同的类型,进行不同的输出,如下方代码所示:
    • 创建一个拥有泛型参数的接口,在接口中创建一个抽象方法
    • 抽象方法中指定传入参数的类型由泛型决定
public interface Printtable<T> {  
    void print(T data);  
}
  • 创建实现接口的类
    • 先创建一个指定类型为Integer的类
    package com.generic;  
    //定义类来实现接口  
    //public class IntegerPrinttable implements Printtable{
    //我们还需要指定处理泛型中的哪种类型,这样写的好处是java会帮我们做类型检查,
    //使用接口的对象的泛型该实现类的泛型是否匹配  
    public class IntegerPrinttable implements Printtable<Integer>{  
        // @Override  
        // public void print(Object data) { }
        @Override  
        public void print(Integer data) {  
            System.out.println("我被用于指定输出Interger类型的参数" + data);  
            // 提供接口中的抽象方法的具体实现  
        }  
    }  
    • 创建一个类来实现接口,指定类型为String
    package com.generic;
    //定义类来实现接口  
    public class StringPrinttable implements Printtable<String>{  
        // 提供接口中的抽象方法的具体实现  
        @Override  
        public void print(String data) {  
            System.out.println("我被用于指定输出String类型的参数" + data);
        }  
    }
  • 在Box类中使用接口
    • 为了使用接口,可以先创建一个接口的引用private Printtable<T> printtable;
    • 创建一个使用该接口的方法printData(直接调用接口的引用拿到的对象中的print方法);
    • 最后我们写一个Box的构造方法,形式参数为Printtable<T> printtable,即为接口的引用,但需注意的是,这里的目的不是传入接口对象(接口本身也不能实例化为对象),而是利用向上转型(父类持有子类对象)持有实现类的对象,利用向上转型的特性,实现多态
    public class Box<T>{  
        private T data;  
        private Printtable<T> printtable;  
        //在类中将接口声明,可以看为,我们需要在这个类中使用该接口的实现
        public Box(Printtable<T> printtable) {  
            this.printtable = printtable; 
            //这里传入实现了printtable接口类的对象,这里实际上是向上转型  
            //这里的目的实际上就是在使用print方法时通过接口选择那种print方法  
        }      
        public void setData(T data) {  
            this.data = data;  
        }  
        public T getData() {  
            System.out.println("data类型是:" + this.data.getClass());  
            System.out.println(this.data);  
            return data;  
        }  
        public void  printData() {  
            printtable.print(this.data);
            //这里我们使用实现了接口的类的对象中的方法  
        }
    }
  • 在主类GenericMain中进行测试
    • 在Box类中我们写了构造方法要求像传入一个接口实现类的对象,至于具体传入哪个则是根据Box对象选择了泛型的哪一种来决定的
    • 之后就可以调用box中的方法了
    • 我们分别调用boxInter.printData(); boxString.printData();,printData会根据父类接口持有的类对象,匹配实现接口的子类的对象中的方法
    public class GenericMain {  
        public static void main(String[] args){  
        //创建容器容器中添加元素  
        Box<Integer> boxInter = new Box<>(new IntegerPrinttable());  
        boxInter.setData(9);
        //创建容器容器中添加元素
        Box<String> boxString = new Box<>(new StringPrinttable());  
        boxString.setData("Hello World");  
        //测试用例:  
        boxInter.printData();  
        boxString.printData();  
        //输出案例:  
        /*   
        我被用于指定输出Interger类型的参数9
            我被用于指定输出String类型的参数Hello World
        */    
        }
    }
  • 泛型在接口中的应用的例子中,即体现了面向对象的多态特性,又体现了泛型能够进行类型校验的功能,在创建box对象的时候,使用的先指定类型,后创建与指定类型匹配的对象
    • 在上面的例子中,我们可以试着创建不匹配指定泛型的接口实现类对象,可以发现因为类型不匹配ide给我们标红报错了

    • 因为我们本应给Printtable<String> printtable赋值public class StringPrinttable implements Printtable<String>,即为父类接口未持有匹配的子实现类

泛型在方法中的应用

  • 创建一个方法,如下方代码所示
public static<T> void printList(ArrayList<T> list){  
    for(T data:list){  
        System.out.println(data);  
    }  
}
  • 调用方法,如下方代码所示
    • 在这里不需要给public static<T> void printList(ArrayList<T> list)传单独的类型给泛型,因为在printList方法的原型中只要求传入ArrayList的对象,而对象中就已经指定了泛型的类型了
public static void main(String[] args){  
        //列表泛型方法测试用例是  
        ArrayList<Integer> list = new ArrayList<>();  
        list.add(9);  
        list.add(8);  
        list.add(7);  
        printList(list);
        //这里String会被当作泛型T的值直接传入
}

到此这篇关于Java泛型及类型校验的文章就介绍到这了,更多相关Java类型校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 快速解决 MyBatis-Plus 中 ID 自增问题(推荐)

    快速解决 MyBatis-Plus 中 ID 自增问题(推荐)

    本文介绍了MyBatis-Plus中自动生成ID过长导致的问题及解决方法,结合示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-02-02
  • Java中转义字符反斜杠\的代替方法及repalceAll内涵解析

    Java中转义字符反斜杠\的代替方法及repalceAll内涵解析

    这篇文章主要介绍了Java中转义字符反斜杠\的代替方法及repalceAll内涵解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • IDEA2023 配置使用Docker的详细教程

    IDEA2023 配置使用Docker的详细教程

    这篇文章主要介绍了IDEA2023 配置使用Docker的详细教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • java 读写 ini 配置文件的示例代码

    java 读写 ini 配置文件的示例代码

    这篇文章主要介绍了java 读写 ini 配置文件,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-01-01
  • Java Web使用Html5 FormData实现多文件上传功能

    Java Web使用Html5 FormData实现多文件上传功能

    这篇文章主要介绍了Java Web使用Html5 FormData实现多文件上传功能,需要的朋友可以参考下
    2017-07-07
  • 判断二叉树是否为完全二叉树的实例

    判断二叉树是否为完全二叉树的实例

    这篇文章主要介绍了判断二叉树是否为完全二叉树的实例的相关资料,需要的朋友可以参考下
    2017-05-05
  • java Swing实现弹窗效果

    java Swing实现弹窗效果

    这篇文章主要为大家详细介绍了java Swing实现弹窗效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Dubbo服务无法注册到ZK上问题

    Dubbo服务无法注册到ZK上问题

    这篇文章主要介绍了Dubbo服务无法注册到ZK上问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Spring高级注解之@DependsOn详解

    Spring高级注解之@DependsOn详解

    这篇文章主要介绍了Spring高级注解之@DependsOn详解,@DependsOn注解可以定义在类和方法上,意思是我这个组件要依赖于另一个组件,也就是说被依赖的组件会比该组件先注册到IOC容器中,需要的朋友可以参考下
    2024-01-01
  • SpringBoot实现配置文件加密的方案分享

    SpringBoot实现配置文件加密的方案分享

    项目的数据库密码、redis 密码等明文展示在配置文件中会有潜在的风险,因此采用合适的安全防护措施是有必要的,下面小编就为大家介绍一下SpringBoot中配置文件加密的方法,希望对大家有所帮助
    2023-11-11

最新评论