在java中,普通的类和方法只能用具体的类型,这对代码的限制很大,代码的可重用性大大降低。

那么如何才能让同一个类和方法使用不同类型的对象呢?在接触泛型之前我们可能会想到通过类型转换的方法来实现。

public class Test {
Object o; public Test(Object o) {
this.o = o;
} public void set(Object o){
this.o=o;
} public Object get(){
return o;
} public static void main(String[] args) {
String str="hello world";
Test test=new Test(str);
String str2=(String) test.get();
} }

但是这种方法有很大的缺陷,容易在类型转换过程中出现错误,而使用泛型能很好地避免这个错误的出现。


泛型能够能够指定容器容器要装什么类型的对象,无须类型转换。

泛型类:

public class Test<T> {
private T a; public Test(T a) {
this.a = a;
} public T getA() {
return a;
} public void setA(T a) {
this.a = a;
} public static void main(String[] args) {
Test<String> test = new Test<>("test");
System.out.println(test.getA());
}
}

泛型方法:

    public <T> String getClassName(T t) {
return t.getClass().getSimpleName();
}

对于泛型方法和泛型类,我们通常首先选择泛型方法,毕竟,泛型类的束缚更大,它表示我们在整个类中都要使用着这类型;相对而言泛型方法就灵活许多,我们可以在不同的方法中使用不同的类型。


泛型擦除:

public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
System.out.println(list1.getClass()==list2.getClass());
/*
output:
true
*/
}

list1和list2的泛型参数类型不相同,但从上面的结果中不难看出,系统认为它们是相同的类型,因为泛型只在编译过程起作用,当程序运行时泛型参数的具体信息都被擦除。


边界:

class Animal{
void eat(){}
} class Bird extends Animal {
}

当我们已经确认此泛型参数为一固定类型Animal或Animal的子类时,我们希望能够调用Animal对象中的eat方法, 那我们又该如何实现呢?

这里我们需要用到泛型边界,它通过extends关键字来实现:

public class Test<T extends Animal> {
public void test(T t) {
t.eat();
}
}

这里声明了边界Animal,它可以调用Animal中的成员。如果没有声明边界,则默认边界为Object。

当然如果只是实现这个目的,我们无需使用泛型:

public class Test{
public void test(Animal a){
a.eat();
}
}

好像这里使用泛型没什么用处,其实并非如此。当泛型方法有泛型类型的返回值时,它能返回确切的类型:

public class Test<T extends Animal> {
public T get(T t) {
t.eat();
return t;
} public static void main(String[] args) {
Animal a = new Test<>().get(new Animal());
Bird b = new Test<Bird>().get(new Bird());
}
}

这比不使用泛型灵活许多,所以,我们在考虑是否使用泛型时要根据具体情况而定,看看结构是否足够复杂,使用泛型是否会给我们带来方便。


通配符:

我们再来看一个错误例子:

List<Animal> list=new ArrayList<Bird>(); //error:Type mismatch: cannot convert from ArrayList<Bird> to List<Animal>

想当初第一次运行类似的代码时,我有些无法理解,Bird是Animal的子类,为何就不能向上转型呢呢,这泛型也太呆板了。仔细一想才发现,这根本就不是向上转型,List<Animal>代表Animal类型的列表,而ArrayList<Bird>代表Bird类型的列表。

可是我们就是想要实现这样的功能,那该怎么做?这里就需要用到通配符:

List<? extends Animal> list=new ArrayList<Bird>();

泛型与数组:

我们无法直接创建泛型数组实例,因为你数组类型必须是确定的,以此确保类型安全,但是擦除却使类型参数信息消失。

List<String>[] lists=new ArrayList<String>[12]; //error

但是们可以声明一个泛型数组:

List<String>[] lists;

根据以上两个特性,我们可以创建一个非泛型数组,再进行转型,从而获得泛型数组:

List<String>[] lists=(List<String>[])new ArrayList[12];
//或简化为:List<String>[] lists=new ArrayList[12];

