`
把阳光剪成雨Java
  • 浏览: 25203 次
  • 性别: Icon_minigender_1
  • 来自: 长春
社区版块
存档分类
最新评论

黑马程序员——泛型

 
阅读更多

 ----------------- android培训java培训、期待与您交流! -----------------

 

泛型

1,泛型基本应用。

package reflect;

import java.lang.reflect.InvocationTargetException;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Vector;

 

public class GenericTest {

    public static void main(String[] args) throws InstantiationException,

           IllegalAccessException, IllegalArgumentException,

           SecurityException, InvocationTargetException, NoSuchMethodException {

       // 泛型是提供给javac编译器使用的,可以限定集合的输入类型,让

       // 编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时

       // 会去掉类型信息,使程序运行的效率不受影响,对于参数化的泛型

       // 类,getClass()方法的返回值和原始类型完全一样。由于编译生成的

       // 字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型

       // 集合中加入其他类型的数据,例如,用反射得到集合,再调用其add方法即可。

 

       ArrayList<String> collection = new ArrayList<String>();

       collection.add("a");

       collection.add("b");

       collection.add("abc");

 

       String str = collection.get(1);

       // 编译器强制集合存储同一种类型的数据。

       ArrayList<Integer> collection2 = new ArrayList<Integer>();

       // 编译完的字节码没有泛型参数类型。

       System.out.println(collection2.getClass() == collection.getClass());

       // 利用反射的方式得到字节码,往里面加入其他数据也是可以的。

       collection.getClass().getMethod("add", Object.class).invoke(collection,

              1);

       System.out.println(collection);

      

//  参数化类型与原始类型的兼容性:

//     参数化类型可以引用一个原始类型的对象,编译报告警告,例如:

       Collection<String> c = new Vector();//编译器一句话的事。

//     原始类型可以引用一个参数化类型的对象,编译报告警告。例如,

       Collection c2 = new Vector<String>();

//  参数化类型不考虑类型参数的继承关系:

//     Vector<String> v = new Vector<Object>();//错误

//     Vector<Object> v2 = new Vector<String>();//错误

      

//     在创建数组实例时,数组的元素不能使用参数化的类型。例如,下面的语句有错误。

//     Vector<String> v3 = new Vector<String>[10];

 

//  下面的代码不会报错,不要用程序的执行顺序进行推理,记着泛型就是给编译器看的。

//     Vector v1 = new Vector<String>();

//     Vector<Object> v = v1;

      

    }

}

2,通配符?

public class GenericTest2 {

    public static void main(String[] args) {

       Collection<String> collection = new ArrayList<String>();

       collection.add("a");

       collection.add("b");

       collection.add("abc");

      

       printCollection(collection);

    }

//泛型中的?通配符。

//  使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,

//  可以调用与参数化无关的方法,不能调用与参数化有关的方法。

    private static void printCollection(Collection<? extends Object> collection) {

      

    }

//  限定通配符的上边界。

//  正确

    Vector<? extends Number> x = new Vector<Integer>();

//  错误

//  Vector<? extends Number> y = new Vector<String>();

   

//  限定通配符的下边界。

//  正确

    Vector<? super Number> z = new Vector<Object>();

//错误

    //  Vector<? super Number> a = new Vector<Integer>();

   

//  注意:通配符总是包括自己。

   

   

}

 

 

3,自定义泛型的方法及应用。

//     printCollection(collection);

//     Object obj = null;

//     autoConvert(obj);

//     int类型

       add(3,5);

//     fload类型

       Number n =add(3.5,3);

//     Object类型

    Object o =add(3,"abc");

//     最大公约数。

      

    }

//定义两个数相加,返回的值是任意的。

    private static <T> T add(T x,T y){

//     return (T)(x+y);

       return null;

    }

//  交换数组的位置。

    private static <T> void swap(T[] a,int i,int j){

       T tmp = a[i];

       a[i]= a[j];

       a[j]=tmp;

    }

    private static <T> T autoConvert(Object obj) {

       return (T)obj;

    }

    private static <T> void fillArray(T[] a,T obj){

       for(int i=0;i<a.length;i++){

          

       }

    }

//  如果自定义泛型?

//  用于放置泛型的类型参数的尖括号应该出现在

//  方法的其他所有修饰符之后和在方法的返回类型之前

//  也就是紧邻返回值之前。按照惯例,类型参数通常用

//  单个大写字母表示。

//  swap(new int[3],3.5),这样不行,只有引用类型才能作为泛型方法的实际参数。

//  除了在应用泛型时候使用extends限定符,在定义泛型时候也可以使用extends限定符。

//  例如,Class.getAnnotation()方法的定义。并且可以用&来指定多个边界,如

//  <V extends Serializable&cloneable> void method(){}

//  普通方法,构造方法,静态方法中都可以使用泛型。编译器也不允许创建

//  类型变量的数组。

//  也可以使用类型变量表示异常,成为参数化的异常,可以用于方法的

//  throws列表中,但是不能用于catch字句中。

//  在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分

//  例如:puboic staic <K,V> V getValue(K key){return map.get(key)}

//数组拷贝到集合中。

    public static <T> void copy1(Collection<T> c,T[] src){

    }

//  数组拷贝到数组。

    public static <T> void copy2(T[] dest,T[] src){

      

    }

 

 

 

 

4,类型参数的类型推断。

    编译器判断范型方法的实际类型参数的过程称为类型推断,类型推断是相对于知觉推断的,其实现方法是一种非常复杂的过程。

    根据调用泛型方法时实际传递的参数类型或返回值的类型来推断,具体规则如下:

    当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法时该处的实际应用类型来确定,这很容易凭着感觉推断出来,即直接根据调用方法时传递的参数类型或返回值来决定泛型参数的类型,例如:

        swap(new String[3],3,4)       static <E> void swap(E[] a, int i, int j)

    当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型都对应同一种类型来确定,这很容易凭着感觉推断出来,例如:

        add(3,5)    static <T> T add(T a, T b)

    当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型,例如,下面语句实际对应的类型就是Number了,编译没问题,只是运行时出问题:

        fill(new Integer[3],3.5f)    static <T> void fill(T[] a, T v)

    当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型, 并且使用返回值,这时候优先考虑返回值的类型,例如,下面语句实际对应的类型就是Integer了,编译将报告错误,将变量x的类型改为float,对比eclipse报告的错误提示,接着再将变量x类型改为Number,则没有了错误:

        int x =(3,3.5f)    static <T> T add(T a, T b)

    参数类型的类型推断具有传递性,下面第一种情况推断实际参数类型为Object,编译没有问题,而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型,编译将出现问题:

       copy(new Integer[5],new String[5])  static <T> void copy(T[] a,T[]  b);

       copy(new Vector<String>(), new Integer[5])  static <T> void copy(Collection<T> a , T[] b);

 

 

5,自定义泛型类的应用。

/*如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,语法格式如下:

    public class GenericDao<T> {

       private T field1;

       public void save(T obj){}

       public T getById(int id){}

    }

类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的,例如,如下两种方式都可以:

GenericDao<String> dao = null;

new genericDao<String>();

注意:

在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。

当一个变量被声明为泛型时,只能被实例变量、方法和内部类调用,而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。

 

 

 

分享到:
评论

相关推荐

    net基础——泛型PPT教案学习.pptx

    net基础——泛型PPT教案学习.pptx

    C 设计新思维——泛型编程与设计范式之应用 PDF.rar

    C 设计新思维——泛型编程与设计范式之应用 PDF,候捷译序。㆒般人对C templates 的粗略印象,大约停留在「容器(containers)」的制作上。稍有研究由会发现,templates衍生出来的C Generic Programming(泛型编程)技术...

    博客《夯实JAVA基本之一——泛型详解(1)》对应源码

    在《夯实JAVA基本之一——泛型详解(1)》的博客中,作者深入浅出地探讨了泛型的基本概念和用法,本文将基于这个博客源码,详细解析泛型的相关知识点。 首先,泛型的主要目标是提高代码的类型安全性。在未引入泛型...

    博客《夯实JAVA基本之一——泛型详解(2)》对应源码

    在《夯实JAVA基本之一——泛型详解(2)》这篇博客中,作者深入探讨了泛型的高级用法和概念,这些内容对于理解和掌握Java泛型至关重要。 首先,泛型的基本语法是以尖括号 `&lt;T&gt;` 表示,其中 `T` 是一个类型参数,代表...

    C#重要知识之——泛型列表List例子

    在C#编程中,泛型列表`List&lt;T&gt;`是一个非常重要的数据结构,它为我们提供了动态数组的功能,并且具有类型安全的特性。这篇文章将深入探讨`List&lt;T&gt;`的使用,包括其基本操作、性能特点以及一些高级用法。 一、基础概念...

    黑马程序员Javase笔记

    Java是世界上最流行的编程语言之一,尤其在...总结来说,"黑马程序员Javase笔记"涵盖了Java的基础语法、内存管理、面向对象编程、集合框架以及泛型和Map等内容,这些都是成为一名合格Java开发者必须掌握的核心知识。

    黑马程序员-Java语言进阶-源码、教程笔记.zip

    day02_Collection、泛型 day03_List、Set、数据结构、Collections day04_Map,斗地主案例 day05_异常,线程 day06_线程、同步 day07_等待与唤醒案例、线程池、Lambda表达式 day08_File类、递归 day09_字节流、字符流...

    黑马程序员匠心之作 C++教程_第7阶段-C++实战项目机房预约讲义.rar

    《黑马程序员匠心之作 C++教程_第7阶段-C++实战项目机房预约讲义》是为C++初学者量身定制的一份详细教学资源。这份讲义深入浅出地介绍了C++编程语言,并通过实际的机房预约系统项目,帮助学习者将理论知识与实践相...

    黑马程序员匠心之作 C++教程_第5阶段-C++提高编程资料讲义.rar

    《黑马程序员匠心之作 C++教程_第5阶段-C++提高编程资料讲义》是一份针对C++编程初学者精心制作的教程资料,旨在帮助学习者深入理解和提升C++编程技能。这份讲义涵盖了许多关键的C++知识点,下面将对其进行详细解读...

    黑马程序员----泛型学习注意点

    黑马程序员提供的这篇关于泛型的学习注意点,结合了源码分析和工具应用,旨在帮助开发者深入理解并有效运用泛型。下面将详细阐述泛型的主要知识点: 1. 泛型的基本概念: 泛型是Java SE 5.0引入的新特性,主要用于...

    全网首发黑马程序员鸿蒙 HarmonyOS NEXT星河版零基础入门到实战,零基础也能快速入门鸿蒙开发教程2

    《全网首发黑马程序员鸿蒙 HarmonyOS NEXT星河版零基础入门到实战》是一套针对初学者精心设计的鸿蒙操作系统开发教程。本教程旨在帮助没有编程基础的学员快速掌握HarmonyOS的开发技能,通过丰富的实例和清晰的讲解,...

    B站《黑马程序员匠心之作-C++教程从0到1入门编程,学习编程不再难》 配套笔记

    【标题】:“B站《黑马程序员匠心之作-C++教程从0到1入门编程,学习编程不再难》 配套笔记” 【描述】提及的是一个针对初学者的C++教学资源,来自B站上的视频课程“BV1et411b73Z”。这门课程的特色在于提供了一份...

    黑马程序员----泛型与反射的小运用

    在Java编程语言中,泛型和反射是两个非常重要的特性,它们在软件开发中有着广泛的应用。本篇文章将深入探讨这两个概念以及它们在实际开发中的小运用。 首先,我们来看泛型(Generics)。泛型是在Java SE 5.0引入的...

    程序员C++提高编程PDF.pdf

    在黑马程序员的《程序员C++提高编程PDF》讲义中,特别针对泛型编程和STL技术进行了详细讲解,这表明了模板在C++编程中的重要性。 首先,讲义介绍了模板的基本概念,这可以通过生活中的模板类比来理解。模板就像是一...

    黑马程序员面试宝典(java)2018版

    《黑马程序员面试宝典(java)2018版》是一本专门为Java开发者准备的面试指南,涵盖了大量在面试过程中可能遇到的问题和知识点。这本宝典由黑马程序员机构精心编纂,汇集了近万名学员的实际面试经验,为求职者提供了...

    黑马程序员.NET基础测试题

    【标题】:“黑马程序员.NET基础测试题”是一个与.NET编程相关的学习资源,主要针对初学者或正在参加黑马训练营的学员。这个测试题集旨在帮助他们检验和提升.NET技术的基础知识。 【描述】:资源中包含“黑马训练营...

    第三阶段 黑马程序员C++提高编程

    ### 第三阶段 黑马程序员C++提高编程 #### 知识点概述: 在本阶段的学习资料中,重点聚焦于C++的高级特性——泛型编程及其应用之一:标准模板库(Standard Template Library, STL)。泛型编程允许开发者编写代码时...

Global site tag (gtag.js) - Google Analytics