一:理论部分。

1.泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。

1)泛型(参数化类型):在定义类、接口和方法时,通过类型参数指示将要处理的对象类型。如ArrayList类是一个泛型程序设计的实例,可以聚集任何类型的对象。

2)泛型类:就是具有一个或多个类型变量的类,即创建用类型作为参数的类。在<>内定义形式类型参数,该形参表示类型而不表示值。

泛型类可以有多个类型变量,例如:public class Pair<T, U>

类定义中的类型变量用于指定方法的返回类型以及域、局部变量的类型。

3)泛型方法:除了泛型类外,还可以只单独定义一个方法作为泛型方法,用于指定方法参数或者返回值为泛型类型,在方法调用时确定具体需要。(泛型方法可以声明在泛型类中,也可以声明在普通类中)

4)泛型变量的限定:a.泛型变量的上界:如<T extends Number>(extends关键字所声明的上界既可以是一个类,也可以是一个接口,extends并不代表继承,它是类型范围限制。)

b.泛型变量的上界:如<? super CashCard>(通过使用super关键字可以固定泛型参数的类型为某种类型或者其超类当程序希望为一个方法的参数限定类型时,通常可以使用下限通配符)

2.泛型类的约束与局限性。

1)不能用基本类型(如int型,float型等)实例化类型参数
2)运行时类型查询只适用于原始类型
3)不能抛出也不能捕获泛型类实例
4)参数化类型的数组不合法
5)不能实例化类型变量
6)泛型类的静态上下文中类型变量无效
7)注意擦除后的冲突

3.泛型类型的继承规则:Java中的数组是协变的,但这一原理不适用于泛型类型。

泛型类可扩展或实现其它的泛型类。

4.通配符:“?”符号表明参数的类型可以是任何一种类型,而T表示一种未知类型。

通配符的一般用法:a.?:用于表示任何类型;

b.? extends type,表示带有上界;

c.? super type,表示带有下界。

二:实验部分。

1、实验目的与要求

(1) 理解泛型概念;

(2) 掌握泛型类的定义与使用;

(3) 掌握泛型方法的声明与使用;

(4) 掌握泛型接口的定义与实现;

(5)了解泛型程序设计,理解其用途。

2、实验内容和步骤

实验1: 导入第8章示例程序,测试程序并进行代码注释。

测试程序1:

l 编辑、调试、运行教材311、312页 代码,结合程序运行结果理解程序;

l 在泛型类定义及使用代码处添加注释;

l 掌握泛型类的定义及使用。

程序如下:

/**
* @version 1.01 2012-01-26
* @author Cay Horstmann
*/
public class PairTest1
{
public static void main(String[] args)
{
String[] words = { "Mary", "had", "a", "little", "lamb" };//初始化一个String对象数组
Pair<String> mm = ArrayAlg.minmax(words);//一对字符串:min,max
System.out.println("min = " + mm.getFirst());
System.out.println("max = " + mm.getSecond());
}
} class ArrayAlg
{
/**
* Gets the minimum and maximum of an array of strings.
* @param a an array of strings
* @return a pair with the min and max value, or null if a is null or empty
*/
public static Pair<String> minmax(String[] a)//普通方法,定义minmax为字符串类型
{
if (a == null || a.length == ) return null;
String min = a[];
String max = a[];
//将元素的泛型具体声明 for (int i = ; i < a.length; i++)//length:数组属性值
{
if (min.compareTo(a[i]) > ) min = a[i];
if (max.compareTo(a[i]) < ) max = a[i];
}//实现字符串比较大小
return new Pair<>(min, max);
}
}
/**
* @version 1.00 2004-05-10
* @author Cay Horstmann
*/
public class Pair<T>//类型变量(放在类名后面)
{
private T first;
private T second; public Pair() { first = null; second = null; }
public Pair(T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; }
public T getSecond() { return second; } public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}

程序运行结果如下:

测试程序2:

l 编辑、调试运行教材315页 PairTest2,结合程序运行结果理解程序;

l 在泛型程序设计代码处添加相关注释;

l 掌握泛型方法、泛型变量限定的定义及用途。

程序如下:

import java.time.*;

