【Java心得总结三】Java泛型上——初识泛型
一、函数参数与泛型比较
泛型(generics),从字面的意思理解就是泛化的类型,即参数化类型。泛型的作用是什么,这里与函数参数做一个比较:
无参数的函数:
public int[] newIntArray(){
return new int[6];
}
函数功能即返回一个大小为6的数组,但是这个函数只能返回固定大小为6的数组,如果想返回不同size的数组则还要重新编写函数。解决方法就是使用函数参数,传入一个代表数组大小的size。
有参数的函数:我们在写一个函数时,往往需要向函数传入一些参数,使得函数具有一定的通用性,完成某些特定的功能,如:
public int[] newIntArray(int size){
return new int[size];
}
这是一个简单的函数,传入参数size,函数会生成相应大小的整型数组返回给我们。但是这里有一个限制,我们只能得到整型的数组,这就大大限制了这个函数的功能和可重用性,那么当我们想要得到一个浮点型数组时又要编写一个非常类似的函数。这里的解决办法就是使用泛型:
有参数且使用泛型的函数
@SuppressWarnings("unchecked")
public static <T> T[] newArray(int size) {
Object array = new Object[size];
return (T[])array;
}
在函数内部我们使用了Object来新建数组,而不是直接用类型参数T直接声明(由于Java泛型的擦除所致,见【Java心得总结四】Java泛型下——万恶的擦除)。通过这个函数,我们就能够得到“任意大小任意类型”的数组。
总结:比较上面三个示例,我们就能理解为什么要有泛型这个概念了。在上面的示例中,每一级的例子都比前一级的例子功能上更加扩展,可重用性更加的高。第一个示例我们只能得到固定大小的数组;为了更加泛化,我们使用参数传入size来得到不同大小的数组;同样为了得到不同类型的数组,我们甚至将类型也作为参数传递入函数,从而得到任意大小任意类型的数组。
综上,我们利用泛型来解耦类或方法与所使用的类型之间的约束,将类型也作为一种参数传入,使得类或方法的可重用性大大提高。
二、泛型类
声明格式:
public class Generics<K, V> {
K k;
V v; public Generics(K k, V v) {
this.k = k;
this.v = v;
}
}
泛型类的声明一般放在类名之后,可以有多个泛型参数,用尖括号括起来形成类型参数列表。
应用:
泛型类应用最广泛的就是我们在平时Java编程中最最常用到的容器类(参见博文【Java心得总结五】Java容器上——容器初探),举一个容器的简单例子:
import java.util.ArrayList;
import java.util.Date;
import java.util.Random; public class RandomList<T> {
private ArrayList<T> storage = new ArrayList<T>();
private Random rand = new Random(new Date().getTime()); public void add(T item) {
storage.add(item);
} public T select() {
return storage.get(rand.nextInt(storage.size()));
}
}
这段代码将原有的ArrayList容器进行了封装,调用select函数会随机的返回一个列表中的元素。
三、泛型接口
声明格式:
public interface Generator<T> {
public T next();
}
同泛型类的声明类似,在接口名之后,用尖括号将所有类型参数括起来。注:这里声明的是一个工厂设计模式常用的生成器接口。
应用:
我们平时编程最常见的泛型接口就是Iterable接口,即迭代器接口(参见博文【Java心得总结五】Java容器上——容器初探),举一个简单的例子:
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Random; public class RandomList<T> implements Iterable<T> {
private ArrayList<T> storage = new ArrayList<T>();
private Random rand = new Random(new Date().getTime()); public void add(T item) {
storage.add(item);
} public T select() {
return storage.get(rand.nextInt(storage.size()));
} /* 实现Iterable接口 */
public Iterator<T> iterator() {
return storage.iterator();
}
}
还是上面泛型类举得容器例子,这次我们给RandomList类部署了Iterable接口,这样我们就可以利用foreach语句对RandomList中的元素进行遍历。
四、泛型方法
声明格式:
public <T> T genericMethod(T t){
return t;
}
泛型方法的声明和泛型类的声明略有不同,它是在返回类型之前用尖括号列出类型参数列表,而函数传入的形参类型可以利用泛型来表示。
应用:
见文章开头的例子。
五、Java泛型的局限性
1.基本类型(【Java心得总结一】Java基本类型和包装类型解析)无法作为类型参数即ArrayList<int>这样的代码是不允许的,如果为我们想要使用必须使用基本类型对应的包装器类型ArrayList<Integer>
2.在泛型代码内部,无法获得任何有关泛型参数类型的信息(见【Java心得总结四】Java泛型下——万恶的擦除)。换句话说,如果传入的类型参数为T,即你在泛型代码内部你不知道T有什么方法,属性,关于T的一切信息都丢失了(类型信息,博文后续)。
3.注,在能够使用泛型方法的时候,尽量避免使整个类泛化。
【Java心得总结三】Java泛型上——初识泛型的更多相关文章
- java 基础知识三 java变量
java 基础知识 三 变量 1.作用域 {} 包围起来的代码 称之为代码块,在块中声明的变量只能在块中使用 2.常量 就是固定不变的量,一旦被定义,它的值就不能再被改变. 3.变量 变量必须在程序 ...
- Java 学习笔记 (三) Java 日期类型
以下内容摘自: https://www.cnblogs.com/crazylqy/p/4172324.html import java.sql.Timestamp; import java.text ...
- java 面向对象(三十五):泛型在继承上的体现
泛型在继承上的体现: /* 1. 泛型在继承方面的体现 虽然类A是类B的父类,但是G<A> 和G<B>二者不具备子父类关系,二者是并列关系. 补充:类A是类B的父类,A< ...
- java 面向对象(三十四):泛型三 自定义泛型类、泛型接口、泛型方法
1.举例: [Order.java] public class Order<T> { String orderName; int orderId; //类的内部结构就可以使用类的泛型 T ...
- java 面向对象(三十六):泛型五 通配符
1.通配符的使用 /* 通配符的使用 通配符:? 类A是类B的父类,G<A>和G<B>是没关系的,二者共同的父类是:G<?> */ @Test public voi ...
- java 面向对象(三十二):泛型一 泛型的理解
1.泛型的概念所谓泛型,就是允许在定义类.接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型.这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量.创建对象时确定 ...
- Java web 实验三部分资料上传
花好月圆系列 貂蝉 黄月英 孙尚香 甄姬 标准包 魏 曹操 司马懿 郭嘉 甄姬 张辽 许褚 夏侯惇 蜀 刘备 关羽 张飞 诸葛亮 黄月英 赵云 马超 吴 孙权 孙尚香 周瑜 大乔 甘宁 吕蒙 群 吕布 ...
- java提高篇(三)-----java的四舍五入
Java小事非小事!!!!!!!!!!!! 四舍五入是我们小学的数学问题,这个问题对于我们程序猿来说就类似于1到10的加减乘除那么简单了.在讲解之间我们先看如下一个经典的案例: public stat ...
- Java学习笔记三:Java的变量、常量、变量的类型及使用规则
Java的变量.常量.变量的类型及使用规则 每一种语言都有一些具有特殊用途的词,Java也不例外,它们被称为关键字.关键字对 Java 的编译器有着特殊的意义. 一:Java中的关键字: 注:Java ...
随机推荐
- 【hihoCoder】1036 Trie图
题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...
- C++迪杰斯特拉算法求最短路径
一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...
- 如何用js得到当前页面的url信息方法(JS获取当前网址信息)
设置或获取对象指定的文件名或路径. alert(window.location.pathname) 设置或获取整个 URL 为字符串. alert(window.location.href); 设置或 ...
- java实现全排列
前天上午的面试遇到了一个用java实现一串数字的全排列的题,想来想去用递归最方便,可是没有在规定的时间内完成555,今天上午有空便继续写,以下是完成后的代码: import java.util.Arr ...
- PHP如何使用GeoIP数据库
1.首先下载GeoIP的IP库.参考<利用GeoIP数据库及API进行地理定位查询>.下载后解压,得到一个GeoIP.dat文件 2.新建一个文件geoip.inc.内容为 <?ph ...
- 初识Windows程序
首先,我们创建第一个Windows程序,一共分为4个步骤: 1.打开Visual Studio开发工具 2.选择"文件"→"新建"→"项目" ...
- 第一章-第十四题(Hello world程序)
题目:请找一个同学结对 (参看本书结对编程的内容),两人共同工作 (不能分开干活),从上面的列表中选取两个平台,在每个平台上,写一个最简单的 "Hello World" 类型的程序 ...
- ASP.NET Aries 开源开发框架:开发指南(一)
前言: 上周开源了Aries开发框架后,好多朋友都Download了源码,在运行过程里,有一些共性的问题会问到. 所以本篇打算写一下简单的开发指南,照顾一下不是太看的懂源码的同学,同时也会讲解一下框架 ...
- 拥抱.NET Core,学习.NET Core的基础知识补遗
前言 .NET Core的新特性之一就是跨平台,但由于对之前框架的兼容导致编写一个.NET Core类库变得相当复杂,主要体现为相当多的框架目标和支持平台,今天我们就对.NET Core的跨平台特性进 ...
- [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)
[.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...