前言

这几天分享了怎么搭建集群,这一篇给大家介绍的是泛型,在我们的很多java底层的源代码都是有很多复杂的泛型的!那什么是泛型呢?

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

Java语言引入泛型的好处是安全简单。在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求

开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。那废话不多说,我们进入正题:

一、泛型的简介

1.1、泛型概述

  泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type),也就是说所操作的数据类型被指定为一个参数,在用到的时候在指定具体的类型。
  这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。
  泛型的类型将来传入是只能是引用类型的,不能是基本类型的。

//编译通过    List<String>    List<Action>    List<Integer>    List<Integer[]>    List<int[]>
//编译报错 List<int>

1.2、泛型特点

  java中的泛型只是在编辑期间起作用的,在运行时会把泛型信息擦除的。

只是在编译期间启动类型安全检查的作用,运行时不起作用。

例如:List<String> list = new ArrayList<String>();

虽然指定了泛型为String,但是在运行时候依然是可以向该list中存放其他类型数据的。(比如使用反射的方法)

二、泛型类

一个泛型类就是具有一个或多个类型变量(把类型参数化)的类。
定义一个泛型类十分简单,只需要在类名后面加上<>,再在里面加上类型参数.

注:类型变量使用大写形式,且比较短,这是很常见的。在JDK中,使用变量E表示集合的元素类型,K和V分别表示关键字与值的类型。(需要时还可以用其他的字母,也可以是一个或多个字母)

举例1:

这里的T是根据将来用户使用Point类的时候所传的类型来定

public class Point<T> {
private T x;
private T y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}

  当我们创建一个对象为:Point<Double> p = new Point<Double>(); ,这里的T就代表的是double。

举例2:

     这里的T和S是根据将来用户使用Point类的时候所传的类型来定

public class Point<T,S> {
private T x;
private S y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public S getY() {
return y;
}
public void setY(S y) {
this.y = y;
}
}

  当我们创建一个对象为:Point<String,Integer> p = new Point<String,Integer>();  ,这个的T是String,S是Integer类型的。

三、泛型接口

一个泛型接口就是具有一个或多个类型变量的接口。

举例: 

public interface Action<T,U>{
void doSomeThing(T t,U u);
} public class ActionTest implements Action<String,Date>{
public void doSomeThing(String str,Date date) {
System.out.println(str);
System.out.println(date);
}
}

四、泛型方法

泛型方法就是在方法上直接声明泛型。

public class Test{
public <T> void run1(T t){ } public <T> T run2(T t){
return t;
} public <T,S> void run3(T t,S s){ }
}

五、通配符

  泛型增加了java中类型的复杂性,例如List<String>、List<Integer>、List<Object>等这些都是不同的类型。

//编译报错
//虽然 List list = new ArrayList(); 是正确的
//虽然 Object是String的父类型
//但是下面代码编译时报错的,因为使用了泛型
List<Object> list = new ArrayList<String>();

  泛型中?是通配符,它可以表示所有泛型的父类型,集合元素可以是任意类型,这种没有意义,一般是方法中,只是为了说明用法。
      List<?> list = new ArrayList<任意>();

//这时list可以指向任何泛型的List类型集合对象
public void test(List<?> list){
//编译报错,因为我们并不知道?到底代表什么类型
list.add();

//编译通过
for(Object o:list){
System.out.println(o);
}
}

   注:通配符?只能用在泛型变量声明的时候。

六、泛型中的extends和super关键字

在泛型中可以使用extends和super关键字来表示将来用户所传的泛型参数的上限和下限。

6.1、extends关键字的使用

举例1:在声明泛型类和泛型接口时使用extends

public class Point<T extends Number> {
private T x;
private T y;
} public class Point<T extends Number,S> {
private T x;
private S y;
} public interface Action<T extends Person> {
public void doSomeThing(T t);
} 例如:在声明泛型方法时使用extends
public <T extends Action> void run(T t){ }

  举例2:在声明泛型方法时使用extends

