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

时间: 2024-10-12 02:32:35

java泛型学习(2)的相关文章

java泛型学习示例_java

Java泛型(Generics)是JDK5开始引入的一个新特性,允许在定义类和接口的时候使用类型参数(Type Parameter).声明的类型参数在使用时用具体的类型来替换,现在泛型最主要的应用是在JDK5中的新集合类框架中,Map, List均有用到.其中的优点不言而喻,我们可以横向扩展更多的类,缺点呢,其实也就是他的优点,因为这需要我们在使用泛型类的时候,要很清楚自己的代码目地,不能使用错误的类型. 最基本的泛型类 复制代码 代码如下: package com.garinzhang.jav

java泛型学习(1)

java泛型(Generices Type)    --->概念:泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引入泛型的好处是安全简单. --->优点:(1)在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的"任意化","任意化"带来的缺点是要做显式的强制类型转换

java泛型学习4之自定义泛型类(DAO)

  例一 package cn.xy.test; public class GenericDao {  public <T> void add(T t)  {  }  public <T> T getModelById(int id)  {   return null;  } } 这个类中泛型方法被常规使用,但两个方法之间的T没有联系和相互约束.       例二 package cn.xy.test; import java.util.Set; public class Gene

java泛型学习3之类型参数的限制

例一private static <T> T returnT(T i) {      return i; } returnT("abc"); returnT(1); 以上两个方法均正确.     例二private static <T> void swap(T[] t, int i, int j) {     T tmp = t[i];     t[i] = t[j];     t[j] = tmp; } swap(new String[ ] { "a

java 泛型的类型擦除与桥方法

java 泛型 学习java泛型的笔记,详细写明白在学习泛型的过程中的笔记心得等: 泛型类 泛型方法 类型擦除(Type Erasure) 桥方法 泛型类 代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 public Pair() { first = null; second = null;} public Pair(T first , T second ) {this.f

java泛型的学习笔记[2]—实际使用

继上一文<java泛型的学习笔记[1]-基础知识>之后,本文将介绍泛型的一些应用和应用过程中遇到的问题. 在此之前,我们先给出一张类图:   1)泛型类型的子类型问题 我们首先来看这样一句代码.该行代码正确,因为Cat是Animal的子类型 Animal animal=new Cat();// 但是再看下一句代码: AarrayList<Animal> animals=new ArrayList<Cat>();//编译出错        这句代码编译出错,因为虽然因为C

Java 8学习资料汇总

本文首发于InfoQ. Java 8发布已经有一段时间,它被认为是Java 5发布以来最大的一次版本升级.Java 8 为Java语言.编译器.类库.开发工具以及JVM(Java虚拟机)带来了大量新特性.Lambda表达式.默认方法.并行API等都受到了开发者的追捧,社区上关于Java 8的学习资料如雨后春笋般涌现.下面是一些优秀的学习资料汇总: Brian Goetz在Stack Overflow上的回答Brian是<Java并发编程实战>的作者之一,有20多年的软件咨询行业经验.Brian

java泛型<?&amp;amp;gt;什么泛型参数

问题描述 java泛型<?>什么泛型参数 java泛型<?>什么泛型参数,是不是无视它,假如可以无视它,为什么还要写上它 解决方案 <?>是通配符呀,相当于一个占位符,看下面的例子,你就知道这个符号的意义了: 用通配符,表示List泛型参数是Integer或其子类: public static void run(List<? extends Integer> list){ } 不用通配符,你能表示吗? 解决方案二: 不写的话泛型参数会是这样.而写上通配符&l

Java 泛型实例详解_java

理解Java泛型最简单的方法是把它看成一种便捷语法,能节省你某些Java类型转换(casting)上的操作: List<Apple> box = ...; Apple apple = box.get(0); 上面的代码自身已表达的很清楚:box是一个装有Apple对象的List.get方法返回一个Apple对象实例,这个过程不需要进行类型转换.没有泛型,上面的代码需要写成这样: List box = ...; Apple apple = (Apple) box.get(0); 很明显,泛型的主