/**
* @version 1.02 2015-06-21
* @author Cay Horstmann
*/
public class PairTest2
{
public static void main(String[] args)
{
LocalDate[] birthdays =
{
LocalDate.of(, , ), // G. Hopper
LocalDate.of(, , ), // A. Lovelace
LocalDate.of(, , ), // J. von Neumann
LocalDate.of(, , ), // K. Zuse
};
Pair<LocalDate> mm = ArrayAlg.minmax(birthdays);
System.out.println("min = " + mm.getFirst());
System.out.println("max = " + mm.getSecond());
}
} class ArrayAlg
{
/**
Gets the minimum and maximum of an array of objects of type T.
@param a an array of objects of type T
@return a pair with the min and max value, or null if a is
null or empty
*/
public static <T extends Comparable> Pair<T> minmax(T[] a) //泛型方法(comparable是T的上界约束)
{
if (a == null || a.length == ) return null;
T min = a[];
T max = a[];//min和max与T的类型一致
for (int i = ; i < a.length; i++)
{
if (min.compareTo(a[i]) > ) min = a[i];
if (max.compareTo(a[i]) < ) max = a[i];
}
return new Pair<>(min, max);
}
}
/**
* @version 1.00 2004-05-10
* @author Cay Horstmann
*/
public class Pair<T> //类型变量
{
private T first;
private T second; public Pair() { first = null; second = null; }
public Pair(T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; }
public T getSecond() { return second; } public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}

程序运行结果如下:

测试程序3:

l 用调试运行教材335页 PairTest3,结合程序运行结果理解程序;

l 了解通配符类型的定义及用途。

程序如下:

/**
* @version 1.01 2012-01-26
* @author Cay Horstmann
*/
public class PairTest3
{
public static void main(String[] args)
{
Manager ceo = new Manager("Gus Greedy", , , , );
Manager cfo = new Manager("Sid Sneaky", , , , );
Pair<Manager> buddies = new Pair<>(ceo, cfo);
printBuddies(buddies); ceo.setBonus();
cfo.setBonus();
Manager[] managers = { ceo, cfo }; Pair<Employee> result = new Pair<>(); minmaxBonus(managers, result);
System.out.println("first: " + result.getFirst().getName()
+ ", second: " + result.getSecond().getName());
maxminBonus(managers, result);
System.out.println("first: " + result.getFirst().getName()
+ ", second: " + result.getSecond().getName());
} public static void printBuddies(Pair<? extends Employee> p)//通配符类型(带有上界)extends关键字所声明的上界既可以是一个类,也可以是一个接口。
{
Employee first = p.getFirst();
Employee second = p.getSecond();
System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
} public static void minmaxBonus(Manager[] a, Pair<? super Manager> result)//通配符类型(带有下界)必须是Manager的子类
{
if (a.length == ) return;
Manager min = a[];
Manager max = a[];
for (int i = ; i < a.length; i++)
{
if (min.getBonus() > a[i].getBonus()) min = a[i];
if (max.getBonus() < a[i].getBonus()) max = a[i];
}//比较大小值
result.setFirst(min);
result.setSecond(max);
} public static void maxminBonus(Manager[] a, Pair<? super Manager> result)//通配符类型(带有下界)
{
minmaxBonus(a, result);
PairAlg.swapHelper(result); //swapHelper捕获通配符类型
}
//无法编写公共静态< T超级管理器>
} class PairAlg
{
public static boolean hasNulls(Pair<?> p)//通过将hasNulls转换成泛型方法,避免使用通配符类型
{
return p.getFirst() == null || p.getSecond() == null;
} public static void swap(Pair<?> p) { swapHelper(p); } public static <T> void swapHelper(Pair<T> p)//使用辅助方法swapHelper(泛型方法),以在交换时临时保存第一个元素
{
T t = p.getFirst();
p.setFirst(p.getSecond());
p.setSecond(t);
}
}
/**
* @version 1.00 2004-05-10
* @author Cay Horstmann
*/
public class Pair<T>
{
private T first;
private T second;
//T是未知类型,不代表值
public Pair() { first = null; second = null; }
public Pair(T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; }
public T getSecond() { return second; } public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}
import java.time.*;

