• java 泛型声明与 通配符的使用


    一:泛型类
      把泛型定义在类上:作用域是整个类的内部
      格式:public class 类名<泛型类型1,…>
      注意:泛型类型必须是引用类型

    import java.util.Arrays;
    
    public class GenericClassDemo {
        public static void main(String[] args) {
            MyArrayList<String> list = new MyArrayList<String>();
            list.add("javase");
            list.add("javaee");
            list.add("javame");
            System.out.println(list.get(0));//javase
            System.out.println(list);//[javase, javaee, javame]
        }
    }
    /*泛型类
        把泛型定义在类上:作用域是整个类的内部
        格式:public class 类名<泛型类型1,…>
        注意:泛型类型必须是引用类型
    */
    class MyArrayList<T>{
        private Object[] elementData = new Object[10];
        
        public boolean add(T e) {
            //遍历数组中的元素值,如果当前元素是null,就说明当前位置没有值,就可以往元素位置里面放值
            for(int i=0; i<elementData.length; i++){
                if(elementData[i]==null){
                    elementData[i] = e;
                    return true;
                }
            }
            return false;
        }
        
        public T get(int index) {
            //判断索引是否正确
            if(index<0 || index>elementData.length-1){
                return null;
            }
            return (T) elementData[index];
        }
        
        //[javase, javaee, javame]
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for(int i=0; i<elementData.length; i++){
                //把不等于null的元素添加进sb中
                Object value = elementData[i];
                if(null!=value){
                    sb.append(value+",");
                }
            }
            //将最后一个元素最右边的","去除掉
            String result = sb.toString().substring(0, sb.length()-1);
            
            return result+"]";
        }
    }

    输出结果:

    javase
    [javase,javaee,javame]

    泛型方法
      把泛型定义在方法上:作用域是整个方法
      格式:public <泛型类型> 返回类型 方法名(泛型类型 .)

    package cn.edu360;
    
    public class GenericMethodDemo {
        public static void main(String[] args) {
            Object obj = "哈哈";
            //把obj强转成String
            //String s = (String)obj;
            String s = cast(obj);
            System.out.println(s);//哈哈
    
            obj = 123;//把123自动装箱成Integer
            //把obj强转成Integer
            //Integer i = (Integer)obj;
            Integer i = cast(obj);
            System.out.println(i);//123
        }
        
        /*泛型方法
            把泛型定义在方法上:作用域是整个方法
            格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
        */
        public static <T> T cast(Object obj){
            return (T) obj;//你要的是什么类型,我就给你强转成什么类型
        }
    }

    输出结果:

    哈哈
    123

      接口泛型可以一直传递下去,接口的子类除了可以继承泛型,还可以定义自己特有的泛型

      

    泛型接口
      把泛型定义在接口上
      格式:public interface 接口名<泛型类型1…>

      

    public interface InterTest<T> {
        void test(T t);
    }
    public class GenericInterfaceDemo<E,T,T2> implements InterTest<E> {
        public static void main(String[] args) {
            
        }
    
        @Override
        public void test(E t) {
            // TODO Auto-generated method stub
            
        }
    }

    二、,类型通配符

        

          1.无限定通配符,<?>

          2.上限通配符,<?  extends  Number>。表示参数类型只能是Number的子类。

          3.下限通配符,<?  supper Number>。表示参数类型只能是Number的父类。

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    //泛型特点:泛型的左右类型必须保持一致且必须是引用类型
    public class GenericDemo {
        public static void main(String[] args) {
            /*泛型通配符<?>
            任意类型,如果没有明确,那么就是Object以及任意的Java类了*/
            //test1();
            
            
            /*? extends E
            向下限定,E及其子类*/
            //test2();
            
            
            /*? super E
            向上限定,E及其父类*/
            test3();
    
        }
        /*泛型通配符<?>
        任意类型,如果没有明确,那么就是Object以及任意的Java类了*/
            private static void test1() {
                Object obj = "哈哈";
            //    Collection<Object> c = new ArrayList<String>();//error
                Collection<Object> c = new ArrayList<Object>();
                Collection<?> c2 = new ArrayList<Object>();
                Collection<?> c3 = new ArrayList<Animal>();
                Iterator<?> iterator = c3.iterator();
                //不能往c3里面添加值,因为不知道c3接收的是什么泛型的集合
                //可以取出值,用Object类型接收,因为不论任何类型的值都是Object的子类
                obj = iterator.next();
            }
            
            
            
            
            /*? extends E
            向下限定,E及其子类*/
            private static void test2() {
                Collection<? extends Animal> c = new ArrayList<Animal>();
                Collection<? extends Animal> c2 = new ArrayList<Pig>();
                Collection<? extends Animal> c3 = new ArrayList<Dog>();
                //Collection<? extends Animal> c4 = new ArrayList<Object>();
                //不能往c3里面添加值,因为不知c3接收的是什么泛型的集合
                Iterator<? extends Animal> iterator = c3.iterator();
                //取值的类型可以Animal来接收,因为集合中添加的值肯定是Animal自身或者子类的类型的值
                Animal animal = iterator.next();
            }
        /*? super E
        向上限定,E及其父类*/
            
            
            
            
        private static void test3() {
            //Collection<? super Animal> c = new ArrayList<Pig>();
            Collection<? super Animal> c2 = new ArrayList<Animal>();
            Collection<? super Animal> c3 = new ArrayList<Object>();
            //可以添加值,因为泛型的类型至少是Animal本身或者Animal的父类泛型,根据多态的特点,至少可以添加Animal类型的值
            c3.add(new Animal());
            Iterator<? super Animal> iterator = c3.iterator();
            //因为最大的父类确定不了,所以只能用obj类接收
            Object obj = iterator.next();
        }
    
        
    
    
    }
    class Animal{}
    class Dog extends Animal{}
    class Pig extends Animal{}

    泛型的好处:

      

         在定义泛型对象的使用方法时,还不知道T是什么类型,它可能是String类型,也可能是Integer类型。如果,把T定义成一个确定的泛型数据类型,参数就只能是这种数据类型。此时,就用到了通配符代替确定的泛型数据类型。

            使用泛型、通配符提高了代码的复用性。

            把一个对象分为声明、使用两部分的话。泛型侧重于类型的声明上代码复用,通配符则侧重于使用上的代码复用。泛型用于定义内部数据类型的不确定性,通配符则用于定义使用的对象类型不确定性。

  • 相关阅读:
    赋值运算符函数
    系统设计面试题分析
    内核线程和用户线程的区别
    线程和进程区别
    TCP程序设计
    UDP程序设计
    死锁,死锁必要条件及处理策略
    Linux进程同步机制
    Windows与Linux下进程间通信技术比较
    Windows下进程通信方式
  • 原文地址:https://www.cnblogs.com/ll1994/p/8280708.html
Copyright © 2020-2023  润新知