java之泛型的使用的更多相关文章

  1. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  2. Java 中泛型的全面解析(转)

    Java泛型(generics) 是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在J ...

  3. Java中泛型 类型擦除

    转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...

  4. Java 泛型 Java使用泛型的意义

    Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性 ...

  5. 跟着刚哥梳理java知识点——泛型(十三)

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ...

  6. 【Java】泛型学习笔记

    参考书籍 <Java核心技术:卷1> 泛型, 先睹为快 先通过一个简单的例子说明下Java中泛型的用法: 泛型的基本形式类似于模板, 通过一个类型参数T, 你可以"私人定制&qu ...

  7. [转] Java 的泛型擦除和运行时泛型信息获取

    原文链接 https://my.oschina.net/lifany/blog/875769 前言 现在很多程序员都会在简历中写上精通 Java.但究竟怎样才算是精通 Java 呢?我觉得不仅要熟练掌 ...

  8. Java 容器 & 泛型:五、HashMap 和 TreeMap的自白

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Java 容器的文章这次应该是最后一篇了:Java 容器 系列. 今天泥瓦匠聊下 Maps. 一.Ma ...

  9. 【译】9. Java反射——泛型

    原文地址:http://tutorials.jenkov.com/java-reflection/generics.html ===================================== ...

  10. Java“禁止”泛型数组

    Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ...

随机推荐

  1. Hi3559AV100 NNIE开发(3)RuyiStudio软件 .wk文件生成过程-mobilefacenet.cfg的参数配置

    之后随笔将更多笔墨着重于NNIE开发系列,下文是关于Hi3559AV100 NNIE开发(3)RuyiStudio软件 .wk文件生成过程-mobilefacenet.cfg的参数配置,目前项目需要对 ...

  2. MyBatis架构分析

      我们都知道Mybatis是一个非常小巧灵活的ORM框架,深受国内广大开发者的喜爱,我们知道它的出现某种程度是为了消除所有的JDBC代码和参数的手工设置以及结果集的封装问题:基于这个一点,我们就可以 ...

  3. Memory Networks02 记忆网络经典论文

    目录 1 Recurrent Entity Network Introduction 模型构建 Input Encoder Dynamic Memory Output Model 总结 2 hiera ...

  4. Java 树结构实际应用 一(堆排序2秒排完800w数据)

    堆排序 1 堆排序基本介绍 1) 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复 杂度均为 O(nlogn),它也是不稳定排序. 2) 堆是具有以下性 ...

  5. 文件锁fcntl

    一.python中的文件锁 我们在写python应用的时候,当涉及到多个进程向同一个文件write(或者read)的情况,如果几个进程同时都对这个文件进行写操作,那么文件的内容就会变得非常混乱,这个时 ...

  6. sqlmap在https下的一种错误 - ssl连接失败

    在昨天与师傅的交流中师傅考了我一个问题,在用sqlmap跑的时候遇到ssl爆红该怎么办,因为在实战中并没有遇到过这种情况,所以今天补一下知识. 首先查询了ssl的概念,通俗来说,如果一个网站没有安装s ...

  7. Web 前端 - 优雅地 Callback 转 Promise :aw

    前言 当今 ES7 标准大行其道,使用 async + await 将异步逻辑同步书写已经普及,但是却有许多旧库或旧代码尚未完全 Promise 化,急需一个小工具去挖去这代码中藓疾. 设计和实现 由 ...

  8. [树形DP]战略游戏

    战 略 游 戏 战略游戏 战略游戏 题目描述 Bob喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的办法.现在他有个问题.他要建立一个古城堡,城堡中的路形成一棵树.他要在这棵树的结点上 ...

  9. 什么是 Ansible - 使用 Ansible 进行配置管理

    [注]本文译自:https://www.edureka.co/blog/what-is-ansible/   Ansible 是一个开源的 IT 配置管理.部署和编排工具.它旨在为各种自动化挑战提供巨 ...

  10. 使用python制作大数据词云

    1 from wordcloud import WordCloud 2 import PIL.Image as image 3 import numpy as np 4 import jieba 5 ...