public class Employee//用户自定义类
{
private String name;
private double salary;
private LocalDate hireDay; public Employee(String name, double salary, int year, int month, int day)
{
this.name = name;
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
} public String getName()
{
return name;
} public double getSalary()
{
return salary;
} public LocalDate getHireDay()
{
return hireDay;
} public void raiseSalary(double byPercent)
{
double raise = salary * byPercent / ;
salary += raise;
}
}
public class Manager extends Employee//继承类
{
private double bonus; /**
@param name the employee's name
@param salary the salary
@param year the hire year
@param month the hire month
@param day the hire day
*/
public Manager(String name, double salary, int year, int month, int day)
{
super(name, salary, year, month, day);
bonus = ;
} public double getSalary()
{
double baseSalary = super.getSalary();
return baseSalary + bonus;
} public void setBonus(double b)
{
bonus = b;
} public double getBonus()
{
return bonus;
}
}

程序运行结果如下:

实验2:编程练习:

编程练习1:实验九编程题总结

l 实验九编程练习1总结(从程序总体结构说明、模块说明,目前程序设计存在的困难与问题三个方面阐述)。

程序总体结构:定义了一个主类Test,一个接口。

模块:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner; public class Test{ private static ArrayList<Person> Personlist1;
public static void main(String[] args) { Personlist1 = new ArrayList<>(); Scanner scanner = new Scanner(System.in);
File file = new File("C:\\Users\\lenovo\\Documents\\身份证"); try {
FileInputStream F = new FileInputStream(file);
BufferedReader in = new BufferedReader(new InputStreamReader(F));
String temp = null;
while ((temp = in.readLine()) != null) { Scanner linescanner = new Scanner(temp); linescanner.useDelimiter(" ");
String name = linescanner.next();
String id = linescanner.next();
String sex = linescanner.next();
String age = linescanner.next();
String place =linescanner.nextLine();
Person Person = new Person();
Person.setname(name);
Person.setid(id);
Person.setsex(sex);
int a = Integer.parseInt(age);
Person.setage(a);
Person.setbirthplace(place);
Personlist1.add(Person); }
} catch (FileNotFoundException e) {
System.out.println("查找不到信息");
e.printStackTrace();
} catch (IOException e) {
System.out.println("信息读取有误");
e.printStackTrace();
}
boolean isTrue = true;
while (isTrue) {
System.out.println("1:按姓名字典序输出人员信息;");
System.out.println("2:查询最大年龄与最小年龄人员信息;");
System.out.println("3.输入你的年龄,查询身份证号.txt中年龄与你最近人的姓名、身份证号、年龄、性别和出生地");
System.out.println("4:按省份找你的同乡;");
System.out.println("5:退出");
int type = scanner.nextInt();
switch (type) {
case :
Collections.sort(Personlist1);
System.out.println(Personlist1.toString());
break;
case : int max=,min=;int j,k1 = ,k2=;
for(int i=;i<Personlist1.size();i++)
{
j=Personlist1.get(i).getage();
if(j>max)
{
max=j;
k1=i;
}
if(j<min)
{
min=j;
k2=i;
} }
System.out.println("年龄最大:"+Personlist1.get(k1));
System.out.println("年龄最小:"+Personlist1.get(k2));
break;
case :
System.out.println("place?");
String find = scanner.next();
String place=find.substring(,);
String place2=find.substring(,);
for (int i = ; i <Personlist1.size(); i++)
{
if(Personlist1.get(i).getbirthplace().substring(,).equals(place))
{
System.out.println("你的同乡:"+Personlist1.get(i));
}
} break;
case :
System.out.println("年龄:");
int yourage = scanner.nextInt();
int close=ageclose(yourage);
int d_value=yourage-Personlist1.get(close).getage();
System.out.println(""+Personlist1.get(close)); break;
case :
isTrue = false;
System.out.println("再见!");
break;
default:
System.out.println("输入有误");
}
}
}
public static int ageclose(int age) {
int m=;
int max=;
int d_value=;
int k=;
for (int i = ; i < Personlist1.size(); i++)
{
d_value=Personlist1.get(i).getage()-age;
if(d_value<) d_value=-d_value;
if (d_value<max)
{
max=d_value;
k=i;
} } return k; }
}
public class Person implements Comparable<Person> {
private String name;
private String id;
private int age;
private String sex;
private String birthplace; public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getid() {
return id;
}
public void setid(String id) {
this.id= id;
}
public int getage() { return age;
}
public void setage(int age) {
// int a = Integer.parseInt(age);
this.age= age;
}
public String getsex() {
return sex;
}
public void setsex(String sex) {
this.sex= sex;
}
public String getbirthplace() {
return birthplace;
}
public void setbirthplace(String birthplace) {
this.birthplace= birthplace;
} public int compareTo(Person o) {
return this.name.compareTo(o.getname()); } public String toString() {
return name+"\t"+sex+"\t"+age+"\t"+id+"\t"; }
}