public <T extends Action> void run(T t){
}

  举例3:在声明泛型类型变量时使用extends

List<? extends Number> list = new ArrayList<Integer>();
List<? extends Number> list = new ArrayList<Long>();
List<? extends Number> list = new ArrayList<Double>();
//编译报错
List<? extends Number> list = new ArrayList<String>(); 例如:
public void test(List<? extends Number> list){ }

6.2、super关键字的使用

  举例1:   

//编译报错
//声明泛型类或泛型接口时不能使用super
public class Point<T super Number> { }
public interface Action<T super Number> { } //编译报错
//声明泛型方法时不能使用super
public <T super Action> void run2(T t){ }

  举例2:在声明泛型类型变量时使用super

//编译通过
List<? super Number> list1 = new ArrayList<Object>();
List<? super Student> list2 = new ArrayList<Object>();
List<? super Student> list3 = new ArrayList<Person>(); //编译通过
public void test(List<? super Number> list){ } //编译通过
public void test(List<? super Student> list){ }

总结:

  ArrayList<T> al=new ArrayList<T>();指定集合元素只能是T类型
  ArrayList<?> al=new ArrayList<?>();集合元素可以是任意类型,这种没有意义,一般是方法中,只是为了说明用法
  ArrayList<? extends E> al=new ArrayList<? extends E>();
  泛型的限定:
    ? extends E:接收E类型或者E的子类型。
    ?super E:接收E类型或者E的父类型。

七、泛型中的&

使用&可以给泛型加多个限定  

    public class A{

        }
public inerface B{ }
//不管该限定是类还是接口,统一都使用关键字extends
//可以使用&符号给出多个限定
//如果限定既有接口也有类,那么类必须只有一个,并且放在首位置
public class Point<T extends A&B> {
} class Sub extends A implements B{}
main:
//编译报错
Point<A> p = new Point<A>();
Point<B> p = new Point<B>(); //编译通过
Point<Sub> p = new Point<Sub>();

总结:我们可以观察API中的Map接口及其方法的声明

public interface Map<K,V>{
public V get(Object key);
public Set<Map.Entry<K,V>> entrySet();
public Set<K> keySet();
public void putAll(Map<? extends K,? extends V> m);
..
}

  

觉得不错的点个“推荐”哦!

javaSE(九)之泛型(Generics)的更多相关文章

  1. [19/03/23-星期六] 容器_ 泛型Generics

    一.概念 生活中的容器不难理解,是用来容纳物体的,程序中的“容器”也有类似的功能,就是用来容纳和管理数据. 数组就是一种容器,可以在其中放置对象或基本类型数据. ---优势:是一种简单的线性序列,可以 ...

  2. 泛型(Generics)

    Framework类库中的泛型 泛型可以使代码重用,提高开发效率 CLR允许在引用类型.值类型或接口中定义泛型方法: CLR允许创建泛型引用类型.泛型值类型(枚举不允许创建).泛型委托类型和泛型接口类 ...

  3. Java 泛型(Generics)

    Generics, 类似C++中的模版. 允许在定义类和接口的时候使用类型参数(type parameters), 声明的类型参数在使用的时候用具体的类型来替换. 如 ArrayList<Str ...

  4. JavaSE复习_8 泛型程序设计

    今晚看了core Java的泛型部分,万万没有想到,当时看培训班视频入门的一带而过的泛型,有这样多的细节,整理了一下书里面提到的一些自认为的重点,方便以后观阅.由于是复习,一些基础知识跳过. △泛型类 ...

  5. Java学习笔记九(泛型)

    1.介绍 所谓的泛型就是将类型作为一种參数来传递.有了泛型后类型不再是一成不变的.能够通过泛型參数来指定. 能够提供程序开发的灵活性. 2.泛型类或接口的使用 泛型类声明时.与普通类没有太大的差别,仅 ...

  6. javase高级技术 - 泛型

    在写案例之前,先简单回顾下泛型的知识 我们知道,java属于强变量语言,使用变量之前要定义,并且定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 所谓“泛型”,就是“宽泛的数据类 ...

  7. Java 泛型(Generics) 综述

    一. 引子 一般的类和方法.仅仅能使用详细类型:要么是基本类型.要么是自己定义类型.假设要编写能够应用于多种类型的代码,这样的刻板的限制对代码的束缚就会非常大. 多态算是一种泛化机制,但对代码的约束还 ...

  8. Welcome-to-Swift-22泛型(Generics)

    泛型代码可以确保你写出灵活的,可重用的函数和定义出任何你所确定好的需求的类型.你可以写出避免重复的代码,并且用一种清晰的,抽象的方式表达出来. 泛型是Swift许多强大特征中的其中一个,许多Swift ...

  9. Javase之集合泛型

    集合泛型知识 泛型 是一种把类型明确工作推迟到创建对象或者调用方法的时候才明确的特殊类型. 也称参数化类型,把类型当成参数传递. 在jdk1.5中出现.一般来说经常在集合中使用. 格式 <数据类 ...

  10. JAVASE(十五) 泛型 :泛型用例、自定义泛型类、通配符

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.泛型在集合中的使用 1.1 在集合中使用泛型之前的例子 ​ 为什么要有泛型(Generic)? 1. ...

