zoukankan      html  css  js  c++  java
  • java泛型学习(2)

    一:深入泛型使用。主要是父类和子类存在泛型的demo

    /**
     * 父类为泛型类
    * @author 尚晓飞
    * @date 2014-7-15 下午7:31:25 
    * 
    * 
    * 父类和子类的泛型。
    * 【泛型的具体声明】
    * (1)子类直接声明具体类型
    * (2)使用时指定具体类型(new 对象时)
    * (3)子类泛型>=父类泛型(个数,类型,顺序无关)
    * 
    * 【泛型的确定】
    * (1)属性:在父类中,泛型随父类泛型而定
    *            子类中,泛型随子类泛型而定
    * (2)重写方法中:
    *         泛型全部随父类而定
    * 【泛型的擦除】
    * 父类和子类泛型要么同时擦除。统一object对待
    * 子类不能擦除泛型,而父类存在泛型
    * 
    * 
    * @param <T>
     */
    public abstract  class Father<T,T1> {
        T name;
        public abstract T test(T t);
    }
    
    //子类声明时指定具体类型
    //属性类型为具体类型
    class Child1 extends Father<String,Integer>{
    
        @Override//重写方法中,泛型全部随父类而定
        public String test(String t) {
            // TODO Auto-generated method stub
            return null;
        }
    
        
    }
    
    //子类为泛型类.类型在使用时确定(new 对象时)
    //子类类型>=父类类型 
    class Child2<T1,T,T2> extends Father<T,T1>{
        @Override
        public T test(T t) {
            // TODO Auto-generated method stub
            return null;
        }
    }
    
    //子类为泛型类,父类不指定泛型,统一object对待,父类泛型的擦除
    //子类和父类同时擦除泛型。
    //子类不能单独擦除泛型,而父类不擦除泛型
    class Child3<T1,T> extends Father{
        T1 name2;//子类中属性,随子类泛型而定
    
        @Override
        public Object test(Object t) {
            // TODO Auto-generated method stub
            return null;
        }
            
    }
    
    //这是报错的,子类擦除,父类使用泛型。编译通不过。
    class Child extends Father<T, T1>{
        
    }
    View Code

    二:泛型的一个误区使用demo

    Student泛型类

    public class Student<T> {
        T javase;
        T oracle;
        
        public T addStudent(T t1){
            T sT=t1;
            return sT ;
        }
        
        public Student() {
            super();
        }
        public Student(T javase, T oracle) {
            super();
            this.javase = javase;
            this.oracle = oracle;
        }
        public T getJavase() {
            return javase;
        }
        public void setJavase(T javase) {
            this.javase = javase;
        }
        public T getOracle() {
            return oracle;
        }
        public void setOracle(T oracle) {
            this.oracle = oracle;
        }
        
    }
    View Code

    测试Test类

    泛型的擦除
     * 【1】子类继承|实现时不指定泛型
     * 【2】使用时不指定泛型
     *  统一Object对待,但泛型不是object,编译时不会类型检查
     *  编译器会发出警告,但不报错

     1 /**
     2  * 泛型的擦除
     3  * 【1】子类继承|实现时不指定泛型
     4  * 【2】使用时不指定泛型
     5  *  统一Object对待,但泛型不是object,编译时不会类型检查
     6  *  编译器会发出警告,但不报错 
     7 * @author 尚晓飞
     8 * @date 2014-7-15 下午8:26:21 
     9 *
    10  */
    11 public class Test {
    12     public static void main(String[] args) {
    13         Student stu1=new Student();//如果使用时不确定泛型类型,编译器会发出警告,但不算错;
    14         Object sd=stu1.javase;//类型统一用object对待。相当于object,而不是指object
    15         
    16         Student<Object> stu2=new Student<Object>();
    17         
    18         test1(stu1);//虽然没确定泛型,以object对待,只是相当于,但不确定。泛型擦除,编译时编译器不会类型检查。所以不报错
    19         test1(stu2);//如果泛型指定是Object时,那么传入的实参的泛型必须是Object.此方法报错。泛型一旦确定,哪怕是指定Object,编译器会编译类型检查
    20         
    21         test2(stu1);
    22         test2(stu2);
    23         
    24     }
    25     
    26     //方法一
    27     public static void  test1(Student<Integer> st){}
    28     //方法二
    29     public static void test2(Student<?> st){}
    30 }
    View Code

    java泛型的深入理解

    在学习泛型之前,简单介绍下泛型的一些基本术语,以ArrayList<E>ArrayList<Integer>做简要介绍:

    整个成为ArrayList<E>泛型类型

    ArrayList<E>中的 E称为类型变量或者类型参数

    整个ArrayList<Integer> 称为参数化的类型

    ArrayList<Integer>中的integer称为类型参数的实例或者实际类型参数

    ·ArrayList<Integer>中的<Integer>念为typeof   Integer

    ArrayList称为原始类型

     

    以下为泛型擦除的概念和示例代码,帮助理解java泛型的原理

     

     1 //【1】java的泛型是伪泛型,只是在编译时起作用,进行类型检查,可称为java的语法糖。
     2         //【2】一旦编译通过,编译成内存中的class文件信息,jvm就将所有的泛型擦除。在jvm中的class信息是无泛型的,都统一是object
     3         //【3】泛型擦除后的原始类型-->,什么是原始类型?原始类型(raw type)就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型。
     4         //无论何时定义一个泛型类型,相应的原始类型都会被自动地提供。类型变量被擦除(crased),
     5         //并使用其限定类型(无限定的变量用Object)替换。 
     6         //【4】,类型检查就是针对引用的,谁是一个引用,用这个引用调用泛型方法,就会对这个引用调用的方法进行类型检测,而无关它真正引用的对象
     7         //因此arryList3能添加Integer类型数据,而与new ArrayList<String>();对象无关,它只是开辟一个空间
     8         ArrayList<String> arrayList1=new ArrayList<String>();
     9         arrayList1.add("shangxiaofei");
    10         
    11         ArrayList<Integer> arrayList2=new ArrayList<Integer>();
    12         arrayList2.add(125);
    13         //【4】
    14         ArrayList arrayList3=new ArrayList<String>();
    15         arrayList3.add(125);
    16         
    17         //【2】本身arrayList2中只能存放Integer类型的数据,但通过反射获取arrayList2的class信息,并操作add方法,却往里添加了字符串。
    18         //证明了java泛型是伪泛型,只存在编译器检查语法错误和类型转换层面,一旦编译成class文件,所有泛型全部擦除
    19         arrayList2.getClass().getMethod("add", Object.class).invoke(arrayList2, "zifuchuan");
    20         //【1】虽然指定了不同的泛型,但类信息还是相同,说明java泛型是伪泛型。
    21         System.out.println("Test.main()"+(arrayList1.getClass()==arrayList2.getClass()));
    22         
    23         
    View Code

    2、泛型中的?通配符的扩展

    1:界定通配符的上边界

    Vector<? extends 类型1> x = new Vector<类型2>();

    类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的子类

    Vector<? extends Number> x = new Vector<Integer>();//这是正确的

    Vector<? extends Number> x = new Vector<String>();//这是错误的

     

    2:界定通配符的下边界

    Vector<? super 类型1> x = new Vector<类型2>();

    类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的父类

    Vector<? super Integer> x = new Vector<Number>();//这是正确的

    Vector<? super Integer> x = new Vector<Byte>();//这是错误的

     

     

     

    3:泛型不存在多态

    首先回顾一下java的多态

     1 //java的多态回顾
     2 public class Animal {
     3 
     4 }
     5 
     6 class Dog extends Animal{
     7     
     8 }
     9 
    10 class Test1 {
    11     public static void main(String[] args) {
    12         //【1】多态 父类引用指向子类对象
    13         Animal animal=new Dog();
    14         add(new Dog());
    15     }
    16     //【2】形参使用多态
    17     public static void add(Animal animal){
    18         
    19     }
    20     //【3】返回值类型使用多态
    21     public static Animal get(){
    22         return new Dog();
    23     }
    24 }
    View Code

    泛型不存在多态的示例代码

     1 //泛型类
     2 class App<T>{}
     3 class Test2{
     4     public static void main(String[] args) {
     5         //【1】泛型不存在多态 ,因此错误
     6         //App<Animal> app=new App<Dog>();
     7         App<Animal> app=new App<Animal>();
     8         
     9         //【2】当形参规定什么泛型时,传递的实参必须是什么泛型,不存在多态
    10         //add(new App<Dog>());
    11     }
    12     //形参使用多态
    13     public static void add(App<Animal> app){}
    14     
    15     //【3】返回值类型的多态,也不正确
    16     public static App<Animal> get(){
    17         //return new App<Dog>();返回值类型不存在多态
    18         //return (App<Animal>)(new App<Dog>());强制类型转化也不对
    19         return null;
    20     }
    21 }
    View Code

    4:泛型的通配符:? extends super 

      [1]通过通配符号,可以实现类似多态的功能

    (1)?号的使用  声明类型|声明方法 时使用。不能声明类和使用泛型时使用。

       ?号可以接受所有类型,只能接收和输出,不能修改

     1 //?的使用
     2 //【1】声明类泛型时不能使用
     3 //【2】声明方法参数时泛型可以使用?号
     4 //【3】声明返回值类型时泛型可以使用?号
     5 //【4】具体使用泛型时不能使用?号,要把?号确定成某一类型
     6 
     7 //【1】class Student<?>{}声明类时不能使用
     8 class Student2<T>{
     9     T score;
    10     public static void add(Student2<?> stu){}//【2】声明方法参数时使用?号
    11     //【3】声明返回值类型时可以使用?号
    12     public static Student2<?> get(){
    13         return new Student2<Integer>();
    14     }
    15 }
    16 
    17 class Test3{
    18     public static void main(String[] args) {
    19         Student2<?> student=new Student2<String>();
    20         //student.add(new Student2<?>());//【4】使用时不能使用?号
    21           student.add(new Student2<Integer>() );//使用时要把?号确定成指定的类型
    22     }
    23 }
    View Code

    (2)? extends V   上限   所使用的泛型必须<=V  必须是V的子类或本身

    (3)? super V  下限   所使用的泛型必须>=V  必须是V的超类或本身

     1 //extends super使用
     2 class Student2<T>{
     3     T score;
     4     
     5     public static  void test1(Student2<? extends Animal> st){}
     6     public static  void test2(Student2<? super Animal> st){}
     7     
     8     //annimal是dog的父类
     9     public static void main(String[] args) {
    10         test1(new Student2<Dog>());
    11         //test1(new Student2<Object>());object是Animal的超类,超过上限,报错
    12         
    13         test2(new Student2<Object>());
    14         //test2(new Student2<Dog>());dog是Animal的子类,不在下限范围内,报错
    15     }
    16 }
    View Code

    5:泛型的嵌套

     1 public class Bjsxt<T> {
     2     T pe;
     3 }
     4 class Person<T>{
     5     T socre;
     6 }
     7 class Test5{
     8     public static void main(String[] args) {
     9         //泛型的嵌套
    10         Bjsxt<Person<String>> bjsxt=new Bjsxt<Person<String>>();
    11         //从外到内拆分
    12         Person<String> pe=bjsxt.pe;
    13         String socreString=pe.socre;
    14     }
    15 }
    View Code

    6:泛型和数组

    (1)没有泛型数组,不能创建泛型数组

    (2)可以只有声明,可以使用?

     1 package com.bjsxt.shangxiaofei;
     2 
     3 public class Array {
     4     public static void main(String[] args) {
     5         Integer[] arr=new Integer[30];//声明一个数组
     6         //Student<String>[] sts=new Student<String>[10];没有泛型数组,但可以声明
     7         Student<String>[] sts=new Student[10]; //可以声明,但并没有什么实际意义
     8         Student<?>[] stss=new Student[10];
     9         
    10         
    11         MyArrayList<String> mList=new MyArrayList<String>();
    12         mList.add(0, "尚晓飞");
    13         //mList.add(1, new Student());泛型规定是String,也就是说数组里只能存放String
    14         String nameString=mList.get(0);
    15         String[] strs=mList.getAll();
    16         System.out.println("Array.main()"+nameString);
    17     }
    18 }
    19 
    20 //泛型与数组的应用。巧妙在于将一个object数组,固定存放String的值
    21 class MyArrayList<E>{
    22     //声明一个object数组
    23     Object[] objs=new Object[30];
    24     
    25     //给数组添加一个值
    26     public void add(int idx, E e){
    27         objs[idx]=e;
    28     }
    29     //获取数组
    30     public E[] getAll(){
    31         return (E[])objs;
    32     }
    33     //获取某个下标的值
    34     public E get(int idx){
    35         return (E)objs[idx];
    36     }
    37     
    38 }
    View Code

     7:jdk1.7对泛型的修改

    1 //jdk1.7后对泛型的修改
    2         //只在声明时用一次泛型,创建和使用时不需要,只需要加上<>
    3         List<String> ad=new ArrayList<String>();//1.7以前使用泛型
    4         //List<String> ad2=new ArrayList<>();//1.7以后只需要声明一次  使用和创建时不需要指定类型
    View Code

    asdf

  • 相关阅读:
    张照行 的第九次作业
    张照行 的第八次作业
    Learning by doing
    张照行 的第七次作业
    张照行 的第六次作业
    Java第七次作业
    java第五次作业
    Java第七次作业
    Java第六次课后作业
    第五次Java作业
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/3846456.html
Copyright © 2011-2022 走看看