目前程序设计存在的困难与问题:

1)对一些知识理解不到位,不能很好地将理论知识应用到程序编写中。

2)当程序中处出现异常时,处理方式最多只能应用抛出异常这种消极方式。

3)分不清如何使用字符流和字节流。

l 实验九编程练习2总结(从程序总体结构说明、模块说明,目前程序设计存在的困难与问题三个方面阐述)。

程序总体结构:一个主类Demo,一个用户自定义类Number

模块:

import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Random; public class Demo {
public static void main(String[] args) { Scanner in = new Scanner(System.in);
Number counter = new Number();
PrintWriter out = null;
try {
out = new PrintWriter("text.txt");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int sum = ; for (int i = ; i <= ; i++) { int a = (int) Math.round(Math.random() * );
int b = (int) Math.round(Math.random() * );
int m = (int) Math.round(Math.random() * );
Random n = new Random(); switch (m) {
case :
System.out.println(i + ": " + a + "/" + b + "="); while (b == ) {
b = (int) Math.round(Math.random() * );
} int c = in.nextInt();
out.println(a + "/" + b + "=" + c);
if (c == counter.division(a, b)) {
sum += ;
System.out.println("恭喜答案正确");
} else {
System.out.println("抱歉,答案错误");
} break; case :
System.out.println(i + ": " + a + "*" + b + "=");
int c1 = in.nextInt();
out.println(a + "*" + b + "=" + c1);
if (c1 == counter.multiplication(a, b)) {
sum += ;
System.out.println("恭喜答案正确");
} else {
System.out.println("抱歉,答案错误");
}
break;
case :
System.out.println(i + ": " + a + "+" + b + "=");
int c2 = in.nextInt();
out.println(a + "+" + b + "=" + c2);
if (c2 == counter.add(a, b)) {
sum += ;
System.out.println("恭喜答案正确");
} else {
System.out.println("抱歉,答案错误");
} break;
case :
System.out.println(i + ": " + a + "-" + b + "=");
int c3 = in.nextInt();
out.println(a + "-" + b + "=" + c3);
if (c3 == counter.reduce(a, b)) {
sum += ;
System.out.println("恭喜答案正确");
} else {
System.out.println("抱歉,答案错误");
}
break; } }
System.out.println("成绩" + sum);
out.println("成绩:" + sum);
out.close(); }
}
public class Number {
private int a;
private int b; public int add(int a, int b) {
return a + b;
} public int reduce(int a, int b) {
return a - b;
} public int multiplication(int a, int b) {
return a * b;
} public int division(int a, int b) {
if (b != )
return a / b;
else
return ;
} }

目前程序设计存在的困难与问题:

1)没有考虑到除法运算中运算结果为小数小数以及除数为0的情况。

2)找不到文件保存路径,只能通过电脑搜索获得,对文件的理解还不到位。

3)对异常的调试还存在很大的问题。

编程练习2:采用泛型程序设计技术改进实验九编程练习2,使之可处理实数四则运算,其他要求不变。

程序如下:

package Demo;

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Random;
import java.util.Scanner; public class Demo {
public static void main(String[] args) { Scanner in = new Scanner(System.in);
Number counter = new Number();
PrintWriter out = null;
try {
out = new PrintWriter("test.txt");
} catch (FileNotFoundException e) {
System.out.println("Error!");
e.printStackTrace();
} int sum = ; for (int i = ; i <= ; i++) {
int a = (int) Math.round(Math.random() * );
int b = (int) Math.round(Math.random() * );
int m;
Random rand = new Random();
m = (int) rand.nextInt() + ; switch (m) {
case :
a = b + (int) Math.round(Math.random() * );
while(b == ){
b = (int) Math.round(Math.random() * );
}
while(a % b != ){
a = (int) Math.round(Math.random() * ); }
//a大于b,a%b为0(保证能整除)
System.out.println(i + ": " + a + "/" + b + "="); int c0 = in.nextInt();
out.println(a + "/" + b + "=" + c0);
if (c0 == counter.division(a, b)) {
sum += ;
System.out.println("恭喜答案正确!");
} else {
System.out.println("抱歉答案错误!");
} break; case :
System.out.println(i + ": " + a + "*" + b + "=");
int c = in.nextInt();
out.println(a + "*" + b + "=" + c);
if (c == counter.multiplication(a, b)) {
sum += ;
System.out.println("恭喜答案正确!");
} else {
System.out.println("抱歉答案错误!");
}
break;
case :
System.out.println(i + ": " + a + "+" + b + "=");
int c1 = in.nextInt();
out.println(a + "+" + b + "=" + c1);
if (c1 == counter.add(a, b)) {
sum += ;
System.out.println("恭喜答案正确!");
} else {
System.out.println("抱歉答案错误!");
}
break;
case :
while (a < b) {
b = (int) Math.round(Math.random() * );
}
//若a<b,则重新生成b(避免出现负数)
System.out.println(i + ": " + a + "-" + b + "=");
int c2 = in.nextInt();
out.println(a + "-" + b + "=" + c2);
if (c2 == counter.reduce(a, b)) {
sum += ;
System.out.println("恭喜答案正确!");
} else {
System.out.println("抱歉答案错误!");
}
break;
}
}
System.out.println("成绩" + sum);
out.println("成绩:" + sum);
out.close();
}
}
package Demo;

public class Number<T> {
private T a;
private T b; public Number() {
a = null;
b = null;
}
public Number(T a, T b) {
this.a = a;
this.b = b;
} public int add(int a,int b) {
return a + b;
} public int reduce(int a, int b) {
return a - b;
} public int multiplication(int a, int b) {
return a * b;
} public int division(int a, int b) {
if (b != && a%b==)
return a / b;
else
return ;
}
}

程序运行结果如下:

三:实验总结。

这周主要学习了泛型程序,泛型类和泛型方法同时具备可重用性、类型安全和效率,泛型类不会强行对值类型进行装箱和拆箱,或对引用类型进行向下强制类型转换,所以是编程性能得到提高。在学习理论课时,听老师讲泛型类不算特别难,但在实验课上运行程序时,并不是太理解程序,经过老师和学长的讲解,对程序有了一定程度的理解,但是也只是基本能读懂程序,在自己编程时,还是有很大问题。在之后的学习中,我会多练习程序去了解这些知识,争取能够独立完整的编写程序。

最新文章

  1. [转]:Delphi 中的哈希表(1): THashedStringList
  2. helpDB
  3. [Eclipse] 详细设置护眼背景色和字体颜色并导出
  4. MVC使用的MetaModel代码生成器模板
  5. 在ASP中限制同一表单被多次提交
  6. Linux下*.tar.gz文件解压缩命令 find 命令
  7. CentOS安装postgresql 9.4
  8. ubuntu配置LAMP
  9. POJ 3304 Segments[直线与线段相交]
  10. imx51-linux的cpuinfo之分析
  11. Python 能做什么?
  12. Stanford CS231n - Convolutional Neural Networks for Visual Recognition
  13. springMVC源码分析--视图View(一)
  14. 【转】【iOS】动态更换App图标
  15. [转帖]select提高并发,select和poll、epoll的区别(杂)
  16. Linux内核hlist数据结构分析
  17. HDUOJ--1058HangOver
  18. 使用ES-Hadoop 6.5.4编写MR将数据索引到ES
  19. Linux安装AUTOCONF和AUTOMAKE产生的程序的一般步骤
  20. 基于ASP.NET Core 创建 Web API

热门文章

  1. 设计数据库 ER 图太麻烦?不妨试试这两款工具,自动生成数据库 ER 图!!!
  2. apollo 项目配置中心开源框架部署
  3. 新版gitbook导出pdf
  4. jax-rs下载文件
  5. 《JavaScript和jQuery实战手册(原书第2版)》——2.1节语句
  6. angular2相关
  7. centos 7.0运行docker出现内核报错解决方法
  8. unittest(简介)
  9. ZABBIX自动发现Redis端口并监控
  10. thinkphp 5.x~3.x 文件包含漏洞分析