随机推荐

  1. 【Hibernate】版本错误 org/hibernate/Query : Unsupported major.minor version 52.0

    报错原因:jdk1.7不支持 hibernate的最新版本5.2.0,把hibernate的版本换成5.1.3或更早的版本. 补充:mysql-connector-java-6.0.x也不被hiber ...

  2. vc++6.0修改字体

    近期在使用vc++6.0写C程序 问题:vc++自带的字体不太好看 解决办法:修改注册表 1. win+r 运行 regedit 调出注册表编辑器 进入到目录 HKEY_CURRENT_USER\SO ...

  3. IT类非开发面试总结--2

    面试总结.. ================================= 第一部分..(自己对公司的最低要求) 面试需要提前准备的是:<想好自己以后要干嘛--我在想我以后要干嘛> ...

  4. ASP.NET Core 2.0使用Cookie认证实现SSO单点登录

    之前写了一个使用ASP.NET MVC实现SSO登录的Demo,https://github.com/bidianqing/SSO.Sample,这个Demo是基于.NET Framework,.NE ...

  5. 手机自带输入法emoji表情的输入,提交及显示——纯前端解决方案

    很早之前就遇到过需要前端支持用户输入并提交emoji表情的问题,一直没有尝试去解决,今天再一次狭路相逢,该来的躲不过,那就着手解决吧. 大多数emoji表情都是4字节的utf-16编码(辅助平面字符, ...

  6. 总结找到后台路径的N总思路方法

    1, 穷举猜解      现如今可以暴力猜解网站后台登陆地址的软件有很多,从最早的啊D注入工具开始,一直到现在很多常用的工具(通常为SQL注入利用工具)都会带有后台登陆地址猜解的功能. 当然了,这个猜 ...

  7. python常用的数据结构运行效率分析

    1.while循环和for循环相同条件下的运行效率比较: 如下代码: import time as tm import timeit as tt import random as rm def whi ...

  8. Spring详解(二)------IOC控制反转

    我相信提到 Spring,很多人会脱口而出IOC(控制反转).DI(依赖注入).AOP等等概念,这些概念也是面试官经常问到的知识点.那么这篇博客我们就来详细的讲解 IOC控制反转. ps:本篇博客源码 ...

  9. 第一篇--认识Jmeter

    Jmeter是Apache组织开发的基于Java的压力测试工具,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试静态和动态资源,例如静态文件.Java 小服务程序.CGI 脚 ...

  10. TCON板新选择--NCS8807 LVDS转mLVDS芯片

    NCS8807 LVDS-to-mLVDS w/ Scaler (4K TCON w/ Scaler) General Description NCS8807 is an LVDS 4K TCON w ...