概述
  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. Android文件系统编译出错记录

    错误1: 注意:external/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java 使用了未经检查或不 ...

  2. sine曲线向前运动

    using UnityEngine; using System.Collections; public class sineWork : MonoBehaviour { float verticalS ...

  3. Linux下的XAMPP基本配置技巧(设置虚拟主机、添加FTP账户等)

    xampp安装好之后就只有一个默认站点及一个默认nobody的ftp账户,这显然不符合我们平时的需求了,那么下面就来讲一下如何设置并管理多个虚拟主机及ftp账户了,至于xampp的安装不在此讨论范围, ...

  4. Qt——添加动作及对话框

    1. 添加动作 教程:https://www.devbean.net/2012/08/qt-study-road-2-action/ 运行教程中的第一个程序,报错如下: 原因:没有将main.cpp改 ...

  5. path 与classpath针对JAVA来说

    Path 路径,是java编译时需要调用的程序(如java,javac等)所在的地方CLASSPATH 类的路径,在编译运行java程序时,如果有调用到其他类的时候,在classpath中寻找需要的类 ...

  6. 解决win764位安装pycrypto遇到unable to find vcvarsall.bat 问题

    今天安装pycrypto的库.安装中遇到一些问题,这里简单记录下来. 首先安装python,pycrypto是基于python的一个库. 第一种:搜索关键字pycrypto,找到pycrypto的官方 ...

  7. CF 434C Tachibana Kanade's Tofu[数位dp+AC自动机]

    Solution //本代码压掉后两维 #include<cstdio> #define max(a,b) (a<b?b:a) using namespace std; inline ...

  8. Capistrano 部署rails 应用

    1 安装 gem install capistrano // For mutiple stages gem install capistrano-ext 2 准备 capify . 这个命令会创建Ca ...

  9. 【OOP】C++ const成员函数

    预备知识 1.代码转换分析技巧 在早期某些编译器会将C++代码翻译为C代码,然后使用C编译器生成可执行文件.其中翻译的一个转化就是:将this指针显式添加到成员函数的第一个参数位置上,并在成员函数调用 ...

  10. Django---简单模板遍历渲染

    简单路由: urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), path('list/', vi ...