黑马----JAVA泛型基础
黑马程序员:Java培训、Android培训、iOS培训、.Net培训
JAVA范型-基础
一、泛型的概念
1、实现了参数化类型
2、用于编写可应用于多种类型的代码,即所编写的代码可应用于许多许多的类型。
3、范型容器、范型接口、范型方法都是经典的用法。
二、泛型与多态
1、多态是一种泛化机制。在使用类型说明的地方,使用多态确实具备一定的灵活性。但,多态是受限制的:只能接受基类或其子类(拘泥于单继承体系,使程序受限太多)。而且,在实际编写代码时,只能使用已存在的基类或接口。同时,一旦指明了接口,程序就会要求你的代码必须使用特定接口(方法)。
2、泛型:使我们能够编写比多态更具灵活性、更加通用的代码,它使代码能够适用于“某种不具体类型”,而不是一个具体接口或类。
3、使用泛型机制编写的代码要比那些杂乱地使用Object变量,然后进行强制类型转换具有更好的安全性和可读性。
4、泛型另一个优点:能够在编译时检测错误,而不是在运行时。例如:
JDK1.5前 : public interface Comparable{public int comparaTo(Object 0)}
//编译通过、运行错误
Comparalbe c = new Date(); //Date实现了Comparalbe
c.compareTo(“red”);
JDK1.5:public interface Comparable<T>{public int comparaTo(T 0)}
//编译错误,因为传递给compareTo()的参数必须为Date类型
Comparalbe<Date> c = new Date(); //Date实现了Comparalbe
c.compareTo(“red”);
三、泛型的限制
1、基本类型不能使用作为类型参数。例如:
Comparalbe<int>是错误的,应该是Comparalbe<Integer>。
2、不能使用泛型类型创建实例。例如:
E object = new E();
3、不能使用泛型类型创建数组。例如:
E[] elements = new E[10];
(可以创建一个Object数组,然后将它的类型转换为E[]来规避这个限制)
(E[] elements = (E[]) new Object[10];)
(有编译警告)
4、不允许使用范型类创建泛型数组。例如:
ArrayList<String>[] list = new ArrayList<String>[10];
(可以使用:ArrayList<String>[] list = (ArrayList<String>[])new ArrayList [10];)
(有编译警告)
5、在静态环境下(静态域、静态方法、静态块)不允许类的参数是泛型类型。
public class test<E>{ //类的参数是泛型
private static E o; //静态域
public static void m(E 0){} //静态方法
static{ } //静态块
}
6、异常类不能是泛型的。例如:
public class MyException<T> extends Exception{
}
四、泛型方法(参数化方法)
1、泛型方法可以在泛型类中,也以在非泛型类中。即,是否拥有泛型方法,与其是否是泛型类没有关系。
2、泛型方法使得该方法能够独立于类而产生变化。如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法。
3、泛型方法定义:只需要将泛型参数列表置于返回类型之前。例如:
private <T> void m(T t){}
public static <T> T m(){return t;} //T t
4、泛型方法调用:与普通方法的调用一样。
五、泛型接口和类
1、泛型接口和类的定义:用尖括号括住类型参数,放在接口(类名)后面。例如:
public class Holder<T>{}
public interface Inter<T>{}
2、读作:具有T类型参数的类。
3、泛型接口和类的经典用法:泛型容器。
六、边界(泛型参数类型限定):<T extends BoundingTypeList>
1、T:为界限列表BoundingTypeList的的子类或子接口
2、BoundingTypeList:界限列表至多只能有一个类,或多个接口,并且类必须放在界限列表的第一位。界限列表使用&连接,例如,
BoundingTypeList:class & interfaceA & interfaceB
注:其中,class称为第一边界,interfaceA为第二边界,以此类推。如果没有界限列表,Object为第一边界。
3、泛型类型限定,也称为泛型类型的边界。它使得我们可以在用于泛型的参数类型上设置限制条件,规定了泛型可以应用的类型(这些泛型类型应该满足限制条件)。另一个更重要的效果就是可以按照自己的的边界类型来调用方法,而无界泛型参数调用的方法只是那些可用Object调用的方法(在下一节详解)。
七、泛型翻译:擦除
1、擦除的神秘之处
1)ArrayList<String>和ArrayList<Integer>
//main()
Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1 == c2);
//output
ture
显然,我们都认为ArrayList<String>和ArrayList<Integer>是不同的类型。然而,程序运行的结果显示:ArrayList<String>和ArrayList<Integer>是同一类型。这是因为:在泛型代码内部,无法获得任何有关泛型参数类型的信息(这也是泛型的使用受限的原因之一,例如,不能创建泛型数组)。
2)擦除带来的问题:在使用泛型时,任何具体类型信息都被擦除,而我们只知道在使用一个原生对象(Object)(如果没有使用边界的话),因此我们只能调用的方法只是那些可用Object调用的方法。
class HasF{ public void f(){System.out.println(“HasF”);}}
class Temp<T>{
T obj;
public Temp(T aObj){obj = aObj;}
public void meth(){obj.f();} //compile error
}
//main()
new Temp<HasF>(new HasF()).meth();
这是因为编译器无法将meth()必须能够在obj上调用f()这一需求映射到HasF拥有f()这一事实。为了解决这一问题,我们就需要到泛型边界(泛型类型参数将擦除到它的第一边界,而没有边界则擦除到原生Object)。
class Temp<T extends HasF>{ //边界HasF,可调用所有HasF暴露的方法
T obj;
public Temp(T aObj){obj = aObj;}
public void meth(){obj.f();} //
}
2、泛型类
无论何时定义一个泛型类型,相应的原始类型(raw type)都会被自动提供。原始类型的名字就是删去了类型参数的泛型类型的名字。类型参数T会被擦除(erased),并用第一边界(无限定类型的变量用Object)替换。例如:
//泛型 //原始类型(类型参数擦除)
public class Pair<T>{ public class Pair{
private T frist; private Object frist;
private T second; private Object second;
public T getFrist(){ retrun frist;} public Object getFrist(){ retrun frist;}
public void setSecond(T aSecond){…..} public void
setSecond(Object aSecond){…..}
} }
3、泛型方法
1)也会进行类型擦除,泛型方法的类型参数T会被擦除(erased),并用第一边
界(无限定类型的变量用Object)替换。例如:
public <T extends Comparable> T m(){…….} //泛型方法
public Comparable m(){…….} //擦除后的方法
2)泛型方法擦除带来的问题:与多态冲突
//擦除前
class DateInterval extends Pair<Date>{
public void setSecond(Date aSecond){…..}
}
//擦除后
class DateInterval extends Pair{
public void setSecond(Date aSecond){…..}
}
//与此同时,DateInterval从Pair中继承方法
public void setSecond(Object aSecond){…..}
//显然,DateInterval有两个setSecond()方法,若执行下面语句
DateInterval interval = new DateInterval();
Pair<Date> pair = interval;
pair.setSecond(aDate);
// 对setSecond()的调用是多态的,pair引用了DateInterva对象,我们希望调用
// DateInterval. setSecond()。问题在于类型擦除与多态发生了冲突。解决办法:
//编译器在DateInterval中生成一个桥方法。
public void setSecond(Object aSecond){setSecond((Date)second)}
3)泛型表达式:返回类型被擦除,编译器插入强制类型转换
Pair<Employee> buddies = …..;
Employee buddy = buddies.getFrist();
//对getFrist()的调用是对原始方法getFrist()的调用,然后将返回的Object强制转//换为Employee
黑马----JAVA泛型基础的更多相关文章
- 一个小栗子聊聊JAVA泛型基础
背景 周五本该是愉快的,可是今天花了一个早上查问题,为什么要花一个早上?我把原因总结为两点: 日志信息严重丢失,茫茫代码毫无头绪. 对泛型的认识不够,导致代码出现了BUG. 第一个原因可以通过以后编码 ...
- Java:泛型基础
泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...
- java泛型基础
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类.接口和方法的创建中, 分别称为泛型类.泛型接口.泛型方法. Ja ...
- java 泛型基础问题汇总
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引 ...
- java泛型基础、子类泛型不能转换成父类泛型
参考http://how2j.cn/k/generic/generic-generic/373.html 1.使用泛型的好处:泛型的用法是在容器后面添加<Type>Type可以是类,抽象类 ...
- java泛型基础、子类泛型不能转换成父类泛型--未完待续
参考http://how2j.cn/k/generic/generic-generic/373.html 1.使用泛型的好处:泛型的用法是在容器后面添加<Type>Type可以是类,抽象类 ...
- 使用java泛型设计通用方法
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...
- Java基础教程:泛型基础
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
- Java基础学习总结(83)——Java泛型总结
1. 什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型 ...
随机推荐
- SWM格式稀疏权重矩阵转换为方阵形式全过程分享
在进行空间统计实验过程中,经常涉及到空间权重矩阵的处理,有时候需要将ArcGIS生成的swm格式的权重矩阵转换为形如“0 1”的方阵格式.这里将我的办法整理出来. 1.用如下工具箱生成swm格式的权重 ...
- guava学习--ComparisonChain
转载:https://my.oschina.net/realfighter/blog/349824 在日常的工作中,我们经常需要对两个对象进行比较,以找出其中的异同, Java中提供了compare/ ...
- 无废话SharePoint入门教程三[创建网站集和网站]
一.前言 前两篇文章讲解了什么是SharePoint,并且介绍了在SharePoint中一些常用的概念.但概念终究是概念,我们还是要脚踏实地的去动手实践.下面的文章对于了解SharePoint的人来说 ...
- 微信开发订阅号(ASP.NET MVC4+jquery mobile+AppHarbor发布)
首先应该去微信公众平台注册一个账号,因为我是用的个人,所以只能注册订阅号,然后需要提供身份证照片,这些大家慢慢折腾.然后在微信管理面板中选择高级功能,进入开发者模式. 在服务器配置中需要提供最重要的u ...
- jsp页面往mysql里插入中文后数据库里显示乱码
1.JSP页面乱码 这种乱码的原因是应为没有在页面里指定使用的字符集编码,解决方法:只要在页面开始地方用下面代码指定字符集编码即可,<%@ page contentType="text ...
- java 通过反射获取调用类方法及属性
首先说下反射是什么?反射是Sun公司推出的一组API,此组API位于Java.lang.reflect中 反射的作用是编写工具(例如eclipse),编写框架,当然对于一般的程序,我们不可能用反射来做 ...
- [转]SPICE仿真软件基础(整理)
现在常用的SPICE仿真软件为方便用户使用都提供了较好的用户界面,在用仿真库中的元器件连成原理图后就可以进行仿真(当然要设置必要的仿真参数),但实际上只是用原理图自动产生了SPICE的格式语句,还是要 ...
- 练习sql语句的好去处——http://www.sqlzoo.cn/
sql语句的编写需要按照实际的例子来练习. 如果自己来做准备,需要你自己搭好数据库,建好库和表,还要填入数据,最后自己想出题目和正确答案. 不过,现在我发现了一个好去处,http://www.sqlz ...
- CodeForces 474B E(Contest #1)
题意: 给你一个数n,代表n段区间,接下来有n个数(a1,a2,...an)代表每段区间的长度,第一段区间为[1,a1],第二段区间为[a1+1,a1+a2],...第i段区间为[ai-1+1,ai- ...
- Python3学习(二)-递归函数、高级特性、切片
##import sys ##sys.setrecursionlimit(1000) ###关键字参数(**关键字参数名) ###与可变参数不同的是,关键字参数可以在调用函数时,传入带有参数名的参数, ...