泛型技术

泛型技术的介绍

  这个技术是JDK5中提供的。

  针对集合这类容器而言,它中可以存放任意的对象,当任何的对象存放到集合中之后,都被提升成Object类型,当我们从集合中遍历出每个对象的时候,拿到的都是Object类型,这时如果我们想使用对象自身的功能时,就需要向下转型。只要使用向下转型都可能发生ClassCastException异常

  在给集合中存放对象的时候,以Object形式存放进去的。在取出时也是Object类型,当我们在使用对象的特有方法时,进行向下转型,结果发生了异常。造成这个异常的原因是集合中可以存放任意类型的对象,而在取出的时候,我们并没有对取出的类型做任何的判断,直接把取出的类型转成某种特定的类型。在转的时候,不是这种类型的数据,在强转时就会发生异常。

  集合是个容器,数组也个是容器。可是数组在定义好之后,它的长度固定了,其中存放的数据类型也被固定了。如果给数组中存放类型不匹配的元素,直接在编译时期就报错。

int[] arr = new int[4];
arr[0] = 3.14;  //这里直接编译报错。

  数组在定义的时候,就把其中存放的数据类型限定死 了。存放的数据一旦不同就直接编译失败。

  我们现在就把数组这种思想移到集合上,在定义集合的时候,也限定集合中存放的数据类型,那么在真正给集合中存放数据的时候如果类型不一致,直接让编译失败。这种实现就Java给我们提供的泛型技术

泛型技术的简单应用

  泛型技术:

  • 格式:<具体的类型>  这个类型只能是引用数据类型
  • 作用(解决的问题):把运行时期的问题,提前到了编译时期。可以保证程序在编译通过之后,运行的时候不会再出现问题。
  • 应用:
    • 在API中,只要看到接口,类名等后面使用<变量名> 都是泛型技术;
    • 当我们在使用这些接口,或者类的时候,要使用者类来指定<> 中间的具体类型。
  • 泛型技术在JDK7中升级,升级成菱形技术

    public class GenericDemo2 {
        public static void main(String[] args) {
            //创建TreeSet集合,并且使用泛型技术
            TreeSet<String> set = new TreeSet<String>( new Comparator<String>(){
    
                public int compare(String o1, String o2) {
                    int temp = o1.length() - o2.length();
                    return temp == 0 ? o1.compareTo(o2) : temp;
                }
    
            } );
    
            set.add("aaa");
            set.add("dddd");
            set.add("a");
            set.add("AAA");
            set.add("DDDD");
            set.add("aaa");
    
            for (String obj : set) {
                System.out.println(obj);
            }
        }
    }

泛型类、方法、静态方法泛型

  在查阅api的时候发现,api中提供的类上或者接口上应用了泛型技术。oracle公司在设计Java中的这些类的时候,它们在类上,或者接口定义了泛型,那么我们就可以模仿他们,在自己定义类的或者接口的时候,也能够使用泛型技术。

泛型类

  需求:定义一个类,负责设置数据,和获取数据

  • 设置字符串数据

    class Demo{
        private String value;
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
    }
  • 设置Integer数据

    class Demo2{
        private Integer value;
        public Integer getValue() {
            return value;
        }
        public void setValue(Integer value) {
            this.value = value;
        }
    }

   上面书写的2个类的确可以设置值也可以获取值,但是它们只能给某个特定的类型来设置值和获取值。当类型不一致时,就无法设置和获取,为了能够给任意对象设置值和获取值,那么:

  • 可以把类中的变量类型定义Object类型。

    class Demo3{
        private Object value;
    
        public Object getValue() {
            return value;
        }
    
        public void setValue(Object value) {
            this.value = value;
        }
    }

  把类中的变量类型改成Object类型之后的确可以保存任意类型的数据,但是调用获取方法时返回的却变成了Object类型,当要使用对象的特有数据时,又要向下转型。这时我们可以使用泛型技术来完成需求。

  这时可以把泛型定义在类上,定以在类上的泛型,就相当于给这个类定义了参数,当使用这个类的时候,要求使用者来指明这个参数到底是什么类型。当把泛型定义在类上时,这个类就成为泛型类。定义在类上的泛型可以在类中直接使用

  • 泛型类

    class Demo4<IT>{
        private IT value;
    
        public IT getValue() {
            return value;
        }
    
        public void setValue(IT value) {
            this.value = value;
        }
    }
    public class GenericDemo {
        public static void main(String[] args) {
            //创建拥有泛型的类对象时,要求指明具体的泛型类型
            Demo4<String> d4 = new Demo4<String>();
            d4.setValue("aaaa");
            String value = d4.getValue();
    
            Demo4<Integer> d5 = new Demo4<Integer>();
            d5.setValue(123);
            Integer value2 = d5.getValue();
        }
    }

