java泛型基础详解

问题: 要求设计一个坐标类:(x,y), 可以同时满足三种类型的数据:
1. int型,x=10,y=100;
2. float型,x = 10.3, y = 50.2;
3. String型,x = "东经180度",y= "北纬210度";
分析:
这个类可以同时处理三种数据类型,为保证程序的正确性,最好采用Object类完成,因为Object可以接收任意的引用数据类型;
原理:
数字-----》自动装箱成为包装类----------》为object类接收;
String---》 Object类接收;
jdk1.5之前:如下实现: 

package com.udast; 

class Point 

{ 

private Object x; // 用Object 去接收所有的数据类型 

private Object y; 

// 现实现int型: 

public Point(Object x, Object y) 

{ 

this.x = x; // 设置坐标 

this.y = y; 

} 

public Object getX() // yong Object accept the return 

{ 

return this.x; 

} 

public Object getY() 

{ 

return this.y; 

} 

} 

public class PointDemo 

{ 

public static void main(String[] args) 

{ 

int ix = 10; 

int iy = 502; 

Point point = new Point(ix, iy); // int--> Integer --> Object 

// 这是jdk1.5前 

int x = (Integer)point.getX(); // 存在不安全因素,因为Object的转型 

int y = (Integer)point.getY(); // 可以是任意类型; 

System.out.println("The point is: " + "(" + x + ", " + y + ")"); 

float fx = 10.3f; 

float fy = 50.2f; 

Point point1 = new Point(fx, fy); 

float x1 = (Float)point1.getX(); 

float y1 = (Float)point1.getY(); 

System.out.println("The point is: " + "(" + x1 + ", " + y1 + ")"); 

String sx = "东经180度"; 

String sy = "北纬21度"; 

Point point2 = new Point(sx, sy); 

String x2 = (String)point2.getX(); 

String y2 = (String)point2.getY(); 

System.out.println("The point is: " + "(" + x2 + ", " + y2 + ")"); 

} 

} 
------------------------jdk1.5后,出现了泛型; 

package com.udast; 

class Point<T> // T 是一个任意类型,在类实例化时才确定! 

{ 

private T x; // 用T 去接收所有的数据类型 

private T y; 

// 现实现int型: 

public Point(T x, T y) 

{ 

this.x = x; // 设置坐标 

this.y = y; 

} 

public T getX() // yong T accept the return 

{ 

return this.x; 

} 

public T getY() 

{ 

return this.y; 

} 

} 

public class PointDemo 

{ 

public static void main(String[] args) 

{ 

int ix = 10; 

int iy = 502; // 实例化时确定属性的类型,这样具有实时的类型安全性; 

Point<Integer> point = new Point<Integer>(ix, iy); // T--> Integer 

// 这是jdk1.5后 

int x = point.getX(); // 不再用转型 

int y = point.getY(); // 

System.out.println("The point is: " + "(" + x + ", " + y + ")"); 

float fx = 10.3f; 

float fy = 50.2f; 

Point<Object> point1 = new Point<Object>(fx, fy); // 泛型擦除的无警告格式,T-->Object 

float x1 = (Float)point1.getX(); // 和不用泛型一样,需要向下转型; 

float y1 = (Float)point1.getY(); 

System.out.println("The point is: " + "(" + x1 + ", " + y1 + ")"); 

String sx = "东经180度"; 

String sy = "北纬21度"; 

Point<String> point2 = new Point<String>(sx, sy); 

String x2 = point2.getX(); 

String y2 = point2.getY(); 

System.out.println("The point is: " + "(" + x2 + ", " + y2 + ")"); 

} 

} 

/* 

class "className"<T> , T 是一个类类型; 也可以有任意多个T, 

class "className"<T,A,B>, 

泛型可以提供简洁,和安全性; 

泛型可以在类的构造方法中使用; 

泛型可以擦除:即实例化时不给出T的具体类型;系统将默认按T为Object处理,以确定程序无误!显式指出<Object>可以避免警告信息;但这不常用; 

*/ 

------通配符:
------------泛型上限: ?extends 最大泛型类型,则实例化时使用的泛型必须是最大泛型类型或其子类型; 

package com.udast; 

class P<T extends Number> // 泛型上限:Number类型; 

{ 

private T x; 

private T y; 

public P(T x, T y) 

{ 

this.x = x; 

this.y = y; 

} 

public void print() 

{ 

System.out.println("X = " + this.x); 

System.out.println("Y = " + this.y); 

} 

public T getX() 

{ 

return this.x; 

} 

} 

public class GenerDemo 

