java泛型使用
- 泛型的解释
现在感觉泛型是一个值得学习的地方,就抽出时间来学习和总结一下泛型的使用。
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
泛型是一种把类型的明确工作推迟到创建对象或者调用方法的时候才去明确的特殊类型。
注意:类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
- 泛型出现的原因
早期的时候,使用Object来代表任意类型。但是这样在向上转型的是没有问题的,但是在向下转型的时候存在类型转换的问题,这样的程序其实是不安全的。所以Java在JDK5之后提供了泛型来解决这个问题。
使用泛型的典型例子,是在集合中的泛型使用。
在使用泛型前,存入集合中的元素可以是任何类型的,当从集合中取出时,所有的元素都是Object类型,需要进行向下的强制类型转换,转换到特定的类型。
泛型的思想就是由程序员指定类型,这样集合就只能容纳该类型的元素。
- 实例分析
在JDK1.5之前,Java泛型程序设计是用继承来实现的。因为Object类是所用类的基类,所以只需要维持一个Object类型的引用即可。就比如ArrayList只维护一个Object引用的数组:
public class ArrayList//JDK1.5之前的
{
public Object get(int i){......}
public void add(Object o){......}
......
private Object[] elementData;
}
- 这样会有两个问题:
1、没有错误检查,可以向数组列表中添加类的对象
2、在取元素的时候,需要进行强制类型转换。这样,很容易发生错误,比如:
/**jdk1.5之前的写法,容易出问题*/
ArrayList arrayList1=new ArrayList();
arrayList1.add(1);
arrayList1.add(1L);
arrayList1.add("asa");
int i=(Integer) arrayList1.get(1);//因为不知道取出来的值的类型,类型转换的时候容易出错
- 这里的第一个元素是一个长整型,而你以为是整形,所以在强转的时候发生了错误。
所以。在JDK1.5之后,加入了泛型来解决类似的问题。例如在ArrayList中使用泛型:
/** jdk1.5之后加入泛型*/
ArrayList<String> arrayList2=new ArrayList<String>(); //限定数组列表中的类型
// arrayList2.add(1); //因为限定了类型,所以不能添加整形
// arrayList2.add(1L);//因为限定了类型,所以不能添加整长形
arrayList2.add("asa");//只能添加字符串
String str=arrayList2.get(0);//因为知道取出来的值的类型,所以不需要进行强制类型转换
还要明白的是,泛型特性是向前兼容的。尽管 JDK 5.0 的标准类库中的许多类,比如集合框架,都已经泛型化了,但是使用集合类(比如 HashMap 和 ArrayList)的现有代码可以继续不加修改地在 JDK 1.5 中工作。当然,没有利用泛型的现有代码将不会赢得泛型的类型安全的好处。
一、泛型类(注意:一旦在类上声明泛型,在类里面所有非静态成员上都可以使用)
格式:public class 类名<参数类型,...>{} 当然这里<>里面也可以使用多个不同参数类型例如:public class User<T,E>{}
注意:类型变量使用大写形式,且比较短,这是很常见的。在Java库中,使用变量E表示集合的元素类型,K和V分别表示关键字与值的类型。(需要时还可以用临近的字母U和S)表示“任意类型”。
public class ObjectTool<T>
{
private T obj; public void setObj(T obj) {
this.obj = obj;
} public T getObj() {
return obj;
}
} public static void main(String[] args) {
ObjectTool<String> obj = new ObjectTool<>();
obj.setObj("Hello World.");
System.out.println(obj.getObj());
}
二、泛型方法
格式:public <T> 返回值 方法名(T a){}
public class ObjectTool {
public <E> void show(E s)
{
System.out.println(s);
}
}
public <E> void show(E s)
{
System.out.println(s);
} public static void main(String[] args) {
ObjectTool obj = new ObjectTool();
obj.show("Hello world.");
obj.show(120);
}
- 方法上的泛型和类上的泛型很像,唯一不同的是类型的作用域不同
三、泛型通配符
<?>:类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List<String>,List<Integer> 等所有List<具体类型实参>的父类。
//泛型如果明确的写的时候,前后类型必须一致
Collection<Object> c1 = new ArrayList<Object>();
Collection<Object> c2 = new ArrayList<Animal>(); //报错
Collection<Object> c3 = new ArrayList<Dog>(); //报错 //?表示任意类型都是可以的
Collection<?> c4 = new ArrayList<Object>();
Collection<?> c5 = new ArrayList<Animal>();
Collection<?> c6 = new ArrayList<Dog>();
<? extends E>:向下限定,只能是E及其子类
Collection<? extends Animal> c1 = new ArrayList<Object>(); //报错
Collection<? extends Animal> c2 = new ArrayList<Animal>();
Collection<? extends Animal> c3 = new ArrayList<Dog>();
Collection<? extends Animal> c4 = new ArrayList<Cat>();
<? super E>:向上限定,只能是E及其父类
Collection<? super Animal> c1 = new ArrayList<Object>();
Collection<? super Animal> c2 = new ArrayList<Animal>();
Collection<? super Animal> c3 = new ArrayList<Dog>(); //报错
Collection<? super Animal> c4 = new ArrayList<Cat>(); //报错
四、继承泛型类别
父类:
public class Parent<T1,T2>
{
private T1 foo1;
private T2 foo2; public T1 getFoo1()
{
return foo1;
}
public void setFoo1(T1 foo1)
{
this.foo1 = foo1;
}
public T2 getFoo2()
{
return foo2;
}
public void setFoo2(T2 foo2)
{
this.foo2 = foo2;
} }
子类:
public class Child<T1, T2, T3> extends Parent<T1, T2>
{
private T3 foo3; public T3 getFoo3()
{
return foo3;
} public void setFoo3(T3 foo3)
{
this.foo3 = foo3;
} }
五、实现泛型接口
泛型接口
public interface ParentInterface<T1,T2>
{
public void setFoo1(T1 foo1);
public void setFoo2(T2 foo2);
public T1 getFoo1();
public T2 getFoo2(); }
子类实现泛型接口:
public class ChildClass<T1,T2> implements ParentInterface<T1, T2>
{
private T1 foo1;
private T2 foo2; @Override
public void setFoo1(T1 foo1)
{
this.foo1 = foo1; }
@Override
public void setFoo2(T2 foo2)
{
this.foo2 = foo2;
}
@Override
public T1 getFoo1()
{
return this.foo1;
}
@Override
public T2 getFoo2()
{
return this.foo2;
} }
还可以在实现接口的时候定义类型:
interface Show<T,U>{
void show(T t,U u);
} class ShowTest implements Show<String,Date>{
@Override
public void show(String str,Date date) {
System.out.println(str);
System.out.println(date);
}
}
测试一下:
public static void main(String[] args) throws ClassNotFoundException {
ShowTest showTest=new ShowTest();
showTest.show("Hello",new Date());
}
不允许使用泛型的地方
public class GenericsExample<T>
{
private static T member; //This is not allowed
}
public class GenericsExample<T>
{
public GenericsExample(){
new T();
}
}
final List<int> ids = new ArrayList<>(); //不允许
final List<Integer> ids = new ArrayList<>(); //允许
// 引起编译错误
public class GenericException<T> extends Exception {}
java泛型使用的更多相关文章
- Java泛型的历史
为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...
- 浅析Java 泛型
泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...
- Java:泛型基础
泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...
- java泛型基础
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类.接口和方法的创建中, 分别称为泛型类.泛型接口.泛型方法. Ja ...
- 使用java泛型设计通用方法
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...
- 关于Java泛型的使用
在目前我遇到的java项目中,泛型应用的最多的就属集合了.当要从数据库取出多个对象或者说是多条记录时,往往都要使用集合,那么为什么这么使用,或者使用时有什么要注意的地方,请关注以下内容. 感谢Wind ...
- 初识java泛型
1 协变数组类型(covariant array type) 数组的协变性: if A IS-A B then A[] IS-A B[] 也就是说,java中的数组兼容,一个类型的数组兼容他的子类类型 ...
- 【Java心得总结四】Java泛型下——万恶的擦除
一.万恶的擦除 我在自己总结的[Java心得总结三]Java泛型上——初识泛型这篇博文中提到了Java中对泛型擦除的问题,考虑下面代码: import java.util.*; public clas ...
- 【Java心得总结三】Java泛型上——初识泛型
一.函数参数与泛型比较 泛型(generics),从字面的意思理解就是泛化的类型,即参数化类型.泛型的作用是什么,这里与函数参数做一个比较: 无参数的函数: public int[] newIntAr ...
- 初识Java泛型以及桥接方法
泛型的由来 在编写程序时,可能会有这样的需求:容器类,比如java中常见的list等.为了使容器可以保存多种类型的数据,需要编写多种容器类,每一个容器类中规定好了可以操作的数据类型.此时可能会有Int ...
随机推荐
- “全栈2019”Java第八章:IntelliJ IDEA设置注释不显示在行首
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- kali linux之拒绝服务攻击工具
hping3 几乎可以定制发送任何TCP/IP数据包,用于测试FW,端口扫描,性能测试 -c - 计数包计数 -i - interval wait(uX表示X微秒,例如-i u1000) ...
- TCP和UDP的最完整的区别【转】
来源:https://blog.csdn.net/li_ning_/article/details/52117463 TCP UDPTCP与UDP基本区别 1.基于连接与无连接 2.TCP要求系统 ...
- 北航软院2015级C#期末考试部分考题讲解
洗洗睡了吧,我怎么知道明天的考试题目! 或者 你明年补考可以过来看看:) 晚安.
- Eclipse中的常见设置
本文将移到下面的博客维护: 新的博客网址 当新建一个workspace时,习惯做下面的设置: 1. 在eclipse中,默认的Text file encoding是GBK(操作系统是中文简体):如果操 ...
- angular5给懒加载模块添加loading
在根组件的构造函数中直接执行: this.router.events.subscribe(event=>{ if(event instanceof RouteConfigLoadEnd) { t ...
- 1095. Maximum Swap —— Weekly Challenge
题目限定输入是[0, 10^8],因而不用考虑负数或者越界情况,算是减小了难度. public class Solution { /** * @param num: a non-negative in ...
- 06-oracle 通用函数
--nvl(数字|列名,默认值) 数字或列的值为null显示为0,不为null时显示原值 --nvl2(comm,comm,0)如果comm不为null则显示comm,为null则显示0 --null ...
- (转)tune2fs命令详解
tune2fs命令详解(原创) 原文:http://czmmiao.iteye.com/blog/1749232 tune2fs简介 tune2fs是调整和查看ext2/ext3文件系统的文件系统参数 ...
- 改修jquery支持cmd规范的seajs
手动包装jquery1.10.2,firebug说$没有定义 define(function (require, exports, module) {//jquery源码module.exports= ...