• java泛型


    什么是泛型?

    泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

    我们为什么要使用泛型?

    我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方法的参数类型不同。然而,泛型可以很轻松的解决这个问题。

    用一个小小的例子简单看看:

    public class Point <T>{
        private T var;
        public T getVar(){
            return var;
        }
        public void setVar(T var){
            this.var=var;
        }
    
    }
    public class test {
    
        public static void main(String[] args) {
            Point<String> p1 = new Point<String>();
            p1.setVar(30 + "");
            Point<Integer> p2 = new Point<Integer>();
            p2.setVar(30);
            System.out.println(p1.getVar());
            System.out.println(p2.getVar());
        }
    
    }

    运行结果如下:

    从代码中可以很明显的看出泛型的优势。

    同时,泛型可以使程序操作更加安全,可以避免发生类转换异常。当然还可以提高代码重用率。

    泛型的基本应用

     泛型的定义:

    类定义:

      【访问权限】 class 类名称 <泛型类型标识1,泛型类型标识2,……,泛型类型标识n>{

      【访问权限】 泛型类型标识 变量名称;

      【访问权限】 泛型类型标识 方法名称(){};

      【访问权限】 返回值类型声明 方法名称(泛型类型标识 变量名称){};

    }

    对象定义:

    类名称<具体类> 对象名称=new 类名称<具体类>();

    注意:

    1. 在上面的例子中,Point类中使用了"<T>",T表示此类型是由外部调用本类时指定的,使用任意字母均可,如<A>、<Y>都可以,为了突出type(表示类型)才使用的T。
    2. 另外,泛型是无法指定基本数据类型的,必须设置成一个类,因此在设置一个数字时就必须使用包装类。
    3. 如果设置的内容与泛型所指定的类型不一致,则会在编译时出错。
    4. 可以在声明类时指定多个泛型类型。如class A<K,V>{}
    5. 在泛型应用中最好在声明类对象时指定好其内部的数据类型,如Info<String>,否则在使用时会出现不安全操作的警告信息。(不影响程序运行)

    通配符的使用:

    在泛型类的操作中,在进行引用传递时,泛型类型必须匹配才可以传递。

    例如将上面的例子改成:

    public class test {
    
        public static void main(String[] args) {
            Point<String> p1 = new Point<String>();
            p1.setVar(30 + "");
            fun(p1);
        }
    
        private static void fun(Point<Object> p1) {
            System.out.println(""+p1.getVar());        
        }
    
    }

    会有如下的错误提示:

    另外,我们还可以直接去掉<Object>,可正常运行。但是,不指定泛型类型不符合习惯,因此引入了通配符“?”,表示接收此类型的任意泛型对象。修改如下:

    public class test {
    
        public static void main(String[] args) {
            Point<String> p1 = new Point<String>();
            p1.setVar(30 + "");
            fun(p1);
        }
    
        private static void fun(Point<?> p1) {
            System.out.println(""+p1.getVar());        
        }
    
    }

    注意:如果使用"?"接收泛型对象时,则不能设置被泛型指定的内容。如:Point<?> p1 = new Point<String>();

    受限泛型:

    泛型上限使用extends关键字声明,表示泛型的类型可能是所指定的类型或者是此类型的子类。

    泛型下限使用super进行声明,表示泛型的类型可能是所指定的类型,或者是此类的父类,或是Object类。

    具体格式:

    设置上限:(声明对象)类名称<? extends 类> 对象名称      (定义类)[访问权限] 类名称<泛型标识 extends 类>

    设置下限:(声明对象)类名称<? super 类> 对象名称    (定义类)[访问权限] 类名称<泛型标识 super 类>

    同样以最上面的例子做修改:

    public class test {
    
        public static void main(String[] args) {
            Point<Integer> p1 = new Point<Integer>();
            p1.setVar(30 );
            fun(p1);
        }
    
        private static void fun(Point<? extends Number> p1) {
            System.out.println(""+p1.getVar());        
        }
    
    }

    运行结果如下:(可正常运行)

    注意:

    一个类的子类可以通过对象的多态性为其父类实例化,但是在泛型操作中,子类的泛型类型是无法使用父类的泛型类型接收的,

    如:

    public static void main(String[] args) {
            Point<Integer> p1 = new Point<Integer>();
            Point<Number> p2 = new Point<Number>();
            p2=p1;
        }

    编译时会出错:

    这里为什么不能向上转型呢?

    如果将子类泛型变为父类泛型,则表示扩大了子类的内容。打个比方:p1和p2由于类型的不同,p2相当于商场的全部商品,p1相当于个人购买的商品,如果p2=p1就相当于在个人购买商品中加入了商城的全部商品,这是基本不可能的。

    泛型接口:

    格式:【访问权限】 interface 接口名称 <泛型标识>

    interface info<T>{
        public T getVar();
    }

    泛型接口的实现方式有两种:

    1. 在子类的定义上声明泛型类型
    2. 直接在接口中指定具体类型

    下面分别实现(第一种)

    interface info<T>{
        public T getVar();
    }
    
    class Point <T> implements info <T>{
        private T var;
        public Point(T var){
            this.setVar(var);
        }
        public T getVar(){
            return var;
        }
        public void setVar(T var){
            this.var=var;
        }
    
    }
    public class test {
    
        public static void main(String[] args) {
            info<String> i=null;
            i=new Point<String>("hehe");
            System.out.println(""+i.getVar());
            
        }
    
    }

    运行结果:

    (第二种)

    interface info<T>{
        public T getVar();
    }
    
    class Point implements info<String>{
        private String var;
        public Point(String var){
            this.setVar(var);
        }
        public String getVar(){
            return var;
        }
        public void setVar(String var){
            this.var=var;
        }
    
    }
    public class test {
    
        public static void main(String[] args) {
            info<String> i=null;
            i=new Point("hehe");
            System.out.println(""+i.getVar());
            
        }
    
    }

    运行结果:

    泛型方法

    泛型方法的定义与其所在的类是否是泛型类是没有任何关系的。

    定义:【访问权限】<泛型标识> 泛型标识 方法名称(【泛型标识 参数名称】)

    如:public<T> T fun(T t){ return t;}

    个人感觉泛型方法的使用与一般方法的使用并无太大的区别。

    泛型的嵌套

     简单的讲就是在一个类的泛型中指定另外一个类的泛型。用一个简单的实例就能明白了。

    class info<T,V>{
        private T var;
        private V value;
        public info(T var,V vanue){
            this.setVar(var);
            this.setValue(vanue);
        }
        public T getVar(){
            return var;
        }
        public void setVar(T var){
            this.var=var;
        }
        public V getValue(){
            return value;
        }
        public void setValue(V value){
            this.value=value;
        }
    }
    
    class Demo <S>{
        private S info;
        public Demo(S info){
            this.setInfo(info);
        }
        public S getVar(){
            return info;
        }
        public void setInfo(S info){
            this.info=info;
        }
    
    }
    public class test {
    
        public static void main(String[] args) {
            Demo<info<String,Integer>> d=null;//将info作为泛型类型
            info<String,Integer> i=null;//info要指定两个两个泛型类型
            i=new info<String,Integer>("123",456);
            d=new Demo<info<String,Integer>>(i);//在demo类中设置info类对象
            System.out.println(""+d.getVar().getVar());
            System.out.println(""+d.getVar().getValue());
            
        }
    
    }

    运行结果:

  • 相关阅读:
    早晨突然想到的几句话
    VBA-工程-找不到工程或库-解决方案
    Mysql 服务无法启动 服务没有报告任何错误
    一道有趣的面试题
    异步和多线程
    异或运算
    线性代数解惑
    全文搜索引擎 Elasticsearch (一)
    HandlerExceptionResolver统一异常处理 返回JSON 和 ModelAndView
    MySQL 20个经典面试题
  • 原文地址:https://www.cnblogs.com/scetopcsa/p/3819000.html
Copyright © 2020-2023  润新知