{ 

public static void main(String[] args) 

{ 

P<Integer> p = new P<Integer>(10, 200); // Ok, Integer is Child Class of Number 

p.print(); 

P<Float> pf = new P<Float>(10.3f, 20.56f); // ok, Float is also ChildClass of Number 

pf.print(); 

P<Number> pn = new P<Number>(10, 200); // use 泛型上限 <=> 泛型擦除, need convert below 

pn.print(); 

int i = (Integer)pn.getX(); // Number --> Integer 

System.out.println(i); 

P pp = new P(20, 20); // 将得到警告:注意:./work/GenerDemo.java 使用了未经检查或不安全的操作。这是泛型擦除! 

fun(p); // accept Integer 

fun(pf); // accept Float 

fun(pn); // accept Number 

fun1(p); // 只接收Integer类 

} 

public static void fun(P<?> p) // ?是类型通配符,表示接收所有合法类型,这避免了使用Object或其他泛型上限时,不同泛型类型不支持相互传递 

{ 

p.print(); 

} 

public static void fun1(P<? extends Integer> p) // 将只能接收Integer类型或其 子类型; 

{ 

System.out.println("对方法使用通配符和泛型上限限制:Integer!"); 

p.print(); 

} 

} 

/* 

P<Object> p1 = new P<Object>(); // 好比整个商城的商品 

P<Integer> p2 = new P<Integer>(); // 好比一个顾客购买的商品 

p1 = p2; // 将是错误的,因为p1、p2不再是类类型,而是泛型类型,如上举例,显然不同! 

那么:fun(P<Object> p); 将不能接收P<Integer> p2泛型; 

而: fun(P<?> p); 包含 fun(P<Integer> p); 所有通配符解决了这个矛盾! 

泛型上限:默认的上限是:Object, 

显式声明格式: ? extends className, className表示泛型上限; 

?super className , 下限; 

*/ 

package com.udast; 

class Str<T> 

{ 

private T str; 

public Str(T t) 

{ 

this.str = t; 

System.out.println("泛型下限:String!" + str); 

} 

} 

public class GenDemo 

{ 

public static void main(String[] args) 

{ 

fun(new Str<String>("String类型可以!")); 

fun(new Str<Object>("Object类型也可以!")); 

} 

public static void fun(Str <? super String> str) // 方法也可以使用泛型下限 

{ 

System.out.println("接收泛型下限以上的类型:" + str); 

} 

} 

/* 

administrator@xu-desktop:~$ javac -d . ./work/GenDemo.java 

administrator@xu-desktop:~$ java com.udast.GenDemo 

泛型下限:String!String类型可以! 

接收泛型下限以上的类型:com.udast.Str@3e25a5 

泛型下限:String!Object类型也可以! 

接收泛型下限以上的类型:com.udast.Str@19821f 

*/ 

--------------泛型接口:和类的泛型语法相同; 

package com.udast; 

interface A<T> // 接口中使用泛型 

{ 

public void fun(T param); // 抽象方法使用泛型; 

} 

class ClassInfo<T> implements A<T> // 第一种实现泛型接口的方法 

{ 

public void fun(T param) // 这个T类型是在类实例化时确定的 

{ 

System.out.println("要打印的类信息:" + param); 

} 

} 

class Test implements A<Test> // 第二种实现方式:该泛型接口只对Test类的实例有效 

{ 

public void fun(Test param) 

{ 

System.out.println("只对本类有效的泛型接口实现:" + param); 

} 

} 

public class GenDemo1 

{ 

public static void main(String[] args) 

{ 

ClassInfo<String> cinfo = new ClassInfo<String>(); // T --> String 

A<String> a = cinfo; 

cinfo.fun("String:字符串类型!"); 

a.fun("父类接口引用子类覆写的方法!"); 

A<Test> at = new Test(); // 第二种方式:对本类操作; 

at.fun(new Test()); 

A<ClassInfo> ainfo = new ClassInfo<ClassInfo>(); // 与第二种方式效果同, 不过要确定T--->ClassInfo; 

ainfo.fun(new ClassInfo()); 

} 

} 

/* 

administrator@xu-desktop:~$ java com.udast.GenDemo1 

要打印的类信息:String:字符串类型! 

要打印的类信息:父类接口引用子类覆写的方法! 

只对本类有效的泛型接口实现:com.udast.Test@addbf1 

要打印的类信息:com.udast.ClassInfo@42e816 

*/ 

--------------泛型方法:
在方法上使用泛型,不要求所在的类使用泛型,更灵活; 

package com.udast; 

class Demo 

{ 

public <T> T print(T param) // 泛型方法:所在的类非泛型操作类 

{ 

return param; // 返回值也是泛型 

} 

} 

public class GenDemo2 

{ 

public static void main(String[] args) 

{ 

String str = new Demo().print("返回泛型!"); // T-->String 

int i = new Demo().print(5); // T-->Integer 

Demo demo = new Demo().print(new Demo()); // T-->Demo 

Demo demo1 = new Demo(); 

System.out.println(str + "\n" + i + "\n" + demo + "\n" + demo1.print(demo1)); 

} 

} 

/* 

administrator@xu-desktop:~$ javac -d . ./work/GenDemo2.java 

administrator@xu-desktop:~$ java com.udast.GenDemo2 

返回泛型! 

5 

com.udast.Demo@3e25a5 

com.udast.Demo@19821f 

*/ 

--------返回泛型数组的泛型方法: 

