面向对象技术与方法(JAVA)
关键词:面向对象JAVA、方法重写、Lambda表达式、文件类、输入输出流
背景信息
这是2022年春季学期,北京理工大学,计算机学院,软件工程,开设的一门必修课程,为期八周,共32课时,难度较大,教师课件使用英文讲授,自学的收获更多。
成绩主要分为三部分,作业、实验、考试。本篇内容为实验题,共六个大题,其中两道难度非常高,以当时的水平写出来实属不易。其他题目更多的是了解面向对象语言的特点和语法。
本篇内容是实验题中的难题。
2022面向对象JAVA实验
目录
(点击跳转)
一、equals()方法重写
实现一个名为Value 的类,其中含有一个字符类型的成员x 和双精度类型的成员y。请重写(override)其equals( )方法,使得用equals( )比较Value 类的两个对象的内容时,相等条件是对象的所有成员分别对应相等。
思路
首先创建Value类,成员有char x,double y以及相应的构造器初始化,重写equals方法,将原先的比较地址改为数据成员的比较,相等返回true,不等返回false。在main方法中创建三个对象,并调用构造器初始化,调用equals方法检验结果。
收获
此题涉及三个知识点:输入、输出和数组排序。输入和输出比较相似,这一题中更多注意输出的时候,考虑到要进行后续的读取,因此选用DataInputStream而不是PrintWriter,并且对于将字符写入文件应当更多使用writeBytes而不是writeChar(后者更容易出错)。对于排序有两种思路,一种是直接集成Comparable接口,实现其中的campareTo方法,按照需要确定大于(1)、等于(0)和小于(-1)。使用时直接使用Arrays.sort进行排序。还有一种是新建一个实现Comparator接口的类作为比较器,实现其中的campare方法(与上述相同)。使用时在Arrays.sort中加入该类作为比较器。
源码
package java_exp2022;
class Value{
char x;
double y;
Value(char x,double y){
this.x = x;
this.y = y;
}
boolean equals(Value v1) {
if( v1.x == this.x && v1.y == this.y) return true;
else return false;
}
}
public class Project1 {
public static void main(String[] args) {
Value a = new Value('a',2.33);
Value b = new Value('b',3.22);
Value c = new Value('a',2.33);
System.out.println("Does value_a equal to value_b?\n"+a.equals(b));
System.out.println("Does value_a equal to value_c?\n"+a.equals(c));
System.out.println("Does value_b equal to value_c?\n"+b.equals(c));
}
}
/*OutPut
Does value_a equal to value_b?
false
Does value_a equal to value_c?
true
Does value_b equal to value_c?
false
*/
二、Lambda表达式排序
使用Lambda表达式比较器Comparator给List对象排序,分别按Name、Age(倒序)、Grade排序。List对象内容如下表:
ID | Name | Age | Grade |
---|---|---|---|
1 | ZhangSan | 28 | 98 |
2 | LiSi | 21 | 100 |
3 | KangKang | 27 | 89 |
4 | LiMing | 19 | 92 |
5 | WangGang | 22 | 66 |
6 | ZhaoXin | 24 | 85 |
7 | LiuWei | 20 | 78 |
8 | BaiZhanTang | 16 | 99 |
思路
首先创立基本的对象Student,包含数据成员Integer ID,age,grade和String name,为了后面方便直接调用比较器比较,这里使用了对象类型的Integer,还是使用构造器进行初始化。在main函数中使用ArrayList容纳Student类;调用add方法添加对象,继续调用sort方法,方法中写入lambda表达式( Student st1 , Student st2 ) -> st1.ID.compareTo(st2.ID),将list中的成员按照ID的从小到大排序;其他排序完全类似。
收获
这个题目涉及的知识点有:容器类的使用,数据的排序,lambda表达式,数据的输出。先创立基本的对象Student,使用ArrayList容纳Student类;调用sort方法,方法中写入lambda表达式( Student st1 , Student st2 ) -> st1.ID.compareTo(st2.ID),即可完成前类的容纳,排序,lambda表达式的使用;最后在main方法之外,即Project2(实验二)类中添加一个static修饰的printlist方法,使用static修饰可以不用再创建类直接调用方法,在方法中建立迭代器Iterator it = list.iterator();继而实现对Student的数据成员逐个打印,即可查看排序效果。
源码
package java_exp2022;
import java.util.*;
class Student{
Integer ID,age,grade;
String name;
Student(Integer _ID,Integer _age,Integer _grade,String _name){
ID = _ID;
age = _age;
grade = _grade;
name = _name;
}
}
public class Project2 {
static void printlist(ArrayList<Student> list) {
Iterator<Student> it = list.iterator();
while(it.hasNext()) {
Student st = it.next();
System.out.println("ID = "+st.ID+" , Age = "+st.age+" ,
Grade = "+st.grade+" , Name = "+st.name);
}
}
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student(1,28,98,"ZhangSan"));
list.add(new Student(2,21,100,"LiSi"));
list.add(new Student(3,27,89,"KangKang"));
list.add(new Student(4,19,92,"LiMing"));
list.add(new Student(5,22,66,"WangGang"));
list.add(new Student(6,24,85,"ZhaoXin"));
list.add(new Student(7,20,78,"LiuWei"));
list.add(new Student(8,16,99,"BaiZhanTang"));
list.sort( ( Student st1 , Student st2 ) -> st1.ID.compareTo(st2.ID) );
System.out.println("------Sorted by ID-----");
printlist(list);
list.sort( ( Student st1 , Student st2 ) -> st2.age.compareTo(st1.age) );
System.out.println("------Sorted by Age(down)-----");
printlist(list);
list.sort( ( Student st1 , Student st2 ) -> st1.grade.compareTo(st2.grade) );
System.out.println("------Sorted by Grade-----");
printlist(list);
list.sort( ( Student st1 , Student st2 ) -> st1.name.compareTo(st2.name) );
System.out.println("------Sorted by Name-----");
printlist(list);
}
}
/*OutPut
------Sorted by ID-----
ID = 1 , Age = 28 , Grade = 98 , Name = ZhangSan
ID = 2 , Age = 21 , Grade = 100 , Name = LiSi
ID = 3 , Age = 27 , Grade = 89 , Name = KangKang
ID = 4 , Age = 19 , Grade = 92 , Name = LiMing
ID = 5 , Age = 22 , Grade = 66 , Name = WangGang
ID = 6 , Age = 24 , Grade = 85 , Name = ZhaoXin
ID = 7 , Age = 20 , Grade = 78 , Name = LiuWei
ID = 8 , Age = 16 , Grade = 99 , Name = BaiZhanTang
------Sorted by Age(down)-----
ID = 1 , Age = 28 , Grade = 98 , Name = ZhangSan
ID = 3 , Age = 27 , Grade = 89 , Name = KangKang
ID = 6 , Age = 24 , Grade = 85 , Name = ZhaoXin
ID = 5 , Age = 22 , Grade = 66 , Name = WangGang
ID = 2 , Age = 21 , Grade = 100 , Name = LiSi
ID = 7 , Age = 20 , Grade = 78 , Name = LiuWei
ID = 4 , Age = 19 , Grade = 92 , Name = LiMing
ID = 8 , Age = 16 , Grade = 99 , Name = BaiZhanTang
------Sorted by Grade-----
ID = 5 , Age = 22 , Grade = 66 , Name = WangGang
ID = 7 , Age = 20 , Grade = 78 , Name = LiuWei
ID = 6 , Age = 24 , Grade = 85 , Name = ZhaoXin
ID = 3 , Age = 27 , Grade = 89 , Name = KangKang
ID = 4 , Age = 19 , Grade = 92 , Name = LiMing
ID = 1 , Age = 28 , Grade = 98 , Name = ZhangSan
ID = 8 , Age = 16 , Grade = 99 , Name = BaiZhanTang
ID = 2 , Age = 21 , Grade = 100 , Name = LiSi
------Sorted by Name-----
ID = 8 , Age = 16 , Grade = 99 , Name = BaiZhanTang
ID = 3 , Age = 27 , Grade = 89 , Name = KangKang
ID = 4 , Age = 19 , Grade = 92 , Name = LiMing
ID = 2 , Age = 21 , Grade = 100 , Name = LiSi
ID = 7 , Age = 20 , Grade = 78 , Name = LiuWei
ID = 5 , Age = 22 , Grade = 66 , Name = WangGang
ID = 1 , Age = 28 , Grade = 98 , Name = ZhangSan
ID = 6 , Age = 24 , Grade = 85 , Name = ZhaoXin
*/
三、文件与输入输出流
打开中的lunch.java文件,一次读取其中的一行,令每行形成一个String对象。然后利用java.util.Comparator接口重新定义String对象间的比较方法:将每个String中的小写字母转为大写后再进行比较。使用该比较法对这些String进行排序,按从大到小的顺序存入一个LinkedList。最后将LinkedList中的String按存入的相反顺序输出到另一个文件inverse.txt中。
lunch.java文件如下图所示:
思路
首先利用java.util.Comparator接口重新定义String对象间的比较方法,由于实现接口不能降低方法的可视性,在新的方法中仍然使用public修饰,返回值为了两个String类型都转化为大写,即调用toUpperCase方法,继而调用campareTo方法比较两个字符串;接着读入文件的数据,因为要按行处理,因此使用BufferedReader读入,继而使用ArrayList容纳每一行的字符串,并用try catch块包裹;后面使用foreach语句打印至控制台查看读取效果,使用题目2的排序方法,对list中的字符串按要求排序,最后写入文件即可。
收获
这个题目涉及的知识点有:接口的实现,文件的读取与写入,字符串的大小写转换,字符串的排序。首先利用java.util.Comparator接口重新定义String对象间的比较方法,调用toUpperCase方法转化为大写,继而调用campareTo方法比较两个字符串;接着使用BufferedReader按行读入文件数据,使用ArrayList容纳,;使用foreach语句打印至控制台便于查看,建立比较器,使用lambda语句将list内容按要求排序,使用FileWriter类,调用.write方法将排序好的数据写入目标文件。
源码
package java_exp2022;
import java.io.*;
import java.util.*;
class ComparatorNew implements Comparator<String>{
public int compare(String o1, String o2) {
return o1.toUpperCase().compareTo(o2.toUpperCase());
}
}
public class Project3 {
public static void main(String[] args) {
System.out.println("请将lunch.java文件放置于D://javatest//"
+ "\n最终的inverse.txt文件也为存于此目录下");
File f = new File("D://javatest//lunch.java");
File f_wr = new File("D://javatest//inverse.txt");
try {
BufferedReader br = new BufferedReader(new FileReader(f));
ArrayList<String> str = new ArrayList<String>();
String temp = null;
while( (temp = br.readLine() ) != null )
str.add(temp);
System.out.println("--------before-------");
for(String s : str)
System.out.println(s);
ComparatorNew com = new ComparatorNew();
str.sort( (String s1,String s2) -> com.compare(s1,s2));
LinkedList<String> l_str = new LinkedList<String>();
System.out.println("--------sorted-------");
for(String s : str) {
l_str.add(s);
System.out.println(s);
}
int num = l_str.size();
FileWriter wr = new FileWriter(f_wr);
f_wr.createNewFile();
System.out.println("--------turn around-------");
for(int i = num-1 ; i>=0 ; i--) {
System.out.println(l_str.get(i));
wr.write(l_str.get(i)+"\n");
}
wr.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出结果
四、综合编程题
一个图书管理系统的面向对象设计方案如下图所示:
Book代表书,有”Name(书名)“、“Author(作者)”、”Price(价格)“、”IsBorrowed(是否借出)”四个属性。类Library代表图书馆,其内部字段books用于保存图书馆中所有的书,他的FindBook()方法依据书名查找同名的书(可能有多本)。另一个Get AllBooks()方法获取馆藏所有书的详细信息。类Reader代表作者,Name字段代表其姓名,读者可以进行BorrowBook()(借书),ReturnBook():(还书)操作。
请完成以下工作:
- 用Java编程实现以上三个类。
- 在main()方法内书写以下测试代码:
(1) 创建一个Library的类的实例,myLittleLibrary,其中预存有以下三本书:
Java程序设计,张三著,45元
Java核心设计,李四著,50元
Java程序设计,王五著,38元
(2) 显示图书馆所有图书的信息,输出样例如下:
Java程序设计,张三著,45元,可借
Java核心设计,李四著,50元,可借
Java程序设计,王五著,38元,未还
(3) 创建一个Reader类的实例oneBeautifulGril,她先在myLittleLibrary中查找《Java程序设计》;
(4) 当oneBeautifulGril借了张三著的那一本书时,显示图书馆所有图书的信息;
(5) oneBeautifulGril把书还了,再次显示图书馆中图书信息;
思路
我们需要建立一个Library类,类中有一个ArrayList成员,用于存储所有图书的信息和借出状态,还包含FindBook方法,GetAllBooks方法。Book类包含书名、作者、价格、借出状态。Reader类包含名字、借书方法,还书方法。主要使用了构造器初始化,foreach遍历方法等。
我还额外考虑了题目之外的借书失败,还书错误等情况。
源码
package java_exp2022;
import java.util.*;
class Book{
String Name;
String Author;
int Price;
boolean IsBorrowed = false ;
Book(String _Name,String _Author,int _Price){
Name = _Name;
Author = _Author;
Price = _Price;
}
}
class Reader{
String Name;
Reader(String name){
Name = name ;
}
void BorrowBook(Library lib,String bookname,String authorname) {
boolean Ifsuccess = false ;
for(Book b : lib.books) {
Ifsuccess = false ;
if(b.Name == bookname && b.Author == authorname && !b.IsBorrowed) {
b.IsBorrowed = true ;
Ifsuccess = true ;
break;//借到就退出
}
}
if(Ifsuccess) System.out.println(this.Name+" 成功借出 "+bookname+authorname+"著");
else System.out.println(this.Name+" 借书失败 ,没有书目"+bookname+authorname+"著");
}
void ReturnBook(Library lib,String bookname,String authorname) {
boolean Ifsuccess = false ;
for(Book b : lib.books) {
Ifsuccess = false ;
if(b.Name == bookname && b.Author == authorname && b.IsBorrowed) {
b.IsBorrowed = false ;
Ifsuccess = true ;
break;//还完就退出
}
}
if(Ifsuccess) System.out.println(this.Name+" 成功还书 "+bookname+authorname+"著");
else System.out.println(this.Name+" 还书失败 ,"+bookname+authorname+"著 不是我们图书馆的");
}
}
class Library{
ArrayList<Book> books = new ArrayList<Book>();
void FindBook(String bookname) {
boolean Ifcontain = false ;
System.out.println("图书"+bookname+"查找结果如下:");
for(Book b : books) {
if(b.Name != bookname)
continue;//不是目标图书继续检索
Ifcontain = true ;
String status = null;
if(b.IsBorrowed) status = "未还";
else status = "可借";
System.out.print(b.Name+", "+b.Author
+"著, "+b.Price+"元, "+status+"\n");
}
if(!Ifcontain)System.out.println("查无此书");
}//获得特定书名的书,可能会有重名书
void GetAllBooks() {
System.out.println("图书馆所有图书的信息如下:");
for(Book b : books) {
String status = null;
if(b.IsBorrowed) status = "未还";
else status = "可借";
System.out.print(b.Name+", "+b.Author
+"著, "+b.Price+"元, "+status+"\n");
}
}
}
public class Project6 {
public static void main(String[] args) {
Library myLittleLibrary = new Library();
myLittleLibrary.books.add(new Book("《Java程序设计》","张三",45) );
myLittleLibrary.books.add(new Book("《Java核心设计》","李四",50) );
myLittleLibrary.books.add(new Book("《Java程序设计》","王五",38) );
myLittleLibrary.GetAllBooks();
Reader oneBeautifulGril = new Reader("oneBeautifulGril");
myLittleLibrary.FindBook("《Java程序设计》");
oneBeautifulGril.BorrowBook(myLittleLibrary, "《Java程序设计》", "张三");
myLittleLibrary.GetAllBooks();
oneBeautifulGril.ReturnBook(myLittleLibrary, "《Java程序设计》", "张三");
myLittleLibrary.GetAllBooks();
System.out.println("\n以下内容为出错示例");
myLittleLibrary.FindBook("《错误书名示例》");
oneBeautifulGril.BorrowBook(myLittleLibrary, "《错误书名示例》", "小明");
oneBeautifulGril.ReturnBook(myLittleLibrary, "《错误书名示例》", "小明");
}
}
/*OutPut
图书馆所有图书的信息如下:
《Java程序设计》, 张三著, 45元, 可借
《Java核心设计》, 李四著, 50元, 可借
《Java程序设计》, 王五著, 38元, 可借
图书《Java程序设计》查找结果如下:
《Java程序设计》, 张三著, 45元, 可借
《Java程序设计》, 王五著, 38元, 可借
oneBeautifulGril 成功借出 《Java程序设计》张三著
图书馆所有图书的信息如下:
《Java程序设计》, 张三著, 45元, 未还
《Java核心设计》, 李四著, 50元, 可借
《Java程序设计》, 王五著, 38元, 可借
oneBeautifulGril 成功还书 《Java程序设计》张三著
图书馆所有图书的信息如下:
《Java程序设计》, 张三著, 45元, 可借
《Java核心设计》, 李四著, 50元, 可借
《Java程序设计》, 王五著, 38元, 可借
以下内容为出错示例
图书《错误书名示例》查找结果如下:
查无此书
oneBeautifulGril 借书失败 ,没有书目《错误书名示例》小明著
oneBeautifulGril 还书失败 ,《错误书名示例》小明著 不是我们图书馆的
*/