第14章 泛型
14.1 泛型基础
实例255 一个关于泛型的简单例子
import java.util.Date;
public class MyFirstGeneric<T> {
T t; //t的类型是T,现在不能具体确定它的类型,需要到创建对象时才能确定
MyFirstGeneric(T t) {// 创建该类的构造方法为T对象赋值
this.t = t;
}
// 这个方法的返回类型也是T
T getT() {
return t;
}
// 显示T的类型
void printType() {
System.out.println("Type of T is:" + t.getClass().getName());
}
public static void main(String args[]) {
// 声明一个String类型的Generic变量
MyFirstGeneric<String> str;
// 创建一个String类型的Generic对象
str = new MyFirstGeneric<String>("这是一个简单的泛型实例");
// 输出它的一些信息
str.printType();
String string = str.getT();
System.out.println("\tstring=" + string);
// 声明一个Date类型的Generic变量
MyFirstGeneric<Date> sobj;
// 创建一个Date类型的Generic对象
sobj = new MyFirstGeneric<Date>(new Date());
// 输出它的一些信息
sobj.printType();
String time = sobj.getT().toGMTString();
System.out.println("\ttime=" + time);
}
}
实例256 带两个类型参数的泛型
public class MoreParameters<T, V> {
T t;
V v;
// 构造方法也可以使用这两个类型参数
MoreParameters(T t1, V v1) {
t = t1;
v = v1;
}
// 显示T和V的类型
void printTypes() {
System.out.println("参数T的对象类型为: " + t.getClass().getName());
System.out.println("参数V的对象类型为: " + v.getClass().getName());
}
T getT() {
return t;
}
V getV() {
return v;
}
public static void main(String args[]) {
MoreParameters<Integer, Double> tv; // 指定类型参数的实际类型
// 构造方法中需要再次指定类型参数,同时还要传递实际参数
tv = new MoreParameters<Integer, Double>(100, 12.56);
tv.printTypes();
int num = tv.getT();
System.out.println("num变量中的值为: " + num);
double dou = tv.getV();
System.out.println("dou变量中的值为:" + dou);
}
}
实例257 有界类型程序示例
//有界类型程序示例
public class BoundedType {
public static void main(String args[]) {
System.out.println("有界类型程序示例如下:");
Integer inums[] = { 1, 2, 3, 4, 5 };//创建一个Integer类型的数组
MyTypes<Integer> iobj = new MyTypes<Integer>(inums);//使用泛型对象
System.out.println("\tint型数据的求和结果为:" + iobj.summation());
Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
MyTypes<Double> dobj = new MyTypes<Double>(dnums);//创建一个Double类型的数
System.out.println("\n\tdouble型数据的求和结果为:" + dobj.summation());
}
}
class MyTypes<T extends Number> {
T[] nums;//定义一个Number类的数组
MyTypes(T[] obj) {//为该数组赋值
nums = obj;
}
double summation() {//对参数进行求和运算
double sum = 0.0;
for (int i = 0; i < nums.length; ++i)
sum += nums[i].doubleValue(); //将Number类数组中的对象转换成double类型并依次相加求和
return sum ;
}
}
实例258 通配符使用示例
import java.util.*;
//通配符参数使用示例
public class Wildcard {
public static void main(String args[]) {
Integer Ints[] = { 1, 2, 3, 4, 5 };// 定义Integer对象数组并初始化
Symbol<Integer> integer = new Symbol<Integer>(Ints);// 创建Integer泛型对象
Double Dous[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };// 定义Double对象数组并初始化
Symbol<Double> douObject = new Symbol<Double>(Dous);// 创建Double泛型对象
douObject.printMessage(integer); // integer和douObject的类型不相同
List<String> list1 = new ArrayList<String>();// 定义一个List泛型对象,添加的元素是String类型的
// 向List对象中添加元素
list1.add("String");
list1.add("你好");
list1.add("世界真大啊");
List<?> list2 = list1;// 声明一个List列表中元素为任何类型的泛型对象,并将list1赋给list2
System.out.println("列表List对象list2中的元素如下:");
for (int i = 0; i < list2.size(); i++) {
System.out.println("\t" + list2.get(i));// 将list2中的元素输出
}
}
}
class Symbol<T extends Number> {
T[] nums;
Symbol(T[] obj) {
nums = obj;
}
void printMessage(Symbol<?> sb) { // 这里使用了类型通配符
System.out.println("对象型参数sb的参数类型是:" + sb.getClass().getName());
}
}
实例259 泛型方法使用示例
import java.util.Date;
//泛型方法的使用示例
public class GenericMethod {
// 定义泛型方法,有一个形式参数用类型参数T来定义
public static <T> void genericMethods(T t, char n) {
T t1 = t; // 局部变量也可以用类型参数T来定义
System.out.println("[1] " + n + "的对象类型为:" + t1.getClass().getName());
}
public static <T> void genericMethods(T t) {
System.out.println("\n[2] " + t + "的对象类型为:" + t.getClass().getName());
}
public static void main(String args[]) {
Date date = new Date();
Character k = new Character('A');
// 用两种不同的方法调用泛型方法
GenericMethod.<Character> genericMethods(k, 'B');
genericMethods(date);
}
}
实例260 泛型接口示例
//泛型接口的使用示例
public class GenericInterface {
public static void main(String args[]) {
Double doubleArrays[] = { 56.5, 58.127, 56.2, 5.569, 825.0, 12.36,
510.89 };// 创建一个Double类型的数组并初始化
Character charArrays[] = { 'A', 'w', 'z', 'Z', 'b', 'u', 'x' };// 创建一个Character类型的数组并初始化
ComparableElement<Double> iob = new ComparableElement<Double>(
doubleArrays);// 创建Double类型的泛型对象
ComparableElement<Character> cob = new ComparableElement<Character>(
charArrays);// 创建Character类型的泛型对象
// 调用MaxOrMin接口中的min()和max()
System.out.println("在Integer数组中,求元素最大值,max= " + iob.max());
System.out.println("在Integer数组中,求元素最小值为,min= " + iob.min());
System.out.println("在Character数组中,求元素最大值,max= " + cob.max());
System.out.println("在Character数组中,求元素最小值为,min= " + cob.min());
}
}
interface MaxOrMin<T extends Comparable<T>> {// 创建一个泛型接口
// 定义两个泛型方法:min()和max()
T min();
T max();
}
// 声明一个ComparableElement类继承于Comparable类并实现MaxOrMin接口
class ComparableElement<T extends Comparable<T>> implements MaxOrMin<T> {
T[] mm;
ComparableElement(T[] ob) {
mm = ob;
}
public T min() {// 重写MaxOrMin接口中的min()方法,求出数组中的最小值
T t = mm[0];
for (int i = 1; i < mm.length; ++i)
if (mm[i].compareTo(t) < 0)
t = mm[i];
return t;
}
public T max() {// 重写MaxOrMin接口中的max()方法,求出数组中的最大值
T t = mm[0];
for (int i = 1; i < mm.length; ++i)
if (mm[i].compareTo(t) > 0)
t = mm[i];
return t;
}
}
实例261 泛型实现坐标打印
/**
* Created by IntelliJ IDEA. User: leizhimin Date: 2007-9-18 Time: 16:09:37
* 三种坐标,用泛型实现坐标打印
*/
public class CoorGeneric {
static void showXY(GenericCoords<?> c) {// 定义泛型方法,利用通配符设置参数C的类型为XL并显示类XL中的变量X和Y的值
System.out.println("X Y 坐标轴:");
for (int i = 0; i < c.gcs.length; i++) {
System.out.println(c.gcs[i].x + " " + c.gcs[i].y);
}
}
static void showXYZ(GenericCoords<? extends XYZ> c) {
System.out.println("X Y Z 坐标轴:");
// 定义泛型方法,利用通配符设置参数C的类型为XYZ并显示类XYZ中的变量X、Y和Z的值
for (int i = 0; i < c.gcs.length; i++) {
System.out.println(c.gcs[i].x + " " + c.gcs[i].y + " "
+ c.gcs[i].z);
}
}
static void showAll(GenericCoords<? extends XYZT> c) {
System.out.println("X Y Z T 坐标轴:");
// 定义泛型方法,利用通配符设置参数C的类型为XYZT并显示类XYZT中的变量X、Y、Z和T的值
for (int i = 0; i < c.gcs.length; i++) {
System.out.println(c.gcs[i].x + " " + c.gcs[i].y + " "
+ c.gcs[i].z + " " + c.gcs[i].t);
}
}
public static void main(String args[]) {
XY td[] = { new XY(0, 0), new XY(7, 9), new XY(18, 4), new XY(-1, -23) };
GenericCoords<XY> gcd1 = new GenericCoords<XY>(td);
System.out.println("GenericCoords类对象gcd2中的内容:");
showXY(gcd1);
XYZT fd[] = { new XYZT(1, 2, 3, 4), new XYZT(6, 8, 14, 8),
new XYZT(22, 9, 4, 9), new XYZT(3, -2, -23, 17) };
GenericCoords<XYZT> gcd2 = new GenericCoords<XYZT>(fd);
System.out.println("GenericCoords类对象gcd2中的内容:");
showXY(gcd2);
showXYZ(gcd2);
showAll(gcd2);
}
}
class XY {// 表示只有XY坐标的类
int x, y;
public XY(int x, int y) {// 为变量X、Y赋值
this.x = x;
this.y = y;
}
}
class XYZ extends XY {// 表示只有XYZ坐标的类
int z;
public XYZ(int x, int y, int z) {
super(x, y);// 调用父类的构造方法
this.z = z;
}
}
class XYZT extends XYZ {// 表示只有XYZT坐标的类,其中X:横坐标,Y:纵坐标 Z:垂直坐标,T:空间
int t;
public XYZT(int x, int y, int z, int t) {
super(x, y, z);// 调用父类的构造方法
this.t = t;
}
}
/**
* 存放泛型坐标的(数据结构)类
*/
class GenericCoords<T extends XY> {// 定义泛型类,设置其参数类型为XY
T[] gcs;
public GenericCoords(T[] gcs) {
this.gcs = gcs;
}
}
14.2 泛型类的继承
实例262 继承泛型类示例
import java.util.Date;
//继承泛型类
public class GenericClass {
public static void main(String args[]) {
System.out.println("以泛型类为父类的实现方法如下:");
// 创建子类的对象,它需要传递两个参数,Date类型给父类,自己使用String类型
Child<Date, String> cd = new Child<Date, String>(new Date(),
"当前系统的时间为: ");
System.out.print("\t" + cd.getDob());
System.out.println(cd.getOb());
}
}
class Child<T, U> extends Father<T> {
U u;
public Child(T t1, U u1) {
super(t1); // 传递参数给父类
u = u1; // 为自己的成员赋值
}
public U getDob() {
return u;
}
}
class Father<T> { // 定义一个泛型类
T t;
public Father(T t) {
this.t = t;
}
public Father() {
t = null;
}
public T getOb() {
return t;
}
}
实例263 继承非泛型类示例
//继承非泛型类示例
public class NonGenericcClass {
public static void main(String args[]) {
System.out.println("继承非泛型类的实现方法如下:");
doNonGeneric<String> oa = new doNonGeneric<String>(
"doNonGeneric类的值为: ", 125);
System.out.print("\t" + oa.getOb());
System.out.println(oa.getNum());
}
}
class NonGeneric {// 创建父类对象,此类并不是泛型类
double num;
public NonGeneric(double n) {// 设置变量num的值等于传入的参数值
num = n;
}
public NonGeneric() {// 设置变量num的默认值为0.0
num = 0.0;
}
public double getNum() {// 返回变量num的当前值
return num;
}
}
class doNonGeneric<T> extends NonGeneric {// 定义一个继承于NonGeneric的子类。该类被声明为泛型类
T ob;
public doNonGeneric(T ob, double n) {
super(n);// 将传入的参数值赋给父类
this.ob = ob;// 将对数类型给自己的变量赋值
}
public T getOb() {
return ob;
}
}
实例264 泛型类的类型识别示例
//泛型运行时类型识别 1
public class GenericRTTI {
public static void main(String args[]) {
MyFirstGeneric<Double> dou = new MyFirstGeneric<Double>(100.0);
MyFirstGeneric<String> str = new MyFirstGeneric<String>("hellow");
if (dou instanceof MyFirstGeneric)//判断dou是否是MyFirstGeneric类的实例
System.out
.println("MyFirstGeneric<Integer> object is instance of MyFirstGeneric");
if (dou instanceof MyFirstGeneric<?>)//判断dou是否是MyFirstGeneric<?>泛型类的实例
System.out
.println("MyFirstGeneric<Integer> object is instance of MyFirstGeneric<?>");
if (dou.getClass() == str.getClass())//判断这两个对象运行时的类是否相等
System.out
.println("MyFirstGeneric<Integer> class equals MyFirstGeneric<String> class");
}
}
实例265 强制类型转换示例
//强制类型转换
public class CastType {
public static void main(String args[]) {
Father<Double> father = new Father<Double>(1.0);
Child<Double, String> child = new Child<Double, String>(200.0, "中国您好");
// 试图将子类对象转换成父类,正确
if ((Father<Double>) child instanceof Father)
System.out.println("子类对象转换成父亲对象.");
// 试图将父类对象转换成子类,错误
try {
if ((Child<Double, String>) father instanceof Child)
System.out.println("父类对象转换成子亲对象.");
} catch (Exception e) {
System.out.println(e);
System.out.println("发生异常的原因:父类对象不能强制转换成子亲对象.");
}
}
}
14.3 擦拭
实例266 无限界的擦拭
import java.util.Date;
//有限界的擦拭
public class BorderWipe<T extends Date> {
// 下面所有的T将被String所代替
T date;
BorderWipe(T date) {
this.date = date;
}
T getOb() {
return date;
}
}
实例267 有限界的擦拭
//无限界的擦拭
public class UnBorderWipe<T> {
// 下面所有的T将被Object所代替
T ob;
UnBorderWipe(T ob) {
this.ob = ob;
}
T getOb() {
return ob;
}
}
14.4 集合泛型类
实例268 Hashtable的泛型化
import java.util.Hashtable;
//Hashtable的泛型化
public class HashtableGeneric<K, V> {
// 创建Hashtable的泛型类对象
public Hashtable<K, V> hashTable = new Hashtable<K, V>();
// 创建put方法为key和value赋值
public void put(K k, V v) {
hashTable.put(k, v);
}
// 创建get方法可以根据key值获取value的值
public V get(K k) {
return hashTable.get(k);
}
public static void main(String args[]) {
HashtableGeneric<String, String> t = new HashtableGeneric<String, String>();
t.put("key", "Java语言");
String s = t.get("key");
System.out.println("根据key值获取的value的内容:\n\t" + s);
}
}
实例269 多功能画笔
import java.awt.*;
import java.awt.event.*;
import java.util.*;
//多功能画笔
public class Paintbrush extends Frame{
private final static int POINT = 0;
private final static int LINE = 1;
private final static int RECTANGLE = 2;
private final static int OVAL = 3;
private int type; // 画笔类型
Point p1;
Point p2;
ArrayList<Point> points = new ArrayList<Point>();
ArrayList<DrawPoint> area = new ArrayList<DrawPoint>();
public Paintbrush(String s) {
super(s);
}
public void mainFrame() {
MenuBar menuBar = new MenuBar();
Menu menu = new Menu("菜单");
MenuItem fmi4 = new MenuItem("Exit");
fmi4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
menu.addSeparator();
menu.add(fmi4);
Menu mtype = new Menu("画笔种类");
MenuItem menuItem = new MenuItem("点状");
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
type = Paintbrush.POINT;
}
});
MenuItem menuItem2 = new MenuItem("线状");
menuItem2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
type = Paintbrush.LINE;
}
});
MenuItem dmi3 = new MenuItem("矩形");
dmi3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
type = Paintbrush.RECTANGLE;
}
});
MenuItem dmi4 = new MenuItem("圆形");
dmi4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
type = Paintbrush.OVAL;
}
});
mtype.add(menuItem);
mtype.add(menuItem2);
mtype.add(dmi3);
mtype.add(dmi4);
menuBar.add(menu);
menuBar.add(mtype);
setMenuBar(menuBar);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
p1 = new Point(e.getX(), e.getY());
if (type == Paintbrush.POINT) {
points.add(p1);
repaint();
}
}
public void mouseReleased(MouseEvent e) {
if (type != Paintbrush.POINT) {
p2 = new Point(e.getX(), e.getY());
area.add(new DrawPoint(p1, p2, type));
repaint();
}
}
});
setBounds(50, 50, 640, 480);
setBackground(Color.WHITE);
setVisible(true);
}
public void paint(Graphics g) {
Iterator<Point> ip = points.iterator(); // 使用泛型
g.setColor(Color.black);
while (ip.hasNext()) {
Point p = ip.next(); // 使用泛型
g.fillOval(p.x, p.y, 10, 10);
}
// 起始点坐标
int x1, y1, x2, y2;
for (Iterator<DrawPoint> ipp = area.iterator(); ipp.hasNext();) {
DrawPoint pp = ipp.next();
x1 = (int) pp.startPoint.getX();
y1 = (int) pp.startPoint.getY();
x2 = (int) pp.endPoint.getX();
y2 = (int) pp.endPoint.getY();
switch (pp.type) {
case LINE:
g.setColor(Color.green);
g.drawLine(x1, y1, x2, y2);
break;
case RECTANGLE:
g.setColor(Color.red);
g.drawRect(x1, y1, x2 - x1, y2 - y1);
// 鼠标从右向左或从下往上拖动,不能绘制出图像:负值无意义
break;
case OVAL:
g.setColor(Color.blue);
g.drawOval(x1, y1, x2 - x1, y2 - y1);
break;
default:
break;
}
}
}
public static void main(String[] args) {
Paintbrush drawApp = new Paintbrush("多功能彩色画笔");
drawApp.mainFrame();
}
}
class DrawPoint {
public Point startPoint;
public Point endPoint;
public int type;
public DrawPoint(Point sPoint, Point ePoint, int drawType) {
startPoint = sPoint;
endPoint = ePoint;
type = drawType;
}
}