Java语言程序设计 习题第十三章

13.1章节习题

13.1 在下面类的定义中,哪些定义了合法的抽象类?

a)

//错误,有只有抽象类中才能有抽象方法
class A {abstract void unfinished() {}
}

b)

// 关键字abstract写错了位置,应该写在class前面
// 习惯上会将访问修饰符(如 public、protected、private)放在前面,而将其他修饰符(如 abstract、final、static)放在后面
public class abstract A {abstract void unfinished();
}

c)

// 错误,有只有抽象类中才能有抽象方法
class A {abstract void unfinished():
}

d)

// 错误,抽象类中的普通方法需要有{},不能省略
abstract class A {protected void unfinished();
}

e)

// 正确
abstract class A {abstract void unfinished();
}

f)

// 正确
abstract class A {abstract int unfinished();
}

13.2 getArea() 方法和 getPerimeter() 方法可以从 GeometricObject 类中删除。在 GeometricObject 类中将这两个方法定义为抽象方法的好处是什么?

在编译(compilation)期,一个声明为GeometricObject的对象可以使用这两个方法

否则,就没办法计算周长和面积

13.3 下面说法为真还是为假?

a. 除了不能使用 new 操作符创建抽象类的实例之外,一个抽象类可以像非抽象类一样使用。

b. 抽象类可以被继承

c. 非抽象的父类的子类不能是抽象的

d. 子类不能将父类中的具体方法重写,并定义为抽象的

e. 抽象方法必须是非静态的

13.3章节习题

13.4 为什么下面两行代码可以编译成功,但是会导致运行错误?

// 第二行等号右侧想要把Integer类型的numberRef转换为Double类型,而Integer和Double没有继承关系,如果Double是Integer的父类,就会运行成功
Number numberRef = new Integer(0);
Double doubleRef = (Double)numberRef;

13.5 为什么下面两行代码可以编译成功,但是会导致运行错误?

//和上一题类似,不能把Double转换成Integer
Number[] numberArray = new Integer[2];
numberArray[0] = new Double(1.5);

13.6 给出下面代码的输出。

public class Test {public static void main(String[] args) {Number x = 3;System.out.println(x.intValue());System.out.println(x.doubleValue());}
}
3
3.0

13.7 下面代码有什么错误? (注意,Integer和Double类的compareTo方法在第10.7节中进行了介绍)

// 很好的例子,因为compareTo只是Integer和Double的方法,并不是Number的方法
public class Test {public static void main(String[] args) {Number x = new Integer(3);System.out.println(x.intValue());System.out.println(x.compareTo(new Integer(4)));}
}

13.8 下面代码中有什么错误?

// 很好的例子,11章讲过,“.”是成员对象访问符,运算顺序优先于类型转化。所以编译器会先检查x.compareTo,自然不通过,理由在上一题
//应该改成((Integer)x).compareTo(new Integer(4))
public class Test {public static void main(String[] args) {Number x = new Integer(3);System.out.println(x.intValue());System.out.println((Integer)x.compareTo(new Integer(4)));}
}

13.4 章节习题

13.9 可以使用Calendar类来创建一个Calendar对象吗?

不可以,Calendar是一个抽象类

13.10 Calendar类中哪个方法是抽象的?

add方法

13.11 如何为当前时间创建一个 Calendar 对象?

GregorianCalendar的无参构造方法

13.12 对于一个 Calendar 对象 c 而言,如何得到它的年、月、日期 、小时 、分钟以及秒钟?

package learning;import java.util.Calendar;
import java.util.GregorianCalendar;public class Test {public static void main(String[] args) {Calendar c = new GregorianCalendar();System.out.println(c.get(Calendar.YEAR));System.out.println(c.get(Calendar.MONTH));System.out.println(c.get(Calendar.DAY_OF_MONTH));System.out.println(c.get(Calendar.HOUR));System.out.println(c.get(Calendar.MINUTE));System.out.println(c.get(Calendar.SECOND)); }
}

输出结果:

需要注意的是,Calendar类中的MONTH是从0计数的

2023
4
15
9
35
25

13.5章节习题

13.13 假设A是一个接口,可以使用newA()创建一个实例吗?

不可以

13.14 假设A是一个接口,可以如下声明一个类型A的引用变量x吗?

A x;

可以

13.15 下面哪个是正确的接口?

// 在抽象类中,既可以有抽象方法(没有方法体),也可以有具体的方法(有方法体),子类继承抽象类后,必须实现抽象方法,可以选择性的实现具体的方法
// 在旧版本的Java中,接口只能包含抽象方法,这些方法没有方法体。但是,自Java 8开始,接口也可以包含默认方法和静态方法
(a)
// 错误,接口不能有方法体
interface A {    void print() { }
} (b)
// 错误,接口不能用abstract修饰,接口不能有方法体
abstract interface A {    abstract void print() { }
}(c)
// 错误,接口不能用abstract修饰
abstract interface A {    print();
} (d)
//正确
interface A {   void print();
}(e)
//正确
interface A {    default void print() {}
} (f)
//正确
interface A {    static int get() {return 0;}
}

13.16 指出下面代码中的错误

// 在接口中声明的方法默认是public的,因此在实现接口方法时,必须使用public访问修饰符进行修饰
interface A {void m1();
}class B implements A {void m1() {System.out.println("m1");}
}

13.6章节习题

13.17 下面说法为真还是为假? 如果一个类实现了Comparable, 那么该类的对象可以调用 compareTo 方法

正确

13.18 下面哪个是正确的 String 类中的 compareTo 方法的方法头?

// compareTo比较当前对象
public int compareTo(String o)
public int compareTo(Object o)

13.19 下面代码可以被编译吗? 为什么?

// 不可以,因为对象类型不一致
Integer n1 = new Integer(3);
Object n2 = new Integer(4);
System.out.println(n1.compareTo(n2));

13.20 可以在类中定义 compareTo 方法而不实现 Comparable 接口。实现 Comparable 接口的好处是 什么?

通过实现 Comparable 接口,可以将类的对象传递给需要 Comparable 类型的方法。

13.21 下面的代码有什么错误?

// Person类没有实现Comparable接口,而sort方法是依赖Camparable的
public class Test {public static void main(String[] args) {Person[] persons = {new Person(3), new Person(4), new Person(1)};java.util.Arrays.sort(persons);}
}class Person {private int id;Person(int id) {this.id = id;         }
}

13.7章节习题

13.22 如果一个对象的类没有实现 java.lang.Cloneable, 可以调用 clone() 方法来克隆这个对象吗? Date 类实现了 Cloneable 接口吗?

在编译阶段不会报错,可以正常编译。但是在运行阶段会报异常。因此,如果在main方法想要调用a.clone(),a对象所在的类必须实现Cloneable

实现了。如果没有实现,克隆时会报异常

13.23 如果 House 类(在程序清单 13-11 中定义)没有覆盖 clone() 方法,或者如果 House 类没有实现java.lang.Cloneable, 会发生什么?

如果没有覆盖clone(),编译器会报错

如果没有实现Cloneable,会报异常

13.24 给出下面代码的输出结果

java.util.Date date = new java.util.Date();
java.util.Date date1 = date;
java.util.Date date2 = (java.util.Date)(date.clone()); System.out.println(date == date1);
System.out.println(date == date2); System.out.println(date.equals(date2));
true
false
true

13.25 给出下面代码的输出结果

ArrayList<String> list = new ArrayList<>();list.add("New York");ArrayList<String> list1 = list;ArrayList<String> list2 = (ArrayList<String>)(list.clone()); list.add("Atlanta");System.out.println(list == list1); System.out.println(list == list2); System.out.println("list is " + list); System.out.println("list1 is " + list1); System.out.println("list2.get(0) is " + list2.get(0)); System.out.println("list2.size() is " + list2.size());
true
false
list is [New York, Atlanta]
list1 is [New York, Atlanta]
list2.get(0) is New York
list2.size() is 1

13.26 下面的代码有什么错误?

// 实现接口,重写方法
public class Test {public static void main(String[] args) {GeometricObject x = new Circle(3); GeometricObject y = x.clone(); System.out.println(x == y);}
}

