概述
  1. 泛型就是参数化类型,一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参,其实你回味一下这里。形参参数化的是变量的值,而如果你想参数化变量的类型,那就用到泛型了。同样的, 定义的时候叫类型形参,使用时传入类型实参
    1. 所以很多时候你会遇到,定义一个方法的时候,形参的类型和值都是用变量表示的,比如:<T> T[] toArray(T[] a);
  2. 所以 , 泛型就是把类中或者方法中某些数据的类型也作为参数来传递,使得代码更加灵活
  3. 对比:
    1. 我把以前的做:参数化变量、变量形参、变量实参
    2. 现在的叫做:参数化类型、类型形参、类型实参
  4. 其实两个还有很大区别的:
    1. 参数化变量只在定义方法的时候会使用,对类没有参数化变量一说,实例化类传递的参数实际上只是构造方法的参数
    2. 而参数化类型不仅在定义方法的时候使用,还在定义类的时候会使用到,这点上它会带来很大的不同
      1. 参数化类型能通过形式参数限定实际参数范围。类比参数化变量,是这样的样子:比如变量类型是Int,你要求int的范围是0到100,于是有 int<100> a;
      2. 本来类之间的相对关系只有一个维度(虽然类似是一个树图),两个类之间有明确的上下关系或者是没有关系(即使算上多重继承),但如果一个类又有了参数化类型的尾巴的话,那类之间的关系又有了一个新的维度,造成的结果可能是这个维度上,A在上B在下,而在另一个维度,B在上A在下,不过目前JAVA就规定尾巴的维度不使用
        1. 这里可能对于尾巴这个维度有一点异议,因为它比较复杂
          1. 在定的时候,一般如果是<T>,那这个维度可以说没有,但如果对这个T有extends的话,那确实会有一个范围,会有一个上下关系
          2. 在使用的,这种上下关系就很明显了,T本身的取值就是类型,它的上下关系会造成外面 Class<T>的上下关系吗
      3. 对类的使用场景有:定义类的时候,实例化类的时候,声明对象类型的时候(多态)
        1. 前两种情况比较简单,但是第三种情况就需要实际面临上面提到的问题【在使用的,这种上下关系就很明显了,T本身的取值就是类型,它的上下关系会造成外面 Class<T>的上下关系吗 】,你需要找到一个基类
 
泛型分 泛型类/接口 和 泛型方法
  1. 实例化泛型类的时候需要显式传递泛型参数,使用泛型方法则一般通过参数传递
 
而应用情景又分为:
  1. 定义泛型时(定义泛型时只能发生在 类/接口的定义 和方法的定义时)
    1. 定义泛型--类/接口,就是在定义类的时候指定某个类型为参数。形式是这样,<>写在定义的类的名称的后边: class Box<T> { .......}
    2. 定义泛型--方法,就是在定义方法的时候指定某个类型为参数。形式是这样,<>写在方法的public 后 void前:public  <T> T[] toArray(T[] a);
  2. 使用泛型时
    1. 使用泛型可以发生在 任何时候,包括 类/接口的定义 和方法的定义时
    2. 使用方法就是把本来应该写类型名称的位置改成你定义的泛型形参名字 , 形式非常简单
  3. 声明对象类型的时候(多态)

下面要做一些拓展(两个层次的上下限):
  1. 类Box<T>中可以向T传入不同的类型参数。T作为形式参数(注意T是传入 类型名,(相当于Object啊),不是对象,这点很特殊,不是多态)
    1. 可以限制T的类型范围,在<T>中标记类型限定:
      1. 不管该限定是类还是接口,统一都使用关键字extends
      2. 跟类的继承使用的关键字是一样的,这里的特点是,这个关键字写在<>里
      3. 这里extends的意思是,T可以是他们的子类(不能是XX的父类。跟没节操的下面不一样)
      4. 可以使用&符号给出多个限定
      5. 如果限定既有接口也有类,那么类必须只有一个,并且放在首位置
      6. 比如 Box<T extends Object&Comparable&Serializable>
  2. 另一个层面(上面说的是Box<T> 中的T,下面要说有<T>这个尾巴的Box<T>本身) ,当【Box<T>这个类的对象】要【作为参数】进行传递的时候,用什么作为它的基类呢?(注意,这里就是传统的传递对象了,用基类和多态完成)
    1. 实验证明,Box<Fruit>和Box<Apple>之间没有等级关系,应该是都为Box类。但是这个Box基类要如何表示呢
    2. JAVA给了一种方法,Box<?>是Box<具体类型名>的基类,于是方法可以是这样:
      public static void getData(Box<?> data)
    3. 而且另一个层面,可以限制用Box<?>作为类型形参传入的Box<具体类型名>对象的范围,在形式参数Box<?>上标记通配符上下限:
      1. 注意点:为什么说另一个层面,因为在对 method(Box<?>  data) 这个整体来看时,它作为一个参数的类型的限定,跟普通的 method(Box data) 对比
        1. 普通的method(Box data) ,表示data的类型,只能是Box类型,或者是Box子类
        2. 而method(Box<?>  data),表示data的类型,只能是Box<各种>的类型,无他
        3. 同时在method(Box<?>  data)中加入了上下限,再缩小了【Box<各种>】的范围,变成【Box<上下限>】
      2. 具体用法:
        1. Box<? extends int>  ;意思是,可以传入以int的所有衍生类作为具体类型名参数的Box类型的对象(然后这个对象本身还可以传入多种不同的类型,也就是它有两重限制的样子)
        2. Box<? super int>;意思是,可以传入以int的所有父类作为具体类型名参数的Box类型的对象