package com.udast; 

public class GenFun 

{ 

public static void main(String[] args) 

{ 

Integer i[] = fun(1, 2, 3, 4, 5); // 泛型为Integer 

for (int x : i) 

{ 

System.out.println(x); 

} 

} 

public static <T> T[] fun(T ... param) // 该泛型方法接收可变参数 

{ 

return param; // 接收的是可变参数,当然返回的是数组; 

} 

} 

/* 

administrator@xu-desktop:~$ javac -d . ./work/GenFun.java 

administrator@xu-desktop:~$ java com.udast.GenFun 

1 

2 

3 

4 

5 

*/ 

---------------泛型嵌套:
用一个泛型类型设置泛型类型; 

package com.udast; 

class Info<T> 

{ 

private T param; // 含有一个泛型的成员 

public void setParam(T param) // 设置泛型成员 

{ 

this.param = param; 

} 

public T getParam() 

{ 

return this.param; // 获取泛型成员 

} 

} 

class Person<T> 

{ 

private T info; // 含有一个泛型的成员 

public void setInfo(T info) 

{ 

this.info = info; // 设置泛型成员 

} 

public T getInfo() 

{ 

return this.info; // 返回泛型成员 

} 

} 

public class MultiGen 

{ 

public static void main(String[] args) 

{ 

Person< Info<String> > per = new Person< Info<String> >(); // 泛型嵌套:T-->Info<T`>;T`-->String 

per.setInfo(new Info<String>()); // 用一个空的Info的实例设置per的info成员 

per.getInfo().setParam("泛型嵌套!"); // 设置Info实例的param成员 

System.out.println(per.getInfo().getParam()); // 得到param成员 

} 

} 

/* 

administrator@xu-desktop:~$ javac -d . ./work/MultiGen.java 

administrator@xu-desktop:~$ java com.udast.MultiGen 

泛型嵌套! 

*/ 

------------- 泛型应用:
/*
一个人的信息分为:基本信息,和联系方式;
实现一个类既能操作人的基本信息,又能操作联系方式;
*/ 

package com.udast; 

interface Info // 表示人的各种信息 

{ 

// 空实现的接口 称为 标识接口; 

} 

class Whois implements Info // 人的基本信息 

{ 

private String name; 

private int age; 

public Whois() 

{ 

super(); // 默认 

} 

public Whois(String name, int age) 

{ 

super(); // 明确调用Object的默认构造 

this.name = name; 

this.age = age; 

} 

public String getName() 

{ 

return this.name; 

} 

public void setName(String name) 

{ 

this.name = name; 

} 

public int getAge() 

{ 

return this.age; 

} 

public void setAge(int age) 

{ 

this.age = age; 

} 

public String toString() // 覆写父类的方法 

{ 

return "姓名:" + this.name + " 年龄:" + this.age; 

} 

} 

class Contact implements Info // 表示联系方式 

{ 

private String address; 

private String zipCode; 

public Contact() 

{ 

super(); 

} 

public Contact(String address, String zipCode) 

{ 

this.address = address; 

this.zipCode = zipCode; 

} 

public String getAddress() 

{ 

return this.address; 

} 

public void setAddress(String address) 

{ 

this.address = address; 

} 

public String getZipCode() 

{ 

return this.zipCode; 

} 

public void setZipCode(String zipCode) 

{ 

this.zipCode = zipCode; 

} 

public String toString() // 覆写父类方法 

{ 

return "地址:" + this.address + " 区号:" + this.zipCode; 

} 

} 

class Person<T extends Info> // 泛型上限为接口Info ,T只能是Info子类 

{ 

private T info; 

public Person(T info) 

{ 

this.info = info; 

} 

public T getInfo() 

{ 

return this.info; 

} 

public void setInfo(T info) 

{ 

this.info = info; 

} 

} 

public class GenPersonInfo 

{ 

public static void main(String[] args) 

{ 

String name = "张三"; 

int age = 30; 

Person<Whois> perWhois = new Person<Whois>(new Whois()); // 一个空的实例 T-->Whois 

perWhois.setInfo(new Whois(name, age)); // 给实例赋值 

System.out.println(perWhois.getInfo()); 

String address = "北京", zipCode = "10000"; 

Person<Contact> perContact = new Person<Contact>(new Contact()); // T-->Contact 

perContact.setInfo(new Contact(address, zipCode)); 

System.out.println(perContact.getInfo()); 

} 

} 

/* 

administrator@xu-desktop:~$ javac -d . ./work/GenPersonInfo.java 

administrator@xu-desktop:~$ java com.udast.GenPersonInfo 

姓名:张三 年龄:30 

地址:北京 区号:10000 

*/

声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 嗅谱网
转载请注明:转自《java泛型基础详解
本文地址:http://www.xiupu.net/archives-4204.html
关注公众号:嗅谱网

赞赏

wechat pay微信赞赏alipay pay支付宝赞赏

上一篇
下一篇

相关文章

在线留言

你必须 登录后 才能留言!