- 浏览: 322608 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (178)
- 程序人生 (9)
- 工作总结 (16)
- 我的功能实现 (8)
- J2SE总结 (8)
- 面试中用到的 (10)
- struts2 (15)
- jsp (4)
- js (21)
- 数据库 (7)
- 数据结构和算法 (3)
- jQuery (18)
- hibernate (3)
- web service (2)
- spring (1)
- mySQL (7)
- 服务器 (1)
- 缓存 (2)
- nginx (1)
- jquery.ui (1)
- 各类标签(Date转 string) (1)
- Raphael (3)
- maven (2)
- 大型分布式网站架构设计 (2)
- linux (1)
- java易犯错误 (1)
- 优化 (4)
最新评论
-
15381049808:
楼主写的很赞 我对中间的批量发送拿过来现在还好用 受益匪浅
java实现邮件抄送,密送,多个附件发送 -
猜猜猜:
你这不是选择了语言之后总是跳到同一个页面吗?比如登录页面,选择 ...
struts2国际化——实例 -
itshu:
struts2国际化——实例 -
itshu:
[flash=200,200][url][img][list] ...
struts2国际化——实例 -
ZP0605:
com.asia.home.cn这个包名好熟悉
struts2拦截器管理日志
[size=medium][/size]
上接《Java 泛型的理解与等价实现》,这个仅仅是泛型的入门。有博友反映泛型很复杂,难以掌握。鉴于此,写一片续集。
实际上泛型可以用得很复杂,复杂到编写代码的人员自己也难以看懂。这往往是对泛型的滥用或者类或接口本身设计不合理导致的。
看来用好泛型还真不容易,为此必须从根源说起。
一、逐渐深入泛型
1、没有任何重构的原始代码:
有两个类如下,要构造两个类的对象,并打印出各自的成员x。
public class StringFoo {
private String x;
public StringFoo(String x) {
this.x = x;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
public class DoubleFoo {
private Double x;
public DoubleFoo(Double x) {
this.x = x;
}
public Double getX() {
return x;
}
public void setX(Double x) {
this.x = x;
}
}
以上的代码是在无聊,就不写如何实现了。
2、对上面的两个类进行重构,写成一个类:
因为上面的类中,成员和方法的逻辑都一样,就是类型不一样,因此考虑重构。Object是所有类的父类,因此可以考虑用Object做为成员类型,这样就可以实现通用了,实际上就是“Object泛型”,暂时这么称呼。
public class ObjectFoo {
private Object x;
public ObjectFoo(Object x) {
this.x = x;
}
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
}
写出Demo方法如下:
public class ObjectFooDemo {
public static void main(String args[]) {
ObjectFoo strFoo = new ObjectFoo("Hello Generics!");
ObjectFoo douFoo = new ObjectFoo(new Double("33"));
ObjectFoo objFoo = new ObjectFoo(new Object());
System.out.println("strFoo.getX="+(String)strFoo.getX());
System.out.println("douFoo.getX="+(Double)douFoo.getX());
System.out.println("objFoo.getX="+(Object)objFoo.getX());
}
}
运行结果如下:
strFoo.getX=Hello Generics!
douFoo.getX=33.0
objFoo.getX=java.lang.Object@19821f
解说:在Java 5之前,为了让类有通用性,往往将参数类型、返回类型设置为Object类型,当获取这些返回类型来使用时候,必须将其“强制”转换为原有的类型或者接口,然后才可以调用对象上的方法。
3、Java5泛型来实现
强制类型转换很麻烦,我还要事先知道各个Object具体类型是什么,才能做出正确转换。否则,要是转换的类型不对,比如将“Hello Generics!”字符串强制转换为Double,那么编译的时候不会报错,可是运行的时候就挂了。那有没有不强制转换的办法----有,改用Java5泛型来实现。
public class GenericsFoo<T> {
private T x;
public GenericsFoo(T x) {
this.x = x;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
}
public class GenericsFooDemo {
public static void main(String args[]){
GenericsFoo<String> strFoo=new GenericsFoo<String>("Hello Generics!");
GenericsFoo<Double> douFoo=new GenericsFoo<Double>(new Double("33"));
GenericsFoo<Object> objFoo=new GenericsFoo<Object>(new Object());
System.out.println("strFoo.getX="+strFoo.getX());
System.out.println("douFoo.getX="+douFoo.getX());
System.out.println("objFoo.getX="+objFoo.getX());
}
}
运行结果:
strFoo.getX=Hello Generics!
douFoo.getX=33.0
objFoo.getX=java.lang.Object@19821f
和使用“Object泛型”方式实现结果的完全一样,但是这个Demo简单多了,里面没有强制类型转换信息。
下面解释一下上面泛型类的语法:
使用<T>来声明一个类型持有者名称,然后就可以把T当作一个类型代表来声明成员、参数和返回值类型。
当然T仅仅是个名字,这个名字可以自行定义。
class GenericsFoo<T> 声明了一个泛型类,这个T没有任何限制,实际上相当于Object类型,实际上相当于 class GenericsFoo<T extends Object>。
与Object泛型类相比,使用泛型所定义的类在声明和构造实例的时候,可以使用“<实际类型>”来一并指定泛型类型持有者的真实类型。类如
GenericsFoo<Double> douFoo=new GenericsFoo<Double>(new Double("33"));
当然,也可以在构造对象的时候不使用尖括号指定泛型类型的真实类型,但是你在使用该对象的时候,就需要强制转换了。比如:GenericsFoo douFoo=new GenericsFoo(new Double("33"));
实际上,当构造对象时不指定类型信息的时候,默认会使用Object类型,这也是要强制转换的原因。
二、泛型的高级应用
1、限制泛型的可用类型
在上面的例子中,由于没有限制class GenericsFoo<T>类型持有者T的范围,实际上这里的限定类型相当于Object,这和“Object泛型”实质是一样的。限制比如我们要限制T为集合接口类型。只需要这么做:
class GenericsFoo<T extends Collection>,这样类中的泛型T只能是Collection接口的实现类,传入非Collection接口编译会出错。
注意:<T extends Collection>这里的限定使用关键字 extends,后面可以是类也可以是接口。但这里的extends已经不是继承的含义了,应该理解为T类型是实现Collection接口的类型,或者T是继承了XX类的类型。
下面继续对上面的例子改进,我只要实现了集合接口的类型:
public class CollectionGenFoo<T extends Collection> {
private T x;
public CollectionGenFoo(T x) {
this.x = x;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
}
实例化的时候可以这么写:
public class CollectionGenFooDemo {
public static void main(String args[]) {
CollectionGenFoo<ArrayList> listFoo = null;
listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
//出错了,不让这么干。
// CollectionGenFoo<Collection> listFoo = null;
// listFoo=new CollectionGenFoo<ArrayList>(new ArrayList());
System.out.println("实例化成功!");
}
}
当前看到的这个写法是可以编译通过,并运行成功。可是注释掉的两行加上就出错了,因为<T extends Collection>这么定义类型的时候,就限定了构造此类实例的时候T是确定的一个类型,这个类型实现了Collection接口,但是实现Collection接口的类很多很多,如果针对每一种都要写出具体的子类类型,那也太麻烦了,我干脆还不如用Object通用一下。别急,泛型针对这种情况还有更好的解决方案,那就是“通配符泛型”。
2、通配符泛型
为了解决类型被限制死了不能动态根据实例来确定的缺点,引入了“通配符泛型”,针对上面的例子,使用通配泛型格式为<? extends Collection>,“?”代表未知类型,这个类型是实现Collection接口。那么上面实现的方式可以写为:
public class CollectionGenFooDemo {
public static void main(String args[]) {
CollectionGenFoo<ArrayList> listFoo = null;
listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
//现在不会出错了
CollectionGenFoo<? extends Collection> listFoo1 = null;
listFoo=new CollectionGenFoo<ArrayList>(new ArrayList());
System.out.println("实例化成功!");
}
}
注意:
1、如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。
2、通配符泛型不单可以向下限制,如<? extends Collection>,还可以向上限制,如<? super Double>,表示类型只能接受Double及其上层父类类型,如Number、Object类型的实例。
3、泛型类定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都泛型类中泛型的使用规则类似。
三、泛型的综合运用实例(代码参考java参考大全,有改动)
public class AvgGen<T extends Number> {
public AvgGen() {
}
public double getAvg(T[] arr) {
double sum = 0.0;
for (int i = 0; i < arr.length; i++) {
sum = sum + arr[i].doubleValue();
}
return sum / arr.length;
}
public static void main(String[] args) {
//整形数组求均值
System.out.println("整形数组{1, 3}求均值:");
Integer[] intArr = {1, 3};
AvgGen<Integer> intObj = new AvgGen<Integer>();
double intavg = intObj.getAvg(intArr);
System.out.println(intavg);
System.out.println();
//浮点型数组求均值
System.out.println("浮点型数组{1.1f,2.9f}求均值:");
Float[] fArr = {1.1f, 2.9f};
AvgGen<Float> fObj = new AvgGen<Float>();
double favg = fObj.getAvg(fArr);
System.out.println(favg);
}
}
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-9-18
* Time: 11:08:14
* 使用通配符泛型参数:泛型参数是可变的,可在运行时来确定。
*/
public class AvgCompGen<T extends Number> {
private T[] arr;
/**
* 构造函数
* @param arr
*/
public AvgCompGen(T[] arr) {
this.arr = arr;
}
/**
* 求数组均值
* @return 数组均值
*/
public double getAvg() {
double sum = 0.0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i].doubleValue();
}
return sum / arr.length;
}
/**
* 比较数组均值是否相等(使用通配符泛型参数)
* AvgCompGen<?>表示可以匹配任意的AvgCompGen对象,有点类似Object
*
* @param x 目标对象
* @return 均值是否相等
*/
public boolean sameAvg(AvgCompGen<?> x) {
if (getAvg() == x.getAvg()) return true;
return false;
}
/**
* 主函数:用来测试
* @param args
*/
public static void main(String[] args) {
//创建参数为Integer类型泛型对象
Integer[] intArr = {1, 3};
AvgCompGen<Integer> intObj = new AvgCompGen<Integer>(intArr);
System.out.println("intObj的平均值="+intObj.getAvg());
//创建参数为Double类型泛型对象
Double[] douArr = {1.0, 3.0};
AvgCompGen<Double> douObj = new AvgCompGen<Double>(douArr);
System.out.println("douObj的平均值="+douObj.getAvg());
//创建参数为Float类型泛型对象
Float[] fltArr = {0.8f, 3.2f};
AvgCompGen<Float> fltObj = new AvgCompGen<Float>(fltArr);
System.out.println("fltObj的平均值="+fltObj.getAvg());
//两两比较对象的均值是否相等
if (intObj.sameAvg(douObj))
System.out.println("intArr与douArr的值相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " douObj的均值=" + douObj.getAvg());
else
System.out.println("intArr与douArr的值不相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " douObj的均值=" + douObj.getAvg());
if (intObj.sameAvg(fltObj))
System.out.println("intArr与fltObj的值相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
else
System.out.println("intArr与fltObj的值不相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
if (douObj.sameAvg(fltObj))
System.out.println("douObj与fltObj的值相等,结果为:" + " douObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
else
System.out.println("douObj与fltObj的值不相等,结果为:" + " douObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
}
}
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-9-18
* Time: 16:09:37
* 三种坐标,用泛型实现坐标打印
*/
public class TwoD {
int x, y;
public TwoD(int x, int y) {
this.x = x;
this.y = y;
}
}
class ThreeD extends TwoD {
int z;
public ThreeD(int x, int y, int z) {
super(x, y);
this.z = z;
}
}
class FourD extends ThreeD {
int t;
public FourD(int x, int y, int z, int t) {
super(x, y, z);
this.t = t;
}
}
/**
* 存放泛型坐标的(数据结构)类
*/
class Coords<T extends TwoD> {
T[] coords;
public Coords(T[] coords) {
this.coords = coords;
}
}
/**
* 工具类--打印泛型数据
* 并给出一个测试方法
*/
class BoundeWildcard {
static void showXY(Coords<?> c) {
System.out.println("X Y Coordinates:");
for (int i = 0; i < c.coords.length; i++) {
System.out.println(c.coords[i].x + " " + c.coords[i].y);
}
System.out.println();
}
static void showXYZ(Coords<? extends ThreeD> c) {
System.out.println("X Y Z Coordinates:");
for (int i = 0; i < c.coords.length; i++) {
System.out.println(c.coords[i].x + " " + c.coords[i].y + " " + c.coords[i].z);
}
System.out.println();
}
static void showAll(Coords<? extends FourD> c) {
System.out.println("X Y Z Coordinates:");
for (int i = 0; i < c.coords.length; i++) {
System.out.println(c.coords[i].x + " " + c.coords[i].y + " " + c.coords[i].z + " " + c.coords[i].t);
}
System.out.println();
}
public static void main(String args[]) {
TwoD td[] = {
new TwoD(0, 0),
new TwoD(7, 9),
new TwoD(18, 4),
new TwoD(-1, -23)
};
Coords<TwoD> tdlocs = new Coords<TwoD>(td);
System.out.println("Contents of tdlocs.");
showXY(tdlocs);
FourD fd[] = {
new FourD(1, 2, 3, 4),
new FourD(6, 8, 14,,
new FourD(22, 9, 4, 9),
new FourD(3, -2, -23, 17)
};
Coords<FourD> fdlocs = new Coords<FourD>(fd);
System.out.println("Contents of fdlocs.");
showXY(fdlocs);
showXYZ(fdlocs);
showAll(fdlocs);
}
}
注意:多个泛型类、接口,接口、类继承,这种设计方式往往会导致泛型很复杂,程序的可读性急剧下降,程序中应该兼顾代码的可读性。
总结:泛型其实就是一个类型的参数化,没有它程序照样写!把这句话记心里。有两层含义:一是泛型的实质,二是要知其然还要知其所以然。泛型不可怕,泛型的设计也从开发者角度出发的,使用得当会大大提高代码的安全性和简洁性。
本文出自 “熔 岩” 博客,转载请与作者联系!
本文出自 51CTO.COM技术博客
引用
Java 5泛型深入研究
上接《Java 泛型的理解与等价实现》,这个仅仅是泛型的入门。有博友反映泛型很复杂,难以掌握。鉴于此,写一片续集。
实际上泛型可以用得很复杂,复杂到编写代码的人员自己也难以看懂。这往往是对泛型的滥用或者类或接口本身设计不合理导致的。
看来用好泛型还真不容易,为此必须从根源说起。
一、逐渐深入泛型
1、没有任何重构的原始代码:
有两个类如下,要构造两个类的对象,并打印出各自的成员x。
public class StringFoo {
private String x;
public StringFoo(String x) {
this.x = x;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
public class DoubleFoo {
private Double x;
public DoubleFoo(Double x) {
this.x = x;
}
public Double getX() {
return x;
}
public void setX(Double x) {
this.x = x;
}
}
以上的代码是在无聊,就不写如何实现了。
2、对上面的两个类进行重构,写成一个类:
因为上面的类中,成员和方法的逻辑都一样,就是类型不一样,因此考虑重构。Object是所有类的父类,因此可以考虑用Object做为成员类型,这样就可以实现通用了,实际上就是“Object泛型”,暂时这么称呼。
public class ObjectFoo {
private Object x;
public ObjectFoo(Object x) {
this.x = x;
}
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
}
写出Demo方法如下:
public class ObjectFooDemo {
public static void main(String args[]) {
ObjectFoo strFoo = new ObjectFoo("Hello Generics!");
ObjectFoo douFoo = new ObjectFoo(new Double("33"));
ObjectFoo objFoo = new ObjectFoo(new Object());
System.out.println("strFoo.getX="+(String)strFoo.getX());
System.out.println("douFoo.getX="+(Double)douFoo.getX());
System.out.println("objFoo.getX="+(Object)objFoo.getX());
}
}
运行结果如下:
strFoo.getX=Hello Generics!
douFoo.getX=33.0
objFoo.getX=java.lang.Object@19821f
解说:在Java 5之前,为了让类有通用性,往往将参数类型、返回类型设置为Object类型,当获取这些返回类型来使用时候,必须将其“强制”转换为原有的类型或者接口,然后才可以调用对象上的方法。
3、Java5泛型来实现
强制类型转换很麻烦,我还要事先知道各个Object具体类型是什么,才能做出正确转换。否则,要是转换的类型不对,比如将“Hello Generics!”字符串强制转换为Double,那么编译的时候不会报错,可是运行的时候就挂了。那有没有不强制转换的办法----有,改用Java5泛型来实现。
public class GenericsFoo<T> {
private T x;
public GenericsFoo(T x) {
this.x = x;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
}
public class GenericsFooDemo {
public static void main(String args[]){
GenericsFoo<String> strFoo=new GenericsFoo<String>("Hello Generics!");
GenericsFoo<Double> douFoo=new GenericsFoo<Double>(new Double("33"));
GenericsFoo<Object> objFoo=new GenericsFoo<Object>(new Object());
System.out.println("strFoo.getX="+strFoo.getX());
System.out.println("douFoo.getX="+douFoo.getX());
System.out.println("objFoo.getX="+objFoo.getX());
}
}
运行结果:
strFoo.getX=Hello Generics!
douFoo.getX=33.0
objFoo.getX=java.lang.Object@19821f
和使用“Object泛型”方式实现结果的完全一样,但是这个Demo简单多了,里面没有强制类型转换信息。
下面解释一下上面泛型类的语法:
使用<T>来声明一个类型持有者名称,然后就可以把T当作一个类型代表来声明成员、参数和返回值类型。
当然T仅仅是个名字,这个名字可以自行定义。
class GenericsFoo<T> 声明了一个泛型类,这个T没有任何限制,实际上相当于Object类型,实际上相当于 class GenericsFoo<T extends Object>。
与Object泛型类相比,使用泛型所定义的类在声明和构造实例的时候,可以使用“<实际类型>”来一并指定泛型类型持有者的真实类型。类如
GenericsFoo<Double> douFoo=new GenericsFoo<Double>(new Double("33"));
当然,也可以在构造对象的时候不使用尖括号指定泛型类型的真实类型,但是你在使用该对象的时候,就需要强制转换了。比如:GenericsFoo douFoo=new GenericsFoo(new Double("33"));
实际上,当构造对象时不指定类型信息的时候,默认会使用Object类型,这也是要强制转换的原因。
二、泛型的高级应用
1、限制泛型的可用类型
在上面的例子中,由于没有限制class GenericsFoo<T>类型持有者T的范围,实际上这里的限定类型相当于Object,这和“Object泛型”实质是一样的。限制比如我们要限制T为集合接口类型。只需要这么做:
class GenericsFoo<T extends Collection>,这样类中的泛型T只能是Collection接口的实现类,传入非Collection接口编译会出错。
注意:<T extends Collection>这里的限定使用关键字 extends,后面可以是类也可以是接口。但这里的extends已经不是继承的含义了,应该理解为T类型是实现Collection接口的类型,或者T是继承了XX类的类型。
下面继续对上面的例子改进,我只要实现了集合接口的类型:
public class CollectionGenFoo<T extends Collection> {
private T x;
public CollectionGenFoo(T x) {
this.x = x;
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
}
实例化的时候可以这么写:
public class CollectionGenFooDemo {
public static void main(String args[]) {
CollectionGenFoo<ArrayList> listFoo = null;
listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
//出错了,不让这么干。
// CollectionGenFoo<Collection> listFoo = null;
// listFoo=new CollectionGenFoo<ArrayList>(new ArrayList());
System.out.println("实例化成功!");
}
}
当前看到的这个写法是可以编译通过,并运行成功。可是注释掉的两行加上就出错了,因为<T extends Collection>这么定义类型的时候,就限定了构造此类实例的时候T是确定的一个类型,这个类型实现了Collection接口,但是实现Collection接口的类很多很多,如果针对每一种都要写出具体的子类类型,那也太麻烦了,我干脆还不如用Object通用一下。别急,泛型针对这种情况还有更好的解决方案,那就是“通配符泛型”。
2、通配符泛型
为了解决类型被限制死了不能动态根据实例来确定的缺点,引入了“通配符泛型”,针对上面的例子,使用通配泛型格式为<? extends Collection>,“?”代表未知类型,这个类型是实现Collection接口。那么上面实现的方式可以写为:
public class CollectionGenFooDemo {
public static void main(String args[]) {
CollectionGenFoo<ArrayList> listFoo = null;
listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
//现在不会出错了
CollectionGenFoo<? extends Collection> listFoo1 = null;
listFoo=new CollectionGenFoo<ArrayList>(new ArrayList());
System.out.println("实例化成功!");
}
}
注意:
1、如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。
2、通配符泛型不单可以向下限制,如<? extends Collection>,还可以向上限制,如<? super Double>,表示类型只能接受Double及其上层父类类型,如Number、Object类型的实例。
3、泛型类定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都泛型类中泛型的使用规则类似。
三、泛型的综合运用实例(代码参考java参考大全,有改动)
public class AvgGen<T extends Number> {
public AvgGen() {
}
public double getAvg(T[] arr) {
double sum = 0.0;
for (int i = 0; i < arr.length; i++) {
sum = sum + arr[i].doubleValue();
}
return sum / arr.length;
}
public static void main(String[] args) {
//整形数组求均值
System.out.println("整形数组{1, 3}求均值:");
Integer[] intArr = {1, 3};
AvgGen<Integer> intObj = new AvgGen<Integer>();
double intavg = intObj.getAvg(intArr);
System.out.println(intavg);
System.out.println();
//浮点型数组求均值
System.out.println("浮点型数组{1.1f,2.9f}求均值:");
Float[] fArr = {1.1f, 2.9f};
AvgGen<Float> fObj = new AvgGen<Float>();
double favg = fObj.getAvg(fArr);
System.out.println(favg);
}
}
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-9-18
* Time: 11:08:14
* 使用通配符泛型参数:泛型参数是可变的,可在运行时来确定。
*/
public class AvgCompGen<T extends Number> {
private T[] arr;
/**
* 构造函数
* @param arr
*/
public AvgCompGen(T[] arr) {
this.arr = arr;
}
/**
* 求数组均值
* @return 数组均值
*/
public double getAvg() {
double sum = 0.0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i].doubleValue();
}
return sum / arr.length;
}
/**
* 比较数组均值是否相等(使用通配符泛型参数)
* AvgCompGen<?>表示可以匹配任意的AvgCompGen对象,有点类似Object
*
* @param x 目标对象
* @return 均值是否相等
*/
public boolean sameAvg(AvgCompGen<?> x) {
if (getAvg() == x.getAvg()) return true;
return false;
}
/**
* 主函数:用来测试
* @param args
*/
public static void main(String[] args) {
//创建参数为Integer类型泛型对象
Integer[] intArr = {1, 3};
AvgCompGen<Integer> intObj = new AvgCompGen<Integer>(intArr);
System.out.println("intObj的平均值="+intObj.getAvg());
//创建参数为Double类型泛型对象
Double[] douArr = {1.0, 3.0};
AvgCompGen<Double> douObj = new AvgCompGen<Double>(douArr);
System.out.println("douObj的平均值="+douObj.getAvg());
//创建参数为Float类型泛型对象
Float[] fltArr = {0.8f, 3.2f};
AvgCompGen<Float> fltObj = new AvgCompGen<Float>(fltArr);
System.out.println("fltObj的平均值="+fltObj.getAvg());
//两两比较对象的均值是否相等
if (intObj.sameAvg(douObj))
System.out.println("intArr与douArr的值相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " douObj的均值=" + douObj.getAvg());
else
System.out.println("intArr与douArr的值不相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " douObj的均值=" + douObj.getAvg());
if (intObj.sameAvg(fltObj))
System.out.println("intArr与fltObj的值相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
else
System.out.println("intArr与fltObj的值不相等,结果为:" + " intObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
if (douObj.sameAvg(fltObj))
System.out.println("douObj与fltObj的值相等,结果为:" + " douObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
else
System.out.println("douObj与fltObj的值不相等,结果为:" + " douObj的均值=" + intObj.getAvg() + " fltObj的均值=" + fltObj.getAvg());
}
}
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-9-18
* Time: 16:09:37
* 三种坐标,用泛型实现坐标打印
*/
public class TwoD {
int x, y;
public TwoD(int x, int y) {
this.x = x;
this.y = y;
}
}
class ThreeD extends TwoD {
int z;
public ThreeD(int x, int y, int z) {
super(x, y);
this.z = z;
}
}
class FourD extends ThreeD {
int t;
public FourD(int x, int y, int z, int t) {
super(x, y, z);
this.t = t;
}
}
/**
* 存放泛型坐标的(数据结构)类
*/
class Coords<T extends TwoD> {
T[] coords;
public Coords(T[] coords) {
this.coords = coords;
}
}
/**
* 工具类--打印泛型数据
* 并给出一个测试方法
*/
class BoundeWildcard {
static void showXY(Coords<?> c) {
System.out.println("X Y Coordinates:");
for (int i = 0; i < c.coords.length; i++) {
System.out.println(c.coords[i].x + " " + c.coords[i].y);
}
System.out.println();
}
static void showXYZ(Coords<? extends ThreeD> c) {
System.out.println("X Y Z Coordinates:");
for (int i = 0; i < c.coords.length; i++) {
System.out.println(c.coords[i].x + " " + c.coords[i].y + " " + c.coords[i].z);
}
System.out.println();
}
static void showAll(Coords<? extends FourD> c) {
System.out.println("X Y Z Coordinates:");
for (int i = 0; i < c.coords.length; i++) {
System.out.println(c.coords[i].x + " " + c.coords[i].y + " " + c.coords[i].z + " " + c.coords[i].t);
}
System.out.println();
}
public static void main(String args[]) {
TwoD td[] = {
new TwoD(0, 0),
new TwoD(7, 9),
new TwoD(18, 4),
new TwoD(-1, -23)
};
Coords<TwoD> tdlocs = new Coords<TwoD>(td);
System.out.println("Contents of tdlocs.");
showXY(tdlocs);
FourD fd[] = {
new FourD(1, 2, 3, 4),
new FourD(6, 8, 14,,
new FourD(22, 9, 4, 9),
new FourD(3, -2, -23, 17)
};
Coords<FourD> fdlocs = new Coords<FourD>(fd);
System.out.println("Contents of fdlocs.");
showXY(fdlocs);
showXYZ(fdlocs);
showAll(fdlocs);
}
}
注意:多个泛型类、接口,接口、类继承,这种设计方式往往会导致泛型很复杂,程序的可读性急剧下降,程序中应该兼顾代码的可读性。
总结:泛型其实就是一个类型的参数化,没有它程序照样写!把这句话记心里。有两层含义:一是泛型的实质,二是要知其然还要知其所以然。泛型不可怕,泛型的设计也从开发者角度出发的,使用得当会大大提高代码的安全性和简洁性。
本文出自 “熔 岩” 博客,转载请与作者联系!
本文出自 51CTO.COM技术博客
发表评论
-
持有对象
2011-12-14 14:34 983Collection: List: Ar ... -
泛型1————弄懂了它就基本上会用泛型了
2011-07-26 14:11 849[size=medium][/size] 引用. ... -
追MM的23种设计模式
2011-07-26 11:47 784引用1、FACTORY?追MM少不了请吃饭了,麦当劳的鸡翅 ... -
IO流——精解
2011-07-26 11:00 633[size=medium][/size] 引用一 ... -
java多线程
2011-07-13 18:08 1036这几天不断添加新内容,给个大概的提纲吧,方面朋友们阅读,各部分 ... -
文件、文件夹的操作
2011-07-13 11:19 921import java.io.*; p ... -
容器总结
2010-11-26 16:02 8041: /** * * @author zhuty ...
相关推荐
Java中的泛型(csdn)————程序
Java 实现泛型List的源码,基本实现了List接口的全部所有方法。欢迎大家发表自己的观点和建议。
java5泛型新特性 pdf,自己看不解释!
2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip...
java泛型深入.pdf
Java Generics and Collections 英文版,详细描述java 泛型技术
实际上泛型可以用得很复杂,复杂到编写代码的人员自己也难以看懂。这往往是对泛型的滥用或者类或接口本身设计不合理导致的。 看来用好泛型还真不容易,为此必须从根源说起
Java泛型编程指南.pdf 此文章译自SUN的泛型编程指南
java 继承泛型类示例 java 继承泛型类示例 java 继承泛型类示例
这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...
java 泛型类的类型识别示例 java 泛型类的类型识别示例 java 泛型类的类型识别示例
Java1.5泛型指南中文版
java 一个关于泛型的简单例子 java 一个关于泛型的简单例子 java 一个关于泛型的简单例子
在Java中运用反射+泛型,实现数据库的动态增删改查等功能,可以是Mysql, 也可以是SQL Server,oracle 也行。本代码是支持SQL Server和oracle的。
java 使用泛型,优化重复多余代码.
Java源码泛型类的继承应用.rar
1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1....
关于java的泛型.doc 关于java的泛型.doc
深入理解java泛型,包括类名泛型的定义,方法泛型定义,泛型的返回