Java泛型初探的更多相关文章

  1. 【Java心得总结三】Java泛型上——初识泛型

    一.函数参数与泛型比较 泛型(generics),从字面的意思理解就是泛化的类型,即参数化类型.泛型的作用是什么,这里与函数参数做一个比较: 无参数的函数: public int[] newIntAr ...

  2. 唬人的Java泛型并不难

    泛型 public interface Foo<E> {}public interface Bar<T> {}public interface Zar<?> {} ...

  3. Java泛型的历史

    为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...

  4. 浅析Java 泛型

    泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...

  5. Java:泛型基础

    泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...

  6. java泛型基础

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类.接口和方法的创建中, 分别称为泛型类.泛型接口.泛型方法.  Ja ...

  7. 使用java泛型设计通用方法

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...

  8. 关于Java泛型的使用

    在目前我遇到的java项目中,泛型应用的最多的就属集合了.当要从数据库取出多个对象或者说是多条记录时,往往都要使用集合,那么为什么这么使用,或者使用时有什么要注意的地方,请关注以下内容. 感谢Wind ...

  9. 初识java泛型

    1 协变数组类型(covariant array type) 数组的协变性: if A IS-A B then A[] IS-A B[] 也就是说,java中的数组兼容,一个类型的数组兼容他的子类类型 ...

随机推荐

  1. SpringBoot(五)-- 整合Spring的拦截器

    一.步骤 1.创建我们自己的拦截器类并实现 HandlerInterceptor 接口. 2.创建一个Java类继承WebMvcConfigurerAdapter,并重写 addInterceptor ...

  2. Selenium 执行JavaScript

    Selenium 可以直接模拟运行 JavaScript,使用 execute_script() 方法即可实现 from selenium import webdriver browser = web ...

  3. RAC的搭建(三)--Grid的安装

    1. 安装cvuqdisk.rpm补丁包 在两个Oracle RAC 所有节点上安装操作系统程序包cvuqdisk.如果没有cvuqdisk,集群验证实用程序就无法发现共享磁盘. 该包在p104045 ...

  4. J2EE学习篇之--Struts1详解

    今天来看一下Struts1的相关知识,其实Struts现在是出名的,每个Web开发者都会知道的,也是现在比较流行的框架,下面就来看一下我们为什么要用Struts框架呢? 摘要 1.建立在mvc这种好的 ...

  5. Android井字游戏(一)首页制作

    创建一个新程序: 应用名: Tic Tac Toe 公司域名: example.org 尺寸: Phone and Tablet 最低SDK: API16: Android 4.1 添加活动: Emp ...

  6. .net 将DLL程序集生成到指定目录中

    .在程序集右键属性 .在程序集属性界面中找到生成事件 在预先生成事件命令行添加: IF NOT EXIST "$(ProjectDir)..\Bin" MD "$(Pro ...

  7. Android Studio 删除 Module

    1.选中Module右击,选择 Open Module Settings,打开Project Structure 窗空.(或者选中Module,按F4打开Project Structure窗口) 2. ...

  8. C# 输出带颜色文字,用于实时日志输出

    private void button1_Click(object sender, EventArgs e) { LogMessage("绿色"); 4 LogError(&quo ...

  9. linux的shell后门尝试以及Cython转成C代码编译

    零.背景 最近研究了一下之前的反弹shell的python代码块,写了一点代码尝试在LInux下绑定和反弹shell(正反向),看了一些代码,基本是两种思路.1.本地shell的输入输出通过管道与so ...

  10. Google浏览器清除缓存快捷键

    1.CTRL+SHIFT+DEL:直接进入“清除浏览数据”页面,包括清除浏览历史记录.清空缓存.删除Cookie等. 2.chrome浏览器F12中 ctrl+p 可以定位文件