泛型方法及静态方法泛型

  定义在类上的泛型可以在类中的成员变量方法上使用。有时我们也会遇到方法上要使用的泛型和类上定义的不一致,这时就需要把泛型定义在方法上。

  • //类上定义的泛型
    class Test<W>{
        private W value;
        //方法上使用类上的泛型
        public void show( W w){
            System.out.println(w);
        }
        /*
         * 定义功能,专门负责打印任何数据,可以在这个方法上定义泛型
         * 在方法上定义的泛型,必须写在返回值的前面
         */
        public <Q> void print( Q q ){
            System.out.println(q);
        }
        /*
         * 静态方法无法使用类上的泛型。
         * 因为类上的泛型的具体类型必须是在创建本类对象的时候明确。
         * 而静态的方法它不需要对象就可以直接执行。
         */
        public static <T> void method( T w ){
            System.out.println(w);
        }
    }
    public class GenericDemo4{
        public static void main(String[] args) {
            Test<String> t = new Test<>();
            t.print("aaa");
            t.print(123);
            t.print(new  Object());        Test.method("bbb");
        }
    }

泛型接口和泛型传递

  • 泛型接口,即:把泛型定义在接口上,泛型接口。
  • 把泛型定义在类上,创建这个类对象的时候,由具体的创建者来明确具体的泛型类型。
  • 定义在接口上,接口是要有实现类来实现这个接口。这时就可以在实现这个接口的时候明确具体的泛型。
  • 当在定义一个类实现某个接口的时候,如果接口上有泛型,但是当前这个实现并不能明确具体的类型时,这时这个实现类可以继续把泛型往下传递,最后后具体创建这个实现类对象的使用这个类明确具体的泛型。这个技术称为泛型的传递
  • 定义泛型接口

    interface Inter<W>{
        public void show(W w);
    }
  • 实现类实现泛型接口

    /*
     * 在书写接口的实现类,就是在使用接口,这时可以明确接口上的泛型类型
     */
    class InterImpl implements Inter<String>{
        @Override
        public void show(String w) {
            System.out.println(w);
        }
    }
  • 泛型的传递

    //interface Collection<E>{}
    //interface List<E> extends Collection<E>{}
    //class ArrayList<E> implements List<E>{}
    /*
     * 在定义实现类的时候,如果不知道接口中泛型的具体类型时,可以继续使用泛型
     */
    class InterImpl2<W> implements Inter<W>{
        public void show(W w) {
        }
    }
    public class GenericDemo5{
        public static void main(String[] args) {
            InterImpl2<String> in = new InterImpl2<>();
        }
    }

泛型通配符

  使用一个符号来匹配所有的数据。这个符号就被称为通配符。

  • 需求:

    定义功能,专门用来打印集合中的数据

    * 打印集合,就是使用遍历,取出集合中的每个元素,然后打印在屏幕上即可。

    public class GenericDemo7 {
        public static void main(String[] args) {
            ArrayList<String> al = new ArrayList<String>();
    
            Collections.addAll(al, "aaaa","dddd","rrrrr","sssss","itcast","ABCD");
    
            printCollection(al);
    
            LinkedList<Integer> ll = new LinkedList<Integer>();
            ll.add(123);
            ll.add(333);
            ll.add(444);
            ll.add(5555);
    
            printCollection(ll);
        }
        /*
         * 定义功能负责打印Collection集合中的元素
         * 这个方法要打印的Collection集合中的元素,这时并不知道真正传递进来的容器中存放的是什么类型的元素。
         * 在定义功能的时候,无法明确Collection的泛型类型。
         * 这时可以使用泛型中的通配符来代替。
         * Java中泛型的通配符可以使用?来表示
         *  Collection<?> coll 当前这个方法可以接收Collection下的所有子集合。?表示的是子集合中的元素类型,
         *  当传递的子集合中存放的是什么类型,?就代表什么类型
         */
        public static  void printCollection( Collection<?> coll ){
            for (Iterator<?> it = coll.iterator(); it.hasNext();) {
                System.out.println(it.next());
            }
        }
        /*
        public static void printCollection( ArrayList<String> coll ){
            for (Iterator<String> it = coll.iterator(); it.hasNext();) {
                System.out.println(it.next());
            }
        }
        public static void printCollection( LinkedList<Integer> coll ){
            for (Iterator<Integer> it = coll.iterator(); it.hasNext();) {
                System.out.println(it.next());
            }
        }
        */
    }