13.8章节习题

13.27 给出一个例子显示接口相对于抽象类的优势。

多重继承

13.28 给出抽象类和接口的定义。抽象类和接口之间的相同点和不同点是什么?

  1. 定义:接口是一种完全抽象的类,只包含方法的声明而没有实现;抽象类是一个可以包含抽象方法和具体方法实现的类。
  2. 实现方式:一个类可以有多个接口,但只能继承一个类。
  3. 构造函数:接口没有构造方法,而抽象类可以有构造方法。
  4. 成员变量:接口中只能定义常量,不能定义实例变量;抽象类可以包含实例变量。
  5. 接口之间的继承:接口可以继承多个接口,形成接口之间的继承关系;抽象类之间只能通过类继承实现继承关系。

13.29 真或者假?

a。接口被编译为独立的字节码文件。

b。接口可以有静态方法。

c。接口可以扩展一个或多个接口。

d。接口可以扩展抽象类。

e。抽象类可以扩展接口。

13.9章节习题

13.30 给出下面代码的输出。

Rational r1 = new Rational(-2, 6);
System.out.println(r1.getNumerator());
System.out.println(r1.getDenominator());
System.out.println(r1.intValue());
System.out.println(r1.doubleValue());
-1
3
0
-0.3333333333333333

13.31 下面的代码错在何处?

// Object类没有compareTo方法
Rational r1 = new Rational(-2, 6);
Object r2 = new Rational(1, 45); System.out.println(r2.compareTo(r1));

13.32 下面的代码错在何处?

//调用方和参数必须都是Rational类型
Object r1 = new Rational(-2, 6);
Rational r2 = new Rational(1, 45); System.out.println(r2.compareTo(r1));

13.33 如何使用一行代码,而不使用if语句来简化程序清单13-13中82 - 85行的代码?

public boolean equals(Object o) {return (this.subtract((Rational)(other))).getNumerator() == 0;
}public int compareTo(Rational o) {return this.subtract(o).getNumerator() > 0 ? 1 :(this.subtract(o).getNumerator() == 0 ? 0 : 1);
}

13.34 仔细地跟踪程序的执行,给出下面代码的输出。

Rational r1 = new Rational(1, 2);
Rational r2 = new Rational(1, -2); System.out.println(r1.add(r2));
0/4

13.10章节习题

13.35 描述类的设计原则。

13.10.1 内聚性

13.10.2 — 致性

13.10.3 封装性

13.10.4 清晰性

13.10.5 完整性

13.10.6 实例和静态

13.10.7 继承与聚合

13.10.8 接口和抽象类

编程练习题

**13.1(三角形类)

设计一个扩展自抽象类GeometricObject的新的Triangle类。绘制Triangle类和GeometricObject类的UML图并实现Triangle类。编写一个测试程序,提示用户输入三角形的三条边、一种颜色以及一个表明该三角形是否填充的布尔值。程序应该根据用户的输入, 使用这些边以及颜色和是否填充的信息,创建一个Triangle对象。程序应该显示面积、周长、 颜色以及真或者假来表明是否被填充。

Test.java

package learning;import java.util.Scanner;public class  Test {public static void main(String[] args) {System.out.print("Input 3 sides of a triangle accordingly: ");Scanner scanner = new Scanner(System.in);double side1 = scanner.nextDouble();double side2 = scanner.nextDouble();double side3 = scanner.nextDouble();System.out.print("Input the color: ");String color = scanner.next();System.out.print("Input the fill status(true / false): ");boolean filled = scanner.nextBoolean();Triangle test1 = new Triangle(side1, side2, side3, color, filled);System.out.print(test1.toString());scanner.close();}
}

GeometricObject.java

package learning;abstract class GeometricObject {String color;boolean filled;abstract double getPerimeter();abstract double getArea();
}

Triangle.java

package learning;//__________________________UML DIAGRAM_____________________________*
/*                                                                  |
*                        /GeometricObject/                          |
*-------------------------------------------------------------------|
*   color: String                                                   |
*   filled: boolean                                                 |
*-------------------------------------------------------------------|
*   /getArea()/: double/                                            |
*   /getPerimeter(): double/                                        |
*___________________________________________________________________| ^^^
//______________________________________________________________________________________________|
/*                                                                                              |
*                                         Triangle                                              |
* ----------------------------------------------------------------------------------------------|
*    side1: double                                                                              |
*    side2: double                                                                              |
*    side3: double                                                                              |
* ----------------------------------------------------------------------------------------------|
*    Triangle()                                                                                 |
*    Triangle(side1:double, side2:double, side3:double, color:String, filled:boolean)           |
*    getPerimeter(): double                                                                     |
*    getArea(): double                                                                          |
*    +toString(): String                                                                       |
*_______________________________________________________________________________________________|*/class Triangle extends GeometricObject {double side1;double side2;double side3;Triangle() {}Triangle(double side1, double side2, double side3, String color, boolean filled) {this.side1 = side1;this.side2 = side2;this.side3 = side3;this.color = color;this.filled = filled;}@Overridedouble getPerimeter() {return side1 + side2 + side3;}@Overridedouble getArea() {return Math.pow((getPerimeter() * 0.5) * (getPerimeter() - side1) * (getPerimeter() - side2) * (getPerimeter() - side3), 0.5);}@Overridepublic String toString() {if (filled == true) {return "The Perimeter is " + getPerimeter() + " and the area is " + getArea() + ".\nThis triangle is " + color + " and filled.";}return "The Perimeter is " + getPerimeter() + " and the area is " + getArea() + ".\nThis triangle is " + color + " and not filled.";}
}

输出结果:

Input 3 sides of a triangle accordingly: 3 4 5
Input the color: blue
Input the fill status(true / false): true
The Perimeter is 12.0 and the area is 54.99090833947008.
This triangle is blue and filled.
*13.2 (打乱ArrayList)

编写以下方法,打乱ArrayList里面保存的数字

public static void shuffle(ArrayList<Number> list)
package learning;import java.util.ArrayList;// 代码的大意是,把初始的list数组创建为1-10的顺序数列,再使用temp数组随机生成0-9的乱序数列,用temp的元素作为list的参数,依次传递给afterShuffle数组,所以打乱完成
// 例如,temp的第一个元素是5,那么就把原数组list中的第5号元素,挪动到新数组afterShuffle中,相当于temp数组充当了参数
public class  Test {// 用户可以设置希望打乱多大的数组,本例中设置为10private final static int SIZE = 10;public static void main(String[] args) {// 把1-10按顺序加进初始list数组ArrayList<Number> list = new ArrayList<>();for (int i = 1; i <= SIZE; i++) {list.add(i);}System.out.print("The original array is: ");System.out.println(list.toString());// 执行打乱方法shuffle(list);}public static void shuffle(ArrayList<Number> list) {// 创建一个暂时的数组temp,用于储存随机的参数ArrayList<Number> temp = new ArrayList<>();// 只要这个temp的长度没有超过用户设置的“10”,就执行循环,添加新的随机参数到数组中while (temp.size() < SIZE) {// 随机生成一个0 - 10的数字,如果这个数字没有被添加过,就把这个数字添加进去// 循环结束后,temp数组由0-9的乱序数列组成int index = (int)(Math.random() * SIZE);if (!temp.contains(index)) {temp.add(index);}}ArrayList<Number> afterShuffle = new ArrayList<>();/* 循环解释:* 假设* list = [1, 2, 3, 4, 5]* temp = [3, 1, 4, 5, 2]* 那么* 把temp[0]元素3拿出来,执行list.get(3),结果是4,把结果赋值给afterShuffle的第一位元素,因此afterShuffle的第一位元素是4* 把temp[1]元素1拿出来,执行list.get(1),结果是2,把结果赋值给afterShuffle的第一位元素,因此afterShuffle的第二位元素是2* ......以此类推*/for (int i = 0; i < SIZE; i++) {//这里需要类型转换的原因是,内圈temp.get(i)得到的数字类型是Number,而外圈list.get()方法需要一个Integer参数afterShuffle.add(list.get((int) temp.get(i)));}System.out.print("The shuffled array is: ");System.out.println(afterShuffle.toString());}
}