泛型上下限

  • /*
     * 泛型的限定
     */
    public class GenericDemo6 {
        public static void main(String[] args) {
            //这个容器中存放Student对象
            ArrayList<Student> al = new ArrayList<Student>();
    
            al.add(new  Student("zhangsan",23));
            al.add(new  Student("lsi",23));
            al.add(new  Student("wangwu",23));
            al.add(new  Student("zhaoliu",23));
            al.add(new  Student("zhangsan",23));
    
            printCollection(al);
    
            //这个容器中存放Person对象
            ArrayList<Person> al2 = new ArrayList<Person>();
    
            al2.add(new  Person("zhangsan",23));
            al2.add(new  Person("lsi",23));
            al2.add(new  Person("wangwu",23));
            al2.add(new  Person("zhaoliu",23));
            al2.add(new  Person("zhangsan",23));
    
            printCollection(al2);
            //这个容器中存放Worker对象
            LinkedList<Worker> ll = new LinkedList<Worker>();
    
            ll.add(new  Worker("xiaoqiang",33));
            ll.add(new  Worker("wangcai",32));
            ll.add(new  Worker("huaan",28));
            ll.add(new  Worker("qiuxiang",18));
    
            //printCollection(ll);
        }
        /*
         * 这个方法Collection<?> coll 它可以接收Collection下的所有子类,并且可以打印其中的数据
         * 现在对这个方法进行限定,可以打印集合中的元素,但是要求集合中的元素必须是Person类型或者是Person的子类类型
         * 这时需要在方法上加泛型的限定
         *     泛型的上限限定    ? extends Person  这里表示?可以是Person本身,也可以是Person的子类类型
         *     泛型的下限限定   ? super Student  这里?表示当前可以是 Student类型,也可以是Student的父类类型
         */
        public static  void printCollection( Collection< ? extends Person > coll ){
            for (Iterator<?> it = coll.iterator(); it.hasNext();) {
                System.out.println(it.next());
            }
        }
    }

泛型在API中的应用

以TreeSet构造方法为例:

public  class   TreeSet<E> implements Set<E>{
    public TreeSet(){}
}

//可以接收一个集合作为创建TreeSet容器时的初始化数据

public TreeSet( Collection<  ?  extends E >  c ){}

这个构造方法主要作用用于创建TreeSet集合,在创建这个集合的时候可以给其传递一个Collection下的子集合,作为TreeSet集合的创建时的初始数据。

TreeSet<...> set  =  new  TreeSet<...>(...)

在创建TreeSet集合对象的时候,明确了泛型,那么就表示TreeSet定义的E泛型就被明确出来了。由于TreeSet集合要对其中的元素进行排序。

在明确的这个E一定是具备排序的功能。那么在创建TreeSet的时候,传递另外一个集合进来,就要求传递进来的这个集合中的元素一定要能够和E进行比较,然后进行排序。

Collection<  ?  extends E >  这里限定上限的原因是由于创建TreeSet集合的时候明确的类型E类型,那么给TreeSet集合对象初始数据的时候,初始的数据可以E本身,也可以是E的子类类型, 这个样就能够保证在TreeSet集合中存放下。

public TreeSet(Comparator<? super E> comparator) {

创建TreeSet集合的时候,可以传递比较器。比较器的功能是对集合中的元素进行比较的。

比较器就要从集合中把元素取出来,对其中的元素进行比较。比较器首先要从集合中把元素取出来,并且比较器就要使用响应的类型来接收取出的这些元素。

new TreeSet<E> (new  Copmarator(){});

Collecions工具类中的方法

定义泛型                                       返回值类型     方法名         参数列表

public static   <T extends Object & Comparable<? super T>>    T       max    (Collection<? extends T> coll)    {

<T extends Object & Comparable<? super T>> T这个类型必须是Object子类同时T类型还要实现Comparable接口

}

Java总结篇系列:Java泛型

时间: 2024-09-29 22:06:16

泛型技术的相关文章

Swift2.0(17)泛型技术

泛型技术 何为泛型? 简单理解:代码具有与类型无关的通用性 Objective-C在Xcode7开始,引入了泛型技术的应用 Swift支持相对比较完整的泛型技术 泛型函数 格式: func 函数名<类型>(参数列表)->返回类型 {} 如: func my_swap<T>(inout value1 value1:T, inout value2:T) {        var tmp:T        tmp = value1        value1 = value2   

C++泛型技术基础-模板

1. 泛型与模板 C++中,用以支持泛型应用的是标准模板类库STL(Standard Template Library),作为C++标准库的一个重要组成部分,它为用户提供了C++泛型设计常用的类模板和函数模板,并用它们支持C++的泛型设计.可以说,支持C++泛型的核心技术就是模板. 1.1 函数模板 template < typename T, typename R, typename S> T maxt( R x, S y) { return ( x > y ) ? x : y; }

Java的泛型

1,泛型技术 因为容器可以存储多种类型的对象,而在取出时,需要用到对象的特有内容时需要做向下转型,但是对象的类型不一致,会导致ClassCassException异常;为了运行时期不出现类型异常,可以在定义容器时,就明确容器中的元素类型,在向容器存储对象时就进行检查,一旦不一致编译就报错.是一项运行在编译时期的安全机制 注意结合多态且不能和多态弄混 2,泛型容器特点: - 提高了程序的安全性 - 将运行期遇到的问题转移到了编译期 - 省去了类型强转的麻烦 - 泛型类的出现优化了程序设计例程 3,

泛型的基本介绍和使用

在开始深入学习java的泛型了,以前一直只是在集合中简单的使用泛型,根本就不明白泛型的原理和作用.泛型在java中,是一个十分重要的特性,所以要好好的研究下. 泛 型的定义:泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数,在用到的时候在指定具体的类型.这种参数类型可以用在类.接口和方法的创建中,分别称为泛 型类.泛型接口和泛型方法. 泛型思想早在C++语言的模板(Templates)中就开始生根发芽,

Java中的泛型

泛型技术在绝大多数语言总都存在.对泛型狭义的解释就是,在定义类的时候不指定属性或方法参数的类型,用一个T或者其他单词代替类型,等到实例化对象的时候根据实际需要指定类型.这样可以极大的提高代码的重用性和健壮性.如下面的代码: 1 class Message<T> 2 { 3 private T info; 4 public Message(T info) 5 { 6 this.info = info; 7 } 8 9 public T getInfo() 10 { 11 return info;

引出泛型,在程序中的使用和作用。

/** *    泛型的概述 *[目标:泛型的由来和基本使用] 1,因为集合可以存储的对象类型是任意的,在取出进行向下转型时,容易发生ClassCastException. 所以JDK1.5以后就有了解决这个问题的技术:泛型. 2,泛型的原理:其实就是在操作的元素类型不确定时,通过传递参数的形式来明确类型. 3,泛型的体现就是 <参数类型变量>用于接收具体的实际元素类型. 4,泛型技术在集合框架中应用非常广泛,只要记住:在使用类或者接口时,如果接口上有明确<>泛型. 在使用时,就传

泛型Java

这两天一直在学习Java中的泛型,发现泛型的出现帮我们苦逼程序猿解决了许多潜在的问题,并为我们程序猿编程减轻了工作量. 下面把我的心得体会与大家共享一下(尽管只是些皮毛): 泛型技术的由来:在集合中可以存储任意的对象,但是在取出时,如果要使用具体对象的特有方法时,需要进行向下转型,如果存储的对象类型不一致,在转型的过程中,就会出现ClassCastException异常.看下面一个例子: package cn.itcast.generic.demo; import java.util.Array

恶补java(十)---泛型与集合的再学习

其余的就不多说了,一切都在代码中 package com.gc.generic; /** * JDK5 之前集合对象使用问题: * 1.向集合添加任何类型对象 * 2.从集合取出对象时,数据类型丢失,使用与类型相关方法,强制类型转换 * 存在安全隐患 * * ***************************** * * JDK5中的泛型:允许程序员使用泛型技术限制集合的处理类型 * List<String> list=new ArrayList<String>(); * 从而

【泛型】Generic

参考: http://blog.csdn.net/lonelyroamer/article/details/7864531#comments http://blog.csdn.net/lonelyroamer/article/details/7868820#comments http://blog.csdn.net/LonelyRoamer/article/details/7927212#comments 关于泛型的一些重要知识点 泛型由来:早期Java版本(1.4及之前)如果要代指某个泛化类对