输出结果:

The original array is: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
The shuffled array is: [9, 5, 2, 3, 8, 1, 4, 6, 7, 10]
*13.3 (排序ArrayList)

编写以下方法,对 ArrayList 里面保存的数字进行排序。

public static void sort(ArrayList<Number> list)
package learning;import java.util.ArrayList;
import java.util.Arrays;//使用冒泡排序,在方法内先把ArrayList转化成int[]
public class  Test {public static void main(String[] args) {ArrayList<Number> list = new ArrayList<>();list.add(5);list.add(9);list.add(2);list.add(7);list.add(3);System.out.print("初始排序 :"); System.out.println(list.toString());   sort(list);}public static void sort(ArrayList<Number> list) {int[] arr = new int[list.size()];for (int i = 0; i < list.size(); i++) {arr[i] = (int)list.get(i);}for (int i = arr.length - 1; i > 0; i--) { //外圈决定循环次数:规律是(length-1)次for (int j = 0; j < i; j++) { // 内圈决定交换次数,规律一个length为n的数组只需交换(n-1)次(i次,j初始值为0所以无“=”)即可实现最大值冒泡if (arr[j] > arr[j + 1]) {// 交换int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}System.out.println("最终排序 :" + Arrays.toString(arr)); //for外只输出最终数组}
}

输出结果:

初始排序 :[5, 9, 2, 7, 3]
最终排序 :[2, 3, 5, 7, 9]
**13.4 (显示日历)

重写程序清单6-12中的PrintCalendar类,使用Calendar和GregorianCalendar类显示一个给定月份的日历。你的程序从命令行得到月份和年份的输入,例如:

java Exercisel3_04 5 2016

也可以不输入年份来运行程序。这种情况下,年份就是当前年份。 如果不指定月份和年份来运行程序,那么就是指当前月份

package learning;import java.util.Calendar;
import java.util.GregorianCalendar;public class Test {/** Main method */public static void main(String[] args) {Calendar calendar = new GregorianCalendar();if (args.length == 2) {printMonth(Integer.parseInt(args[1]), Integer.parseInt(args[0]));}if (args.length == 1) {printMonth(calendar.get(Calendar.YEAR), Integer.parseInt(args[0]));}if (args.length == 0) {printMonth(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1);}}/** Print the calendar for a month in a year */public static void printMonth(int year, int month) {// Print the headings of the calendarprintMonthTitle(year, month);// Print the body of the calendarprintMonthBody(year, month);}/** Print the month title, e.g., May, 1999 */public static void printMonthTitle(int year, int month) {System.out.println("         " + getMonthName(month)+ " " + year);System.out.println("-----------------------------");System.out.println(" Sun Mon Tue Wed Thu Fri Sat");}/** Get the English name for the month */public static String getMonthName(int month) {String monthName = "";switch (month) {case 1: monthName = "January"; break;case 2: monthName = "February"; break;case 3: monthName = "March"; break;case 4: monthName = "April"; break;case 5: monthName = "May"; break;case 6: monthName = "June"; break;case 7: monthName = "July"; break;case 8: monthName = "August"; break;case 9: monthName = "September"; break;case 10: monthName = "October"; break;case 11: monthName = "November"; break;case 12: monthName = "December";}return monthName;}/** Print month body */public static void printMonthBody(int year, int month) {// Get start day of the week for the first date in the monthint startDay = getStartDay(year, month);// Get number of days in the monthint numberOfDaysInMonth = getNumberOfDaysInMonth(year, month);// Pad space before the first day of the monthint i = 0;for (i = 0; i < startDay; i++)System.out.print("    ");for (i = 1; i <= numberOfDaysInMonth; i++) {System.out.printf("%4d", i);if ((i + startDay) % 7 == 0)System.out.println();}System.out.println();}/** Get the start day of month/1/year */public static int getStartDay(int year, int month) {final int START_DAY_FOR_JAN_1_1800 = 3;// Get total number of days from 1/1/1800 to month/1/yearint totalNumberOfDays = getTotalNumberOfDays(year, month);// Return the start day for month/1/yearreturn (totalNumberOfDays + START_DAY_FOR_JAN_1_1800) % 7;}/** Get the total number of days since January 1, 1800 */public static int getTotalNumberOfDays(int year, int month) {int total = 0;// Get the total days from 1800 to 1/1/yearfor (int i = 1800; i < year; i++)if (isLeapYear(i))total = total + 366;elsetotal = total + 365;// Add days from Jan to the month prior to the calendar monthfor (int i = 1; i < month; i++)total = total + getNumberOfDaysInMonth(year, i);return total;}/** Get the number of days in a month */public static int getNumberOfDaysInMonth(int year, int month) {if (month == 1 || month == 3 || month == 5 || month == 7 ||month == 8 || month == 10 || month == 12)return 31;if (month == 4 || month == 6 || month == 9 || month == 11)return 30;if (month == 2) return isLeapYear(year) ? 29 : 28;return 0; // If month is incorrect}/** Determine if it is a leap year */public static boolean isLeapYear(int year) {return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);}
}

输出结果:

// 不指定年月
java /Users/kevinwang/eclipse-workspace/test/src/learning/Test.javaMay 2023
-----------------------------Sun Mon Tue Wed Thu Fri Sat1   2   3   4   5   67   8   9  10  11  12  1314  15  16  17  18  19  2021  22  23  24  25  26  2728  29  30  31
*13.5 (将 GeometricObject 类变成可比较的)

修改 GeometricObject 类以实现 Comparable 接口,并且在 GeometricObject 类中定义一个静态的求两个 GeometricObject 对象中较大者的 max 方法。画出 UML 图并实现这个新的 GeometricObject 类。编写一个测试程序,使用 max 方法求两个圆中的较大者和两个矩形中的较大者。

Test.java

package learning;public class Test {public static void main(String[] args) {GeometricObject circle1 = new Circle(1);GeometricObject circle2 = new Circle(10);// max方法会利用多态,将声明为GeometricObject类型的变量匹配到Circle类型的方法GeometricObject.max(circle1, circle2);GeometricObject rec1 = new Rectangle(3, 5);GeometricObject rec2 = new Rectangle(10, 20);// max方法会利用多态,将声明为GeometricObject类型的变量匹配到Rectangle类型的方法GeometricObject.max(rec1, rec2);}
}

GeometricObject.java

package learning;//__________________________UML DIAGRAM_____________________________*
/*                                                                  |
*                        /GeometricObject/                          |
*-------------------------------------------------------------------|
*   color: String                                                   |
*   filled: boolean                                                 |
*-------------------------------------------------------------------|
*   /getArea: double/                                               |
*   +compareTo(o: GeometricObject): int                                |
*   +___max(obj1: GeometricObject, obj2: GeometricObject): void___ |
*   +toString(): String                                                |
* __________________________________________________________________| */abstract class GeometricObject implements Comparable<GeometricObject>{String color;boolean filled;abstract double getArea();// Comparable接口实现了compareTo方法,实现这个接口的抽象类GeometricObject需要覆写,如果当前抽象类没有覆写,继承抽象类的常规子类就必须覆写@Overridepublic int compareTo(GeometricObject o) {if (getArea() > o.getArea())return 1;else if (getArea() < o.getArea())return -1;else return 0;}// max方法会先调用上面的compareTo方法,得到返回值,根据返回值,调用toString方法进行输出public static void max(GeometricObject obj1, GeometricObject obj2) {if (obj1.compareTo(obj2) == 1)System.out.println(obj1.toString());else if (obj1.compareTo(obj2) == -1)System.out.println(obj2.toString());elseSystem.out.println("Equal");}// 需要注意的是,如果GeometricObject类,Circle类和Rectangle类都覆写了toString,那么调用哪个toString,会根据多态,取决于变量的实际类型// 如果Circle类和Rectangle类没有覆写toString,那么就会调用GeometricObject类的toString// 例如,GeometricObject类,Circle类和Rectangle类都覆写了toString,那么下面的toString就不会被调用@Overridepublic String toString() {return "I will not be invoked";}
}

Circle.java

package learning;class Circle extends GeometricObject{double radius;Circle(double radius) {this.radius = radius;}// GeometricObject实现了抽象方法getArea,子类必须强制调用@Overridedouble getArea() {return Math.PI * radius * radius;}@Overridepublic String toString() {return "The " + radius + " radius object is larger";}
}

Rectangle.java

package learning;class Rectangle extends GeometricObject{double width;double height;Rectangle(double width, double height) {this.width = width;this.height = height;}// GeometricObject实现了抽象方法getArea,子类必须强制调用@Overridedouble getArea() {return Math.PI * width * height;} @Overridepublic String toString() {return "The " + width + " width and " + height + " height object is larger";}
}

输出结果:

The 10.0 radius object is larger
The 10.0 width and 20.0 height object is larger
*13.6 (ComparableCircle类)

创建名为 ComparableCircle 的类,它继承自 Circle 类,并实现 Comparable 接口。画出 UML 图并实现 compareTo 方法,使其根据面积比较两个圆。编写一个测试程序求出 ComparableCircle 对象的两个实例中的较大者。

Test.java

package learning;//___________________________UML DIAGRAM____________________________|
/*                                                                  |
*                                Circle                             |
*-------------------------------------------------------------------|
*    radius: double                                                 |
*-------------------------------------------------------------------|
*    Circle()                                                       |
*    Circle(radius: double)                                         |
*    getArea(): double                                              |
* __________________________________________________________________| */
/*                            ^^^
//_____________________UML DIAGRAM_________________________________|
/*                                                                 |
*                     ComparableCircle                             |
*------------------------------------------------------------------|                    //_______________________________________________|
*    radius: double                                                |                    *                <<interface>>                   *
*    ComparableCircle()                                            |<<<<<<<<<<<<<<<<<<<<*                  Comparable                    |
*    ComparableCircle(radius: double)                              |                    *      +compareTo(circle: ComparableCircle): int |
*    getArea(): double                                             |                    //_______________________________________________|
*    +compareTo(o: comparableCircle): int                         |
*__________________________________________________________________| */                    public class Test {public static void main(String[] args) {ComparableCircle test1 = new ComparableCircle(5);ComparableCircle test2 = new ComparableCircle(10);System.out.print(test1.compareTo(test2));}
}

Circle.java

package learning;class Circle {double radius;Circle() {radius = 1;}Circle(double radius) {this.radius = radius;}double getArea() {return Math.PI * radius * radius;}
}

ComparableCircle.java

package learning;class ComparableCircle extends Circle implements Comparable<ComparableCircle> {double radius;ComparableCircle() {super();}ComparableCircle(double radius) {this.radius = radius;}@Overridedouble getArea() {return Math.PI * radius * radius;}@Overridepublic int compareTo(ComparableCircle o) {if (getArea() > o.getArea())return 1;else if (getArea() < o.getArea())return -1;elsereturn 0;}
}

输出结果:

-1
*13.7 (可着色接口Colorable)

设计一个名为 Colorable 的接口,其中有名为 howToColor() 的 void 方法。可着色对象的每个类必须实现 Colorable 接口。设计一个名为 Square 的类,继承自 CeometricObject 类并实现 Colorable 接口。实现 howToColor 方法,显示一个消息 Color all four sides(给所有的四条边着色)。

画出包含 Colorable、Square 和 CeometricObject 的 UML 图。编写一个测试程序,创建有五个 GeometricObject 对象的数组。对于数组中的每个对象而言,如果对象是可着色的, 那就调用 howToColor 方法。

Test.java

package learning;//___________________________UML DIAGRAM____________________________|
/*                                                                  |
*                           /GeometricObject/                       |
*-------------------------------------------------------------------|
*    color: String                                                  |
*    filled: boolean                                                |
*-------------------------------------------------------------------|
*    GeometricObject()                                              |
* __________________________________________________________________| */
/*                            ^^^
//_____________________UML DIAGRAM_________________________________|
/*                                                                 |
*                          Square                                  |
*------------------------------------------------------------------|
*    sides: double                                                 |                    //_______________________________________________|
*------------------------------------------------------------------|                    *                <<interface>>                   *
*    Square()                                                      |<<<<<<<<<<<<<<<<<<<<*                  Colorable                     |
*    Squaree(sides: double)                                        |                    *                howToColor(): void              |
*    +howToColor(): void                                          |                    //_______________________________________________|
*__________________________________________________________________| */                    public class Test {public static void main(String[] args) {Square square = new Square(5);square.howToColor();}
}

GeometricObject.java

package learning;abstract class GeometricObject {String color;boolean filled;GeometricObject() {}
}

Square.java

package learning;class Square extends GeometricObject implements Colorable {double sides;Square() {}Square(double sides){this.sides = sides;}@Overridepublic void howToColor() {System.out.println("Color all four sides");}
}

Colorable.java

package learning;interface Colorable {void howToColor();
}
*13.8 (修改MyStack类)

重写程序清单11-10中的MyStack类, 执行list域的深度复制

Test.Java

package learning;public class Test {public static void main(String[] args) throws CloneNotSupportedException {MyStack start = new MyStack();start.push(new String("One"));start.push(new String("Two"));start.push(new String("Three"));// 返回的stackCloned返回声明类型是Object,但是实际类型是MyStack,所以可以进行转换MyStack cloned = (MyStack) start.clone();// 通过==判断这两个对象其实是不共享内存的,后续的追加数据也是独立的System.out.println(cloned == start);start.push(new String("Four"));System.out.println("Cloned " + cloned.toString());System.out.println("Original " + start.toString());}}

MyStack.java

package learning;import java.util.ArrayList;public class MyStack implements Cloneable {private ArrayList<Object> list = new ArrayList<Object>();public int getSize() {return list.size();}public Object peek() {return list.get(getSize() - 1);}public Object pop() {Object obj = list.get(getSize() - 1);list.remove(getSize() - 1);return obj;}public void push(Object obj) {list.add(obj);}public int search(Object obj) {return list.indexOf(obj);}@Overridepublic Object clone() throws CloneNotSupportedException {// 深拷贝的逻辑是,创建一个新的内存空间,储存新对象,新旧对象互不干涉,所以就需要新建一个实例变量,用来储存新的对象// 创建一个新的实例变量stackCloned,先对start进行浅拷贝,将浅拷贝的结果储存进stackCloned// 其中,super.clone()相当于start.clone(),调用Object类的clone()方法进行克隆,start的实际类型是MyStack,所以转型可以成功MyStack stackCloned = (MyStack)super.clone();// 调用deepClone()方法,将深拷贝储存到stackCloned中,在这里我们需要深拷贝的是list字段,所以deepClone()方法针对list字段进行深拷贝stackCloned.list = deepClone();// 返回深拷贝后的stackCloned// 由于方法返回值类型是Object,所以可以返回任意子类类型// 但是需要注意的是,返回的stackCloned还是一个Object类型(实际类型是MyStack),后续如果需要,就要类型转换return stackCloned;}// 由于stackCloned.list = deepClone()语句中,我们是想要深拷贝list,而list的类型是ArrayList<Object>,所以下面方法的返回值也应该是ArrayList<Object>// 相当于在stackCloned对象中,储存了一个ArrayList<Object>字段ArrayList<Object> deepClone() {// 方法的逻辑是,新建一个ArrayList<Object>数组,一个一个元素复制对象的list字段,最后返回这个新建的数组ArrayList<Object> temp = new ArrayList<>();for (int i = 0; i < list.size(); i++) temp.add(list.get(i));return temp;}@Overridepublic String toString() {return "Stack: " + list.toString();}
}

输出结果:

false
Cloned Stack: [One, Two, Three]
Original Stack: [One, Two, Three, Four]
*13.9 (将 Circle 类改成可比较的)

改写程序清单13-2中的 Circle 类,它继承自 GeometricObject 类并实现 Comparable 接口。覆盖 Object 类中的 equals 方法。当两个 Circle 对象半径相等时,则这两个 Circle 对象是相同的。画出包括 Circle 、GeometricObject 和 Comparable 的 UML图。

Test.java

package learning;//___________________________UML DIAGRAM____________________________|
/*                                                                  |
*                           /GeometricObject/                       |
*-------------------------------------------------------------------|
*    color: String                                                  |
*    filled: boolean                                                |
*-------------------------------------------------------------------|
*    GeometricObject()                                              |
* __________________________________________________________________| */
/*                            ^^^
//_____________________UML DIAGRAM_________________________________|
/*                                                                 |
*                          Circle                                  |
*------------------------------------------------------------------|
*    -radius: double                                               |                    //_______________________________________________|
*------------------------------------------------------------------|                    *                <<interface>>                   *
*    +Circle()                                                    |<<<<<<<<<<<<<<<<<<<<*                  Comparable                    |
*    +Circle(radius: double)                                      |                    *                +compareTo(other T): int       |
*    +getArea(): double                                               |                    //_______________________________________________|
*    +compareTo(c: Circle): int                                       |
*    +equals(ob: Object): boolean                                 |
*__________________________________________________________________| */                    public class Test {public static void main(String[] args) throws CloneNotSupportedException {Circle c1 = new Circle(5);Circle c2 = new Circle(5);System.out.println(c1.equals(c2));System.out.println(c1.compareTo(c2));}
}

Circle.java

package learning;// 通常情况下,Comparable接口的范型参数应该是当前的类名,以指定要比较的对象是当前类的实例,但是其实类型可以是当前类的任意子类或父类
// Comparable接口的范型参数应该和compareTo方法的范型参数保持一致
public class Circle extends GeometricObject implements Comparable<Circle> {private double radius;public Circle() {}public Circle(double radius) {this.radius = radius;}public double getArea() {return radius * radius * Math.PI;}@Overridepublic int compareTo(Circle c) {if (getArea() > c.getArea())return 1;else if (getArea() < c.getArea())return -1;else return 0;}@Overridepublic boolean equals(Object ob) {Circle circle = (Circle) ob;return this.radius == circle.radius;}
}

GeometricObject.java

package learning;abstract class GeometricObject {String color;boolean filled;GeometricObject() {}
}

输出结果:

true
0
*13.10(将Rectangle类变成可比较的)

改写程序清单13-3的Rectangle类,它继承自GeometricObject类并实现Comparable接口。覆盖Object类中的equals方法。当两个Rectangle对象面积相同时,则这两个对象是相同的。画出包括Rectangle,GeometricObject和Comparable的UML图

Test.java

package learning;//___________________________UML DIAGRAM____________________________|
/*                                                                  |
*                           /GeometricObject/                       |
*-------------------------------------------------------------------|
*    color: String                                                  |
*    filled: boolean                                                |
*-------------------------------------------------------------------|
*    GeometricObject()                                              |
* __________________________________________________________________| */
/*                            ^^^
//_____________________UML DIAGRAM_________________________________|
/*                                                                 |
*                        Rectangle                                 |
*------------------------------------------------------------------|
*    -width: double         -height: double                        |                    //_______________________________________________|
*------------------------------------------------------------------|                    *                <<interface>>                   *
*    +Rectangle()                                                 |<<<<<<<<<<<<<<<<<<<<*                  Comparable                    |
*    +Rectangle(height: double, width: double)                    |                    *                +compareTo(other T): int       |
*    +getArea(): double                                               |                    //_______________________________________________|
*    +compareTo(obj: Rectangle): int                              |
*    +equals(ob: Object): boolean                                 |
*__________________________________________________________________| */                    public class Test {public static void main(String[] args) throws CloneNotSupportedException {Rectangle c1 = new Rectangle(5, 10);Rectangle c2 = new Rectangle(5, 10);System.out.println(c1.equals(c2));System.out.println(c1.compareTo(c2));}
}

GeometricObject.java

package learning;abstract class GeometricObject {String color;boolean filled;GeometricObject() {}
}

Rectangle.java

package learning;public class Rectangle extends GeometricObject implements Comparable<Rectangle> {private double width;private double height;public Rectangle() {}public Rectangle(double width, double height) {this.width = width;this.height = height;}public double getArea() {return width * height;}@Overridepublic int compareTo(Rectangle obj) {if (this.getArea() > obj.getArea()) {return 1;} else if (this.getArea() < obj.getArea()) {return -1;} elsereturn 0;}@Overridepublic boolean equals(Object ob) {Rectangle r = (Rectangle) ob;double thisArea = this.getArea();double rArea = r.getArea();// 等号的左边必须是变量,因此前面新声明了一个变量表示面积return thisArea == rArea;}
}
*13.11 (八边形类Octagon)

编写一个名为Octagon的类,它继承自GeometricObject类并实现Comparable和Cloneable接口。假设八边形八条边的边长都相等。它的面积可以使用下面的公式计算:

面积 = ( 2 + 4 / √ 2 ) × 边长 × 边长 面积=(2+4/√2)×边长×边长 面积=(2+4/√2)×边长×边长

画出包括Octagon、GeometricObject、Comparable和Cloneable的UML图。编写一个测试程序,创建一个边长值为5的Octagon对象,然后显示它的面积和周长。使用clone方法创建一个新对象,并使用compareTo方法比较这两个对象。

Test.java

package learning;//___________________________UML DIAGRAM____________________________|/*                                                                 |*                          /GeometricObject/                       |*------------------------------------------------------------------|*    color: String                                                 |*    filled: boolean                                               |*------------------------------------------------------------------|*   GeometricObject()                                              |*   /#getPerimeter(): double/                                      |*   /#getArea(): double/                                           |* _________________________________________________________________| *//*                                  ^^^^/*_________________UML Diagram__________________**                                              **                   Octagon                    **-----------------------------------------------**                                                 **   side: double                               **-----------------------------------------------*
_____________________________________               *   Octagon()                                   *                _____________________________________
*           <<interface>>           *               *   Octagon(side:double)                        *               *           <<interface>>            *
*      java.lang.Cloneable          *               *                                               *               *   java.lang.Comparable<Octagon>    *
*___________________________________*   <<<<<<<<<    *                                               *   >>>>>>>>>   *____________________________________*
*       #clone():Object             *               *   #getArea(): double                          *               *   +compareTo(obj: T):int           *
*___________________________________*               *   #getPerimeter(): double                     *               *____________________________________**     #clone(): Object                            **      +compareTo(o: Octagon): int                    *   * ______________________________________________* */public class Test {public static void main(String[] args) throws CloneNotSupportedException {Octagon o1 = new Octagon(5);System.out.println(o1.getPerimeter());System.out.println(o1.getArea());Octagon o2 = (Octagon)o1.clone();System.out.print(o1.compareTo(o2));}
}

GeometricObject.java

package learning;abstract class GeometricObject{String color;boolean filled;GeometricObject() {}protected abstract double getPerimeter();protected abstract double getArea();
}

Octagon.java

package learning;class Octagon extends GeometricObject implements Cloneable, Comparable<Octagon>{private double side;Octagon() {this(1.0);}Octagon(double side) {this.side = side;}@Overrideprotected double getPerimeter() {return side * 8;}@Overrideprotected double getArea() {return (2 + 4 / Math.pow(2, 0.5) * side * side);}@Overridepublic int compareTo(Octagon o) {if (getArea() > o.getArea())return 1;else if (getArea() < o.getArea())return -1;  else return 0;}@Override// 在覆写中,子类必须要选择可见性更高的修饰符,部分关键字不需要覆写(如abstract,native),父类方法声明的异常也不需要覆写protected Object clone() throws CloneNotSupportedException {// Object类中的clone方法是经过关键字native由虚拟机完成的,无法在Java源代码直接访问到return super.clone();}
}

输出结果:

40.0
72.71067811865474
0
*13.12(求几何对象的面积之和)

编写一个方法,求数组中所有几何对象的面积之和。方法签名如下:

public static double sumArea(Geometricobject[] a)

编写测试程序,创建四个对象(两个圆和两个矩形)的数组,然后使用sumArea方法求它们的总面积。

Test.java

package learning;//___________________________UML DIAGRAM____________________________|/*                                                                 |*                          /GeometricObject/                       |*------------------------------------------------------------------|*    color: String                                                 |*    filled: boolean                                               |*------------------------------------------------------------------|*   GeometricObject()                                              |*   /#getArea(): double/                                           |* _________________________________________________________________| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^            ^                                                                             ^^                                                                              ^/*_________________UML Diagram___________________*                             /*_________________UML Diagram____________________**                                              *                              *                                                **                  Rectangle                   *                              *                   Circle                       **-----------------------------------------------*                              *------------------------------------------------**     -width: double                              *                              *    -radius: double                             **   -height: double                            *                              *------------------------------------------------**-----------------------------------------------*                                 *    Circle()                                    **   Rectangle()                                    *                              *    Circle(radius: double)                      **   Rectangle(width: double, height: double)   *                              *    #getArea(): double                          **   #getArea(): double                         *                              *                                                ** ______________________________________________*                             * _______________________________________________* */public class Test {public static void main(String[] args) throws CloneNotSupportedException {GeometricObject r1 = new Rectangle(3, 4);GeometricObject r2 = new Rectangle(4, 5);GeometricObject c1 = new Circle(3);GeometricObject c2 = new Circle(4);GeometricObject[] go = new GeometricObject[4];go[0] = r1;go[1] = r2;go[2] = c1;go[3] = c2;System.out.print(sumArea(go));}public static double sumArea(GeometricObject[] a) {double sum = 0;for (int i = 0; i < a.length; i++) {double area = a[i].getArea();sum = sum + area;}return sum;}
}

GeometricObject.java

package learning;abstract class GeometricObject{String color;boolean filled;GeometricObject() {}protected abstract double getArea();
}

Circle.java

package learning;class Circle extends GeometricObject {private double radius;Circle() {this(1);}Circle(double radius) {this.radius = radius;}@Overrideprotected double getArea() {return Math.PI * radius * radius;}}

Rectangle.java

package learning;class Rectangle extends GeometricObject {private double width;private double height;Rectangle() {this(1, 1);}Rectangle(double width, double height) {this.width = width;this.height = height;}@Overrideprotected double getArea() {return width * height;}}

输出结果:

110.53981633974483
*13.13 (使得 Course 类可复制)

重写程序淸单10-6中的 Course 类,增加一个 clone 方法,执行students 域上的深度复制。

Test.java

package learning;                                    public class Test {public static void main(String[] args) throws CloneNotSupportedException {Course c1 = new Course("English");c1.addStudent("A");c1.addStudent("B");c1.addStudent("C");c1.addStudent("D");Course c2 = (Course)c1.clone();System.out.println("c1 == c2 is " + (c1.getStudents() == c2.getStudents()));}
}

Course.java

package learning;public class Course implements Cloneable {private String courseName;private String[] students = new String[4];private int numberOfStudents;public Course(String courseName) {this.courseName = courseName;}public void addStudent(String student) {students[numberOfStudents] = student;numberOfStudents++;}public String[] getStudents() {return students;}public int getNumberOfStudents() {return numberOfStudents;}  public String getCourseName() {return courseName;}  @Overrideprotected Object clone() throws CloneNotSupportedException{Course studentCloned = (Course)super.clone();studentCloned.students = deepCloned();return studentCloned;}protected String[] deepCloned() {String[] temp = new String[4];for (int i = 0; i < students.length; i++) {temp[i] = students[i];}return temp;}
}

输出结果:

c1 == c2 is false
*13.14(演示封装的好处)

使用新的分子分母的内部表达改写13.13节中的Rational类。创建有两个整数的数组,如下所示:

private long[] r = new 1ong[2]:

使用r[0]表示分子,使用r[1]表示分母。在Rational类中的方法签名没有改变,因此,无须重新编译,前一个Rational类的客户端应用程序可以继续使用这个新的Rational类。

// 替换字段处即可
private long[] r = new long[2];
private long numerator = r[0];
private long denominator = r[1];
13.15(在 Rational 类中使用 Biglnteger)

使用 Biglnteger 表示分子和分母,重新设计和实现

package learning;import java.math.BigInteger;public class Rational extends Number implements Comparable<Rational> {// Data fields for numerator and denominatorprivate BigInteger numerator = BigInteger.ZERO;private BigInteger denominator = BigInteger.ONE;public Rational() {this(0, 1);}public Rational(long numerator) {this(numerator, 1);}public Rational(long numerator, long denominator) {BigInteger gcd = gcd(numerator, denominator);this.numerator = BigInteger.valueOf(((denominator > 0) ? 1 : -1) * numerator).divide(gcd);this.denominator = BigInteger.valueOf(Math.abs(denominator)).divide(gcd);}private static BigInteger gcd(long n, long d) {BigInteger b1 = BigInteger.valueOf(n);BigInteger b2 = BigInteger.valueOf(d);return b1.gcd(b2);}public long getNumerator() {return numerator.longValue();}public long getDenominator() {return denominator.longValue();}public Rational add(Rational secondRational) {long n = numerator.longValue() * secondRational.getDenominator() +denominator.longValue() * secondRational.getNumerator();long d = denominator.longValue() * secondRational.getDenominator();return new Rational(n, d);}public Rational subtract(Rational secondRational) {long n = numerator.longValue() * secondRational.getDenominator()- denominator.longValue() * secondRational.getNumerator();long d = denominator.longValue() * secondRational.getDenominator();return new Rational(n, d);}public Rational multiply(Rational secondRational) {long n = numerator.longValue() * secondRational.getNumerator();long d = denominator.longValue() * secondRational.getDenominator();return new Rational(n, d);}public Rational divide(Rational secondRational) {long n = numerator.longValue() * secondRational.getDenominator();long d = denominator.longValue() * secondRational.numerator.longValue();return new Rational(n, d);}@Overridepublic String toString() {if (denominator.intValue() == 1)return numerator + "";elsereturn numerator + "/" + denominator;}@Override public boolean equals(Object other) {if ((this.subtract((Rational) (other))).getNumerator() == 0)return true;elsereturn false;}@Override public int intValue() {return (int) doubleValue();}@Override public float floatValue() {return (float) doubleValue();}@Overridepublic double doubleValue() {return numerator.longValue() * 1.0 / denominator.longValue();}@Override public long longValue() {return (long) doubleValue();}@Override public int compareTo(Rational o) {if (this.subtract(o).getNumerator() > 0)return 1;else if (this.subtract(o).getNumerator() < 0)return -1;elsereturn 0;}
}
*13.16(创建一个有理数的计算器)

编写一个类似于程序清单7-9的程序。这里不使用整数,而是使用有理数,如图13-10a所示。需要使用在10.10.3节中介绍的String类中的split方法来获取分子字符串和分母字符串,并使用Integer.parseInt方法将字符串转换为整数

Test.java

package learning;                                    public class Test {public static void main(String[] args) {String num1 = "1/3";String opera = "*";String num2 = "1/3";String[] sepNum1 = new String[2];String[] sepNum2 = new String[2];sepNum1 = num1.split("/");sepNum2 = num2.split("/");long numerator1 = Integer.parseInt(sepNum1[0]);long denominator1 = Integer.parseInt(sepNum1[1]);long numerator2 = Integer.parseInt(sepNum2[0]);long denominator2 = Integer.parseInt(sepNum2[1]);switch(opera) {case "+":System.out.println(new Rational(numerator1, denominator1).add(new Rational(numerator2, denominator2)));break;case "-":System.out.println(new Rational(numerator1, denominator1).subtract(new Rational(numerator2, denominator2)));break;case "*":System.out.println(new Rational(numerator1, denominator1).multiply(new Rational(numerator2, denominator2)));break;case "/":System.out.println(new Rational(numerator1, denominator1).divide(new Rational(numerator2, denominator2)));}}
}

Rational.java

package learning;public class Rational extends Number implements Comparable<Rational> {// Data fields for numerator and denominatorprivate long numerator = 0;private long denominator = 1;/** Construct a rational with default properties */public Rational() {this(0, 1);}/** Construct a rational with specified numerator and denominator */public Rational(long numerator, long denominator) {long gcd = gcd(numerator, denominator);this.numerator = (denominator > 0 ? 1 : -1) * numerator / gcd;this.denominator = Math.abs(denominator) / gcd;}/** Find GCD of two numbers */private static long gcd(long n, long d) {long n1 = Math.abs(n);long n2 = Math.abs(d);int gcd = 1;for (int k = 1; k <= n1 && k <= n2; k++) {if (n1 % k == 0 && n2 % k == 0) gcd = k;}return gcd;}/** Return numerator */public long getNumerator() {return numerator;}/** Return denominator */public long getDenominator() {return denominator;}/** Add a rational number to this rational */public Rational add(Rational secondRational) {long n = numerator * secondRational.getDenominator() +denominator * secondRational.getNumerator();long d = denominator * secondRational.getDenominator();return new Rational(n, d);}/** Subtract a rational number from this rational */public Rational subtract(Rational secondRational) {long n = numerator * secondRational.getDenominator()- denominator * secondRational.getNumerator();long d = denominator * secondRational.getDenominator();return new Rational(n, d);}/** Multiply a rational number to this rational */public Rational multiply(Rational secondRational) {long n = numerator * secondRational.getNumerator();long d = denominator * secondRational.getDenominator();return new Rational(n, d);}/** Divide a rational number from this rational */public Rational divide(Rational secondRational) {long n = numerator * secondRational.getDenominator();long d = denominator * secondRational.numerator;return new Rational(n, d);}@Override  public String toString() {if (denominator == 1)return numerator + "";elsereturn numerator + "/" + denominator;}@Override // Override the equals method in the Object class public boolean equals(Object other) {if ((this.subtract((Rational)(other))).getNumerator() == 0)return true;elsereturn false;}@Override // Implement the abstract intValue method in Number public int intValue() {return (int)doubleValue();}@Override // Implement the abstract floatValue method in Number public float floatValue() {return (float)doubleValue();}@Override // Implement the doubleValue method in Number public double doubleValue() {return numerator * 1.0 / denominator;}@Override // Implement the abstract longValue method in Numberpublic long longValue() {return (long)doubleValue();}@Override // Implement the compareTo method in Comparablepublic int compareTo(Rational o) {if (this.subtract(o).getNumerator() > 0)return 1;else if (this.subtract(o).getNumerator() < 0)return -1;elsereturn 0;}}

输出结果:

1/9
*13.17(數学: Complex类)

一个复数是一个形式为a+bi加的数,这里的a和b都是实数,i是 − 1 \sqrt{-1} −1 ​的平方根。数字a和b分别称为复数的实部和虚部。可以使用下面的公式完成复数的加、减、乘、除:

a + bi + c + di = (a + c) + (b + d)i
a + bi - (c + di) = (a - c) + (b - d)i
(a + bi)*(c + di) = (ac - bd) + (bc + ad)i
(a + bi)/(c + di) = (ac + bd)/(c2 + d2) + (bc - ad)i/(c^2 + d^2)

还可以使用下面的公式得到复数的绝对值:

∣ a + b i ∣ = a 2 + b 2 |a + bi| = \sqrt{a^2 + b^2} ∣a+bi∣=a2+b2 ​

(复数可以解释为一个平面上的点,将(a,b)值作为该点的坐标。复数的绝对值是该点到原点的距离,如图13-10b所示。)

设计一个名为Complex的复数来表示复数以及完成复数运算的add、substract、 multiply、divide和abs方法,并且覆盖toString方法以返回一个表示复数的字符串。 方法toString返回字符串a+bi。如果b是0,那么它只返回a。Complex类应该也实现Cloneable接口。

提供三个构造方法Complex(a,b)、Complex(a)和Complex()。Complex()创建数字0的Complex对象,而Complex(a)创建一个b为0的Complex对象。还提供getRealPart() 和getImaginaryPart()方法以分别返回复数的实部和虚部。

编写一个测试程序,提示用户输人两个复数,然后显示它们做加、减、乘、除之后的结果。下面是一个运行示例:

Test.java

package learning;                                    public class Test {public static void main(String[] args) {Complex c1 = new Complex(3.5, 5.5);Complex c2 = new Complex(-3.5, 1);System.out.println(c1.add(c2));System.out.println(c1.sub(c2));System.out.println(c1.mul(c2));System.out.println(c1.div(c2));System.out.println(c1.abs());}
}

Complex.java

package learning;class Complex {public double a;public double b;//会依次调用之后的两个构造方法,注意如果没有传入值,默认0.0public Complex() {this(0);}public Complex(double a) {this(a, 0);}public Complex(double a, double b) {this.a = a;this.b = b;}public Complex add(Complex c2) {double c = c2.a;double d = c2.b;double complex1 = a + c;double complex2 = b + d;return new Complex(complex1, complex2);}public Complex sub(Complex c2) {double c = c2.a;double d = c2.b;double complex1 = a - c;double complex2 = b - d;return new Complex(complex1, complex2);}public Complex mul(Complex c2) {double c = c2.a;double d = c2.b;double complex1 = a * c - b * d;double complex2 = b * c + a * d;return new Complex(complex1, complex2);}public Complex div(Complex c2) {double c = c2.a;double d = c2.b;double complex1 = (a * c + b * d) / (c * c + d * d);double complex2 = (b * c - a * d) / (c * c + d * d);return new Complex(complex1, complex2);}public double abs() {return Math.pow(a * a + b * b, 0.5);}public double getRealPart() {return a;}public double getImaginaryPart() {return b;}@Override// 输出对象时,会自动调用toStringpublic String toString() {if (b == 0)return a + "";elsereturn a + " + " + b + "i";}
}

输出结果:

0.0 + 6.5i
7.0 + 4.5i
-17.75 + -15.75i
-0.5094339622641509 + -1.7169811320754718i
6.519202405202649
13.18(使用 Rational 类)

编写程序,使用 Rational 类计算下面的求和数列:

1 2 + 2 3 + 3 4 + ⋅ ⋅ ⋅ + 99 100 \frac{1}{2} + \frac{2}{3} + \frac{3}{4} + ··· + \frac{99}{100} 21​+32​+43​+⋅⋅⋅+10099​

你将会发现输出是不正确的 ,因为整数溢出(太大了)。为了解决这个问题 ,参见编程练习題13.15。

直接复制13.15的Rational代码,下面只给出Test测试类

Test.java

package learning;                                    public class Test {public static void main(String[] args) {Rational resultRational = new Rational();long i = 2;while (i <= 100) {Rational rational = new Rational(i - 1, i);System.out.print(rational.getNumerator() + "/" + rational.getDenominator());if (i == 100) System.out.print(" = ");else if (i % 10 == 0) System.out.println(" + ");else System.out.print(" + ");resultRational = resultRational.add(rational);i++;}System.out.println(resultRational.getNumerator() + " / " + resultRational.getDenominator());}
}

输出结果:

1/2 + 2/3 + 3/4 + ... + 97/98 + 98/99 + 99/100 = 1349247664274259951 / 1822963237492290880
13.19 (将十进制數转化为分教)

编写一个程序,提示用户输入一个十进制数,然后以分数的形式显示该数字。提示 :将十进制数以字符串的形式读入 ,从字符串中抽取其整数部分和小数部分 ,然后运用编程练习题 13.15 中使用 Biglnteger 实现的 Rational 类,来获得该十进制数的有理数。这里是一些运行示例:

最后3题比较考察数学功底,编程逻辑不难,但是数学难哈哈哈。。。

直接复制13.15的Rational代码,下面只给出Test测试类

Test.java

package learning;                                    import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner in = new Scanner(System.in);System.out.print("Enter a decimal number: ");String decVal = in.next();try {System.out.println("The fraction number is " + decimalToFraction(decVal));} catch (Exception e) {System.out.println(e.getMessage());}in.close();}private static String decimalToFraction(String val) throws Exception {boolean isNegative = val.startsWith("-");String[] decimalNumberParts = val.split("\\.");if (decimalNumberParts.length < 2) {throw new Exception("You must enter a decimal number like: 123.12");}if (val.startsWith("-")) {isNegative = true;}Rational leftSideOfDecimal = new Rational(Long.parseLong(decimalNumberParts[0]));String denominatorRightSide = "1";for (int i = 0; i < decimalNumberParts[1].length(); i++) {denominatorRightSide += "0";}Rational rightSideOfDecimal = new Rational(Long.parseLong(decimalNumberParts[1]), Long.parseLong(denominatorRightSide));Rational result = leftSideOfDecimal.add(rightSideOfDecimal);return (isNegative ? "-" : "") + result.toString();}
}

输出结果:

Enter a decimal number: 3.25
The fraction number is 13/4
13.20 (數学:求解二元方程)

重写编程练习题3.1,如果行列式小于0,则使用编程练习题13.17中的 Complex 类来得到虚根。这里是一些运行示例:

最后3题比较考察数学功底,编程逻辑不难,但是数学难哈哈哈。。。

直接复制13.17的Complex代码,下面只给出Test测试类

Test.java

package learning;import java.util.Scanner;public class Test {public static void main(String[] args) {try (Scanner input = new Scanner(System.in)) {System.out.print("Enter a, b, c: ");double a = input.nextDouble();double b = input.nextDouble();double c = input.nextDouble();double discriminant = b * b - 4 * a * c;if (discriminant > 0) {double r1 = ((-1 * b) + Math.sqrt(discriminant)) / (2 * a);double r2 = ((-1 * b) - Math.sqrt(discriminant)) / (2 * a);System.out.printf("Two real roots: %2.5f and %2.5f", r1, r2);} else if (discriminant == 0) {double r = ((-1 * b) + Math.sqrt(discriminant)) / (2 * a);System.out.print("One real root: " + r);} else {Complex complexR1 = new Complex(-b / (2 * a), Math.sqrt(2 * a));Complex complexR2 = new Complex(-b / (2 * a), -Math.sqrt(2 * a));System.out.println("The roots are " + complexR1 + " and " + complexR2);}} catch (Exception e) {e.printStackTrace();}}
}

输出结果:

Enter a, b, c: 1 2 3
The roots are -1.0 + 1.4142135623730951i and -1.0 + -1.4142135623730951i
13.21(代数:顶点式方程)

抛物线方程可以表达为标准形式(y=ax2+bx+c)或者顶点式(y=a(x-h)2+k)。编写一个程序,提示用户输人标准形式下的整数a、b和c值,显示顶点式下面的h和k值。这里是一些运行示例:

最后3题比较考察数学功底,编程逻辑不难,但是数学难哈哈哈。。。

直接复制13.15的Rational代码,下面只给出Test测试类

Test.java

package learning;import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner in = new Scanner(System.in);System.out.print("Enter a, b, c (as integers): ");int a = in.nextInt();int b = in.nextInt();int c = in.nextInt();Rational aRational = new Rational(a); Rational bRational = new Rational(b); Rational cRational = new Rational(c); Rational h = new Rational(bRational.multiply(new Rational(-1)).longValue(),aRational.multiply(new Rational(2)).longValue());Rational k = aRational.multiply(h.multiply(h)).add(bRational.multiply(h)).add(cRational);System.out.println("h is " + h + ", k is " + k);}
}

输出结果:

Enter a, b, c (as integers): 1 3 1
h is -3/2, k is -5/4

《Java黑皮书基础篇第10版》 第13章【习题】相关推荐

  1. 《Java黑皮书基础篇第10版》 第9章【习题】

    Java语言程序设计 习题第九章 9.3章节习题 9.1 描述对象和它的定义类之间的关系. 定义类是描述具有相似特征对象的集合 对于每一个对象,都有自己独立的数据域 9.2 如何定义一个类? clas ...

  2. 《Java黑皮书基础篇第10版》 第5章【习题】【笔记】

    Java语言程序设计 第五章笔记 5.1 引言 Java 提供了三种类型的循环语句: while循环.do-while循环和for循环. 5.2 while循环 计时器控制的循环:确切的知道循环体需要 ...

  3. 《Java黑皮书基础篇第10版》 第11章【习题】

    Java语言程序设计 习题第十一章 11.2章节习题 11.1 下面说法是真是假? 一个子类是父类的子集 不是,子类可以拥有父类的数据域和方法,还可以拥有自己独有的数据域和方法 11.2 使用什么关键 ...

  4. 《Java黑皮书基础篇第10版》 第12章【习题】

    Java语言程序设计 习题第十二章 12.2章节习题 12.1 使用异常处理的优势是什么? 如果没有异常处理,方法执行(called method)出错时,调用者(caller)没有办法进行处理(比如 ...

  5. 《Java黑皮书基础篇第10版》 第7章【习题】

    Java语言程序设计 第七章 7.2 习题 如何声明一个数组引用变量,如何创建一个数组? elementType[] arrayRefVar; elementType[] arrayRefVar = ...

  6. 《Java黑皮书基础篇第10版》 第7章【笔记】

    第七章 7.1引言 7.2 数组的基础知识 声明数组变量 elementType[] arrayRefVar 创建数组 elementType[] arrayRefVar = new elementT ...

  7. 《Java黑皮书基础篇第10版》 第3章【习题】

    第三章 3.2习题 列出6个关系操作符 >,>=,<,<=,==,!=>, >=, <, <=, ==, !=>,>=,<,<= ...

  8. 《Java黑皮书基础篇第10版》 第1章【笔记】

    Java语言程序设计 第一章 计算机.程序和Java概述 1.1 引言 程序设计(又称编程)就是创建软件,软件也称为程序 1.2 什么是计算机 计算机包括硬件和软件两部分,软件发出的指令控制硬件,使得 ...

  9. 《Java黑皮书基础篇第10版》 第9章【笔记】

    第九章 9.1 引言 9.2 为对象定义类 类: 类可以储存同类型的对象,例如圆就是一个类 (ClassName: Circle) 对象: 创建对象的过程被称为实例化,一个对象有自己的数据域(字段), ...

最新文章

  1. 苹果12系统升级无服务器,iOS 12.1.4验证现已关闭 你还没升到12.2吗?
  2. python编程案例教程书籍-Python程序设计案例教程
  3. mysql 存储地理信息_使用Amazon Aurora存储和处理地理信息数据
  4. 设计师经常逛的网站?
  5. android canvas帧动画,html5视频,canvas,画布
  6. 苹果ppt_“苹果美感中国学不来?”阿里、腾讯的设计师让你感受中国智造
  7. java代码颜色_JAVA颜色代码
  8. 发现本站一个非常简单易学的springClould教程 特此转载《方志朋》
  9. 三分钟了解Activity工作流
  10. C语言英文字符的使用
  11. 魔兽争霸V星际争霸V红警
  12. RAII惯用法:C++资源管理的利器
  13. win10无法防问其他计算机没有权限,Win10无internet访问权限怎么解决?
  14. zebradesginer zpl代码_老司机为您win7系统安装斑马GK888t打印机驱动的操作技巧
  15. 【设计模式】抽象类与接口
  16. 彩色图像--伪彩处理 灰度图转伪彩色图像
  17. [网络流24题] No2_太空飞行计划
  18. 人气有所回升,反弹看量能
  19. java ffmpeg视频截图_Java实现对视频进行截图的方法【附ffmpeg下载】
  20. android o 结构光流程,结构光光条中心的提取算法.pdf

热门文章

  1. 安装WebStorm-2022.3.2
  2. 网络与信息安全监控内容
  3. 安利一个最适合数据分析师的小众高薪兼职!
  4. java用户删除_添加/删除用户
  5. winform实现发票打印功能
  6. Hexo+GitHub搭建个人网站全网最详细教程
  7. 多少 程序员珍藏 的 东东...
  8. 证书工具+网络插件介绍
  9. 星空主题设计理念_星空主题餐厅设计
  10. 计算机视觉发展和应用浅谈