9.1 描述对象和它的定义类之间的关系。
定义类是描述具有相似特征对象的集合
对于每一个对象,都有自己独立的数据域
9.2 如何定义一个类?
class ClassName{
//dataFields
//constructionMethod
//method
}
9.3 如何声明一个对象引用变量?
//ClassName objectName是创建引用变量objectNameVariable
ClassName objectRefVar
9.4 如何创建一个对象?
//new ClassName()是创建类的实例(对象)
ClassName objectRefVar = new ClassName();
9.5 构造方法和普通方法之间的区别是什么?
构造方法没有返回值,普通方法有返回值
构造方法的功能用来初始化对象,普通方法的功能随需求而定
构造方法会在创建对象时一定会执行一次,普通方法可以在创建对象后多次执行
9.6 什么时候类将有一个默认构造方法?
程序中没有定义任何构造方法的时候
9.7 哪个操作符用于访问对象的数据域或者调用对象的方法?
'.'操作符
9.8 什么是匿名对象?
不需要引用变量的对象
9.9 什么是NullPointerException?
NullPointerException 是一种常见的运行时错误,当调用值为null的引用变量上的方法时会发生此类异常。在通过引用变量调用一个方法之前,确保先将对象引用賦值给这个变量
9.10 数组是对象还是基本类型值?数组可以包含对象类型的元素吗?描述数组元素的默认值。
数组是一个对象
对象数组指的是,数组中的元素是对象(的引用变量)。Array数组可以包含基本类型和对象类型。可以参见https://cloud.tencent.com/developer/article/1916099
如果数组元素没有被初始化,会给定一个默认值:
byte,short,int,long类型定义的数组,默认值是0;
float、double类型定义的数组,默认值是0.0;
boolean类型定义的数组,默认值是false;
char类型定义的数组,默认值是\u0000;
String类型定义的数组,默认值是null。
9.11 下面每个程序中有什么错误?
public class Main{
public static void main(String[]args){
//没有定义对应的构造方法
Main t = new Main(5);
}
}
public class Main{
public static void main(String[]args){
//没有定义对应的构造方法
Main t = new Main(5);
//没有定义对应的数据域
t.x();
}
}
public class Main{
public void method1(){
Circle c;
//没有定义方法
System.out.println("What is radius "
+ c.getRadius());
c = new Circle();
}
}
public class Main {
public static void main(String[]args){
//没有对应的构造方法
C c = new C(5.0);
System.out.println(c.value);
}
}
class C {
int value = 2;
}
9.12 下面代码有什么错误?
class Main {
public static void main(String[]args){
//没有定义对应的构造方法,如果加上无参构造方法,会打印默认值null
A a = new A();
a.print();
}
}
class A {
String s;
A(String newS){
s = newS;
}
public void print(){
System.out.print(s);
}
}
9.13 下面代码的输出是什么?
//报错
public class Main{
boolean x;
public static void main(String[]args){
A a = new A();
System.out.println(a.x);
}
}
9.14 如何为当前时间创建一个Date? 如何显示当前时间?
public class Main{
public static void main(String[]args){
//为当前时间创建一个date对象的引用变量
java.util.Date date = new java.util.Date();
//显示当前时间和日期
System.out.println("The elapsed time since Jan 1,1970 is " + date.getTime() + " milliseconds");
System.out.println(date.toString());
}
}
9.15 如何创建一个Point2D? 假设p1和p2是Point2D的两个实例,如何获得两点之间的距离?
import java.util.Scanner;
import javafx.geometry.Point2D;
public class Main {
public static void main(String[]args){
Scanner input = new Scanner(System.in);
System.out.print("Enter pointl's x-,y-coordinates:"); double x1 = input.nextDouble();
double y1 = input.nextDouble();
System.out.print("Enter point2's x-,y-coordinates:"); double x2 = input.nextDouble();
double y2 = input.nextDouble();
Point2D p1 = new Point2D(x1,y1);
Point2D p2 = new Point2D(x2,y2);
System.out.println("pl is " + p1.toString());
System.out.println("p2 is " + p2.toString());
System.out.println("The distance between pl and p2 is " + p1.distance(p2));
}
}
9.16 哪些包包含类Date 、Random、Point2D、System以及Math?
java.util.Date
java.util.Random
javafx.geometry.Point2D
Java.lang.System
Java.lang.Math
9.17 假设F类在a中定义,f是F的一个实例, 那么b中的哪些语句是正确的?
最好通过类名去访问静态方法和静态变量,不要通过实例变量去访问静态变量和静态方法,否则会得到一个警告
通过类名只能访问静态方法和静态变量,不可以访问实例变量和实例方法,否则编译器会报错
public class Main {
public static void main(String[] args) {
F f = new F();
//正确
System.out.println(f.i);
//警告
//The static field F.s should be accessed in a static way
System.out.println(f.s);
//正确
f.imethod();
//警告
//The static method smethod()from the type F should be accessed in a static way
f.smethod();
//错误
//Cannot make a static reference to the non-static field F.i
System.out.println(F.i);
//正确
System.out.println(F.s);
//错误
//Cannot make a static reference to the non-static method imethod()from the type F
F.imethod();
//正确
F.smethod();
}
}
class F {
int i;
static String s;
void imethod(){
}
static void smethod(){
}
}
9.18 如果合适的话,在出现?的位置添加static关键字。
public class Main {
int count;
//需要添加,是入口方法
public ? void main(String[]args) {
}
//不可以添加,因为count数据域是非静态的,所以他的方法也应该是非静态的
public ? int getCount() {
return count;
}
//可以添加,方法内没有引用其他的实例变量,是一个静态方法
public ? int factorial (int n) {
int result = 1;
for (int i = 1; i <= n; i++)
result *= i;
return result;
}
}
9.19 能否从静态方法中调用实例方法或引用一个实例变量? 能否从实例方法中调用静态方法或引用一个静态变量? 下面代码错在哪里?
不可以从静态方法中调用一个实例方法或引用一个实例变量
可以从实例方法中调用静态方法或引用一个静态变量
public class Main {
public static void main(String[] args){
//Cannot make a static reference to the non-static method method1()from the type Main
//不可以从静态方法中调用一个实例方法
method1();
}
static int a = 1;
public int method1() {
//可以从实例方法中引用一个静态变量
return a;
//可以从实例方法中调用一个静态方法
method2();
}
public static void method2() {
//Cannot make a static reference to the non-static field c
//不可以从静态方法中引用一个实例变量
System.out.println("What is radius " + c.getRadius()); }
Circle c = new Circle();
}
9.20 什么是访问器方法? 什么是修改器方法? 访问器方法和修改器方法的命名习惯是什么?
访问器方法是get方法,修改器方法是set方法
//访问器方法
public returnType getPropertyName()
//修改器方法
public void setPropertyName(dataType propertyValue)
9.21 数据域封装的优点是什么?
防止用户直接篡改数据,上传不合法的数据导致难以维护,保证用户只能通过get方法拿取数据,set方法修改数据
9.22 在下面的代码中,Circle类中的radius是私有的,而myCircle是Circle类的一个对象,下面高亮的代码会导致什么问题吗? 如果有问题的话,解释为什么。
public class Main {
private double radius = 1;
/** Find the area of this circle */
public double getArea(){
return radius * radius * Math.PI;
}
public static void main(String[]args) {
Main myCircle = new Main();
System.out.println("Radius is " + myCircle.radius);
}
}
不会有问题,因为private把访问权控制在了Main类内部,myCircile就在Main类内部,所以不会有问题
9.23 描述传递基本类型参数和传递引用类型参数的区别,并给出下面程序的输出
对于基本类型参数的传递,是方法对参数的复制,参数本身并不受影响
对于引用类型参数的传递,方法和引用变量最终的指向都是对象本身,任意一方的修改都会牵一发而动全身
下面程序考察的就是传递基本类型和引用类型参数的区别
对于栈中的引用变量,都指向堆中的对象,一个变了就全都变了
对于基本类型的传递,在方法内times改变,但是方法外times不变
public class Main {
public static void main(String[] args) {
Count myCount = new Count();
int times = 0;
for (int i = 0; i < 100; i++)
increment(myCount,times);
System.out.println("count is " + myCount.count);
System.out.println("times is " + times);
}
public static void increment(Count c,int times){
c.count++;
times++;
}
}
class Count {
public int count;
public Count(int c) {
count = c;
}
public Count() {
count = 1;
}
}
count is 101
times is 0
9.24 显示下面程序的输出:
public class Main {
public static void main(String[]args) {
Circle circle1 = new Circle(1);
Circle circle2 = new Circle(2);
swap1(circle1,circle2);
System.out.println("After swap1: circle1 = " + circle1.radius + " and circle2 = " + circle2.radius);
swap2(circle1,circle2);
System.out.println("After swap2: circle1 = " + circle1.radius + " and circle2 = " + circle2.radius);
}
public static void swap1(Circle x, Circle y) {
Circle temp = x;
x = y;
y = temp;
System.out.println(x.radius);
System.out.println(y.radius);
}
public static void swap2(Circle x,Circle y) {
double temp = x.radius;
x.radius = y.radius;
y.radius = temp;
System.out.println(x.radius);
System.out.println(y.radius);
}
}
class Circle {
double radius;
Circle(double newRadius) {
radius = newRadius;
}
}
2.0
1.0
After swap1: circle1 = 1.0 and circle2 = 2.0
2.0
1.0
After swap2: circle1 = 2.0 and circle2 = 1.0
9.25 显示下面程序的输出:
//交换失败,因为交换的是基础类型参数int
public class Main {
public static void main(String[] args) {
int[] a = {1, 2};
swap(a[0], a[1]);
System.out.println("a[0] = " + a[0] + " a[1] = " + a[1]);
}
public static void swap(int n1, int n2) {
int temp = n1;
n1 = n2;
n2 = temp;
}
}
a[0] = 1 a[1] = 2
//交换成功,因为交换的是引用类型参数int[]
public class Main {
public static void main(String[] args) {
int[] a = {1, 2};
swap(a);
System.out.println("a[0] = " + a[0] + " a[1] = " + a[1]);
}
public static void swap(int[] a) {
int temp = a[0];
a[0] = a[1];
a[1] = temp;
}
}
a[0] = 2 a[1] = 1
public class Main {
public static void main(String[] args) {
T t = new T();
swap(t);
System.out.println("e1 = " + t.e1 + " e2 = " + t.e2);
}
public static void swap(T t) {
int temp = t.e1;
t.e1 = t.e2;
t.e2 = temp;
}
}
class T {
int e1 = 1;
int e2 = 2;
}
e1 = 2 e2 = 1
public class Main {
public static void main(String[] args) {
T t1 = new T();
T t2 = new T();
System.out.println("t1's i = " + t1.i + " and j = " + t1.j);
System.out.println("t2's i = " + t2.i + " and j = " + t2.j);
}
}
class T {
static int i = 0;
int j = 0;
T() {
i++;
j = 1;
}
}
t1's i = 2 and j = 1
t2's i = 2 and j = 1
9.26 显示下面程序的输出:
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date date = null;
m1(date);
System.out.println(date);
}
public static void ml(Date date) {
date = new Date();
}
}
null
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date date = new Date(1234567);
m1(date);
System.out.println(date.getTime());
}
public static void m1(Date date) {
date = new Date(7654321);
}
}
1234567
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date date = new Date(1234567);
m1(date);
System.out.println(date.getTime());
}
public static void m1(Date date) {
date.setTime(7654321);
}
}
7654321
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date date = new Date(1234567);
m1(date);
System.out.println(date.getTime());
}
public static void m1(Date date) {
date = null;
}
}
1234567
9.27 下面的代码有什么错误?
public class Main {
public static void main(String[] args) {
java.util.Date[] dates = new java.util.Date[10];
System.out.println(dates[0]);
System.out.println(dates[0].toString());
}
}
第二个输出会抛出空指针异常NullPointerException:如果一个对象为null,调用其方法或访问其字段就会导致该异常
9.28 如果类中仅包含私有数据域并且没有设置set方法,该类可以改变吗?
如果get方法返回了数据域中的可变引用类型,就可以通过这个引用改变数据域的值
9.29 如果类中的所有数据域是私有的基本数据类型,并且类中没有包含任何set方法,该类可以改变吗?
不可以改变,因为没有引用类型
9.30 下面的类可以改变吗?
public class A {
private int[] values;
public int[] getValues() {
return values;
}
}
可以改变,因为数组是引用类型
9.31 下面程序的输出是什么?
public class Main {
private static int i = 0;
private static int j = 0;
public static void main(String[] args) {
int i = 2;
int k = 3;
{
int j = 3;
System.out.println("i + j is " + i + j);
}
k = i + j;
System.out.println("k is " + k);
System.out.println("j is " + j);
}
}
i + j is 23
k is 2
j is 0
9.32 描述this关键字的角色。
this关键字可以引用对象,也可以在一个构造方法中调用其他构造方法
9.33 下面代码中哪里有错误?
public class C {
private int p;
public C() {
//构造方法中,this必须出现在第一行
System.out.println("C's no-arg constructor invoked"); this(0);
}
public C(int p) {
//需要调用this引用对象
p = p;
}
public void setP(int p) {
//需要调用this引用对象
p = p;
}
}
9.34 下面代码中哪里有错误?
public class Test {
private int id;
public void m1() {
this.id = 45;
}
public void m2() {
//不可以用类名去引用实例变量
Test.id = 45;
}
}
遵照9.2节中Circle类的例子,设计一个名为Rectangle的类表示矩形。这个类包括:
• 两个名为width和height的double型数据域,它们分别表示矩形的宽和高。width和height的默认值都为1。
• 创建默认矩形的无参构造方法。
• —个创建width和height为指定值的矩形的构造方法。
• 一个名为getArea()的方法返回这个矩形的面积。
• 一个名为getPerimeter()的方法返回周长。
画出该类的UML图并实现这个类。编写一个测试程序,创建两个Rectangle对象,一个矩形的宽为4而高为40,另一个矩形的宽为3.5,而高为35.9。按照这个顺序显示每个矩形的宽、高、面积和周长。
public class Test {
public static void main(String[] args) {
Rectangle r1 = new Rectangle(4, 40);
Rectangle r2 = new Rectangle(3.5, 35.9);
System.out.print("\t\tWidth\tHeight\tArea\tPerimeter");
System.out.printf("\nRactangle 1\t%.2f\t%.2f\t%.2f\t%.2f", r1.width, r1.height, r1.getArea(), r1.getPerimeter());
System.out.printf("\nRactangle 2\t%.2f\t%.2f\t%.2f\t%.2f", r2.width, r2.height, r2.getArea(), r2.getPerimeter());
}
}
//__________________________UML DIAGRAM_____________________________*
/* |
* Rectangle |
*------------------------------------------------------------------|
* width : double |
* |
* height : double |
*------------------------------------------------------------------|
* Rectangle() |
* |
* Rectangle(newWidth:double, newHeight:Double) |
* |
* getArea(): double |
* |
* getRectangle(): double |
*__________________________________________________________________| */
class Rectangle {
double width;
double height;
Rectangle() {
//如果想要默认的数据域,可以在无参构造方法中给定默认值,而不是在创建数据域时直接给出默认值
width = 1;
height = 1;
}
Rectangle(double newWidth, double newHeight) {
width = newWidth;
height = newHeight;
}
double getArea() {
return width * height;
}
double getPerimeter() {
return 2 * (width + height);
}
}
输出结果:
Width Height Area Perimeter
Ractangle 1 4.00 40.00 160.00 88.00
Ractangle 2 3.50 35.90 125.65 78.80
遵照9.2节中Circle类的例子,设计一个名为Stock的类。这个类包括:
• —个名为symbol的字符串数据域表示股票代码。
• 一个名为name的字符串数据域表示股票名字。
• 一个名为previousClosingPrice的double型数据域,它存储的是前一日的股票值
• 一个名为currentPrice的double型数据域,它存储的是当时的股票值。
• 创建一支有特定代码和名字的股票的构造方法。
• 一个名为getChangePercent()的方法,返回从previousClosingPrice变化到currentPrice的百分比。
画出该类的UML图并实现这个类。编写一个测试程序,创建一个Stock对象,它的股票代码是0RCL,股票名字为Oracle Corporation,前一日收盘价是34.5。设置新的当前值为34.35,然后显示市值变化的百分比。
public class Test {
public static void main(String[] args) {
Stock s1 = new Stock("ORCL", "Oracle Corporation", 34.5, 34.35);
System.out.printf("The changing percent is %.4f", s1.getChangePercent());
System.out.print("%");
}
}
//__________________________UML DIAGRAM_____________________________*
/* |
* Stock |
*------------------------------------------------------------------|
* symbol: String |
* |
* name: String |
* |
* previousClosingPrice: double |
* |
* currentPrice: double |
*------------------------------------------------------------------|
* Stock(newSymbol: String, newName: String) |
* |
* getChangePercent(): double |
*__________________________________________________________________| */
class Stock {
String symbol;
String name;
double previousClosingPrice;
double currentPrice;
Stock(String newSymbol, String newName, double newPreviousClosingPrice, double newCurrentPrice) {
symbol = newSymbol;
name = newName;
previousClosingPrice = newPreviousClosingPrice;
currentPrice = newCurrentPrice;
}
double getChangePercent() {
return (currentPrice - previousClosingPrice) / previousClosingPrice;
}
}
输出结果:
The changing percent is -0.0043%
编写程序创建一个Date对象,设置它的流逝时间分别为10000、100000、1000000、10000000、100000000、1000000000、10000000000、100000000000,然后使用toString()方法分别显示上述日期。
import java.util.Date;
public class Main {
//想表示long型数据需要在数据末尾加L
//把常量在主类私有,确保数据不可被篡改
private static final long startTime = 10000;
private static final long finalTime = 100000000000L;
public static void main(String[] args) {
Date date = new Date();
for (long a = startTime; a <= finalTime; a = a * 10) {
date.setTime(a);
System.out.println("The elapsed time is " + date.toString());
}
}
}
//完全可以用for循环替代下面的代码
//date.setTime(10000);
//System.out.println("The elapsed time is " + date.toString());
//date.setTime(100000);
//System.out.println("The elapsed time is " + date.toString());
//date.setTime(1000000);
//System.out.println("The elapsed time is " + date.toString());
//date.setTime(10000000);
//System.out.println("The elapsed time is " + date.toString());
//date.setTime(100000000);
//System.out.println("The elapsed time is " + date.toString());
//date.setTime(1000000000);
//System.out.println("The elapsed time is " + date.toString());
//date.setTime(10000000000L);
//System.out.println("The elapsed time is " + date.toString());
//date.setTime(100000000000L);
//System.out.println("The elapsed time is " + date.toString());
输出结果:
The elapsed time is Thu Jan 01 01:00:10 GMT 1970
The elapsed time is Thu Jan 01 01:01:40 GMT 1970
The elapsed time is Thu Jan 01 01:16:40 GMT 1970
The elapsed time is Thu Jan 01 03:46:40 GMT 1970
The elapsed time is Fri Jan 02 04:46:40 GMT 1970
The elapsed time is Mon Jan 12 14:46:40 GMT 1970
The elapsed time is Sun Apr 26 18:46:40 GMT 1970
The elapsed time is Sat Mar 03 09:46:40 GMT 1973
编写一个程序,创建种子是1000的Random对象,然后使用nextInt(100)方法显示0到100之间前50个随机整数。
import java.util.Random;
public class Main {
//把常量在主类私有,确保数据不可被篡改
private static final int seed = 1000;
private static final int n = 100;
public static void main(String[] args) {
Random number = new Random(seed);
for (int i = 0; i < 50; i++) {
//每10个数字进行一次回车,增加输出结果的可读性
if (i % 10 == 0) System.out.println();
System.out.print(number.nextInt(100) + " ");
}
}
}
输出结果:
87 35 76 24 92 49 41 45 64 50
79 59 72 83 36 75 46 2 23 41
22 71 89 2 93 42 49 42 35 76
32 0 52 95 87 31 99 18 79 2
91 5 55 84 71 95 58 87 77 38
Java API有一个在包java.util中的类GregorianCalendar,可以使用它获得某个日期的年、月、日。它的无参构造方法构建一个当前日期的实例,get(GregorianCalendar.YEAR)、get(GregorianCalendar.MONTH)、get(GregorianCalendar.DAY_OF_MONTH)方法返回年、月和日。编写一个程序完成两个任务:
• 显示当前的年、月和日。
• GregorianCalendar类有方法setTimeInMillis(Iong),可以用它来设置从1970年1月1日算起的一个特定时间。将这个值设置为1234567898765L,然后显示这个年、月和日。
import java.util.GregorianCalendar;
public class Main {
public static void main(String[] args) {
GregorianCalendar current = new GregorianCalendar();
System.out.println(current.get(GregorianCalendar.YEAR));
System.out.println(current.get(GregorianCalendar.MONTH));
System.out.println(current.get(GregorianCalendar.DAY_OF_MONTH));
current.setTimeInMillis(1234567898765L);
System.out.println(current.get(GregorianCalendar.YEAR));
System.out.println(current.get(GregorianCalendar.MONTH));
System.out.println(current.get(GregorianCalendar.DAY_OF_MONTH));
}
}
输出结果:
2023
3
17
2009
1
13
设计一个名为Stopwatch的类,该类包含:
• 具有访问器方法的私有数据域startTime和endTime。
• 一个无参构造方法,使用当前时间来初始化startTime。
• 一个名为start()的方法,将startTime重设为当前时间。
• 一个名为stop()的方法,将endTime设置为当前时间。
• —个名为getElapsedTime()的方法,以毫秒为单位返回秒表记录的流逝时间。
画出该类的UML图并实现这个类。编写一个测试程序,用于测量使用选择排序对100 000个数字进行排序的执行时间。
public class Test {
public static void main(String[] args) {
//创建数组
double [] arr = new double[100000];
for (int i = 0; i < 100000; i++) {
arr[i] = Math.random();
}
//初始化时间并调用选择排序
StopWatch newTime = new StopWatch();
System.out.println(newTime.start());
selectionSort(arr);
//计算间隔
System.out.println(newTime.end());
System.out.println(newTime.getElapsedTime());
}
//把选择排序单独写成一个方法
public static void selectionSort(double[] arr) {
for (int i = 0; i < arr.length-1; i++) { //外圈决定循环次数:(length-1)次
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) { // 内圈反复查找最小值下标,最大查找次数不能超过数组长度0-4(也就是<5)
if (arr[j] < arr[minIndex]) {
minIndex = j;// 记录最小值下标
}
}
if (minIndex != i) { //交换:如果自己就是最小值下标,不需要交换
double temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
}
//__________________________UML DIAGRAM_____________________________*
/* |
* StopWatch |
*------------------------------------------------------------------|
* -startTime: long ` |
* |
* -endTime: long |
*------------------------------------------------------------------|
* StopWatch() |
* |
* start(): void |
* |
* stop(): void |
* |
* getStartTime(): long |
* |
* getEndTime(): long |
* |
* getElapsedTime(): long |
*__________________________________________________________________| */
class StopWatch {
private long startTime;
private long endTime;
StopWatch() {
startTime = System.currentTimeMillis();
}
long getStartTime() {
return startTime;
}
long getEndTime() {
return endTime;
}
long start() {
return startTime = System.currentTimeMillis();
}
long end() {
return endTime = System.currentTimeMillis();
}
long getElapsedTime() {
return endTime - startTime;
}
}
输出结果:
1681727637974
1681727640839
2865
9.7 (账户类Account)
设计一个名为Account的类,它包括
• 一个名为id的int类型私有数据域(默认值为0)
• 一个名为balance的double类型私有数据域(默认值为0)
• —个名为annualInterestRate的double类型私有数据域存储当前利率(默认值为0)。假设所有的账户都有相同的利率
• 一个名为dateCreated的Date类型的私有数据域,存储账户的开户日期
• 一个用于创建默认账户的无参构造方法
• 一个用于创建带特定id和初始余额的账户的构造方法
• id、balance和annualInterstRate的访问器和修改器
• dateCreated的访问器
• 一个名为getMonthlyInterestRate()的方法,返回月利率
• —个名为withDraw的方法,从账户提取特定数额
• —个名为deposit的方法向账户存储特定数额
画出该类的 UML 图并实现这个类。
public class Test {
public static void main(String[] args) {
Account list1 = new Account(1122, 20_000);
list1.withDraw(2500);
list1.deposit(3000);
list1.setAnnualInterestRate(4.5);
System.out.println(list1.toString() + "\nMonthly Interest: " + list1.getMonthlyInterest());
}
}
import java.util.Date;
//__________________________UML DIAGRAM_____________________________*
/* |
* Fan |
*-------------------------------------------------------------------|
* -id: int |
* |
* -balance: double |
* |
* -annualInterestRate: double |
* |
* -dateCreated: Date |
*-------------------------------------------------------------------|
* Account() |
* |
* Account(id: int, balance: double) |
* |
* getId(): int |
* |
* getBalance(): double |
* |
* getAnnualInterestRate(): double |
* |
* setId(newId: int): void |
* |
* setSBalance(newBlance: double): void |
* |
* setAnnualInterestRate(newRate: double): void |
* |
* getDateCreated(): Date |
* |
* getMonthlyInterestRate(): double |
* |
* getMonthlyInterest(): double |
* |
* withDraw(): void |
* |
* deposit(): void |
*___________________________________________________________________| */
class Account {
private int id;
private double balance;
private double annualInterestRate;
private Date dateCreated;
Account() {
id = 0;
balance = 0;
annualInterestRate = 0;
dateCreated = new Date();
}
Account(int id, double balance) {
this.id = id;
this.balance = balance;
annualInterestRate = 0;
dateCreated = new Date();
}
int getId() {
return id;
}
void setId(int newId) {
this.id = newId;
}
double getBalance() {
return balance;
}
void setbalance(int newBalance) {
this.balance = newBalance;
}
double getAnnualInterestRate() {
return annualInterestRate;
}
void setAnnualInterestRate(double newRate) {
this.annualInterestRate = newRate;
}
Date getDateCreated() {
return dateCreated;
}
double getMonthlyInterestRate() {
return annualInterestRate / 1200;
}
double getMonthlyInterest() {
return getMonthlyInterestRate() * balance;
}
void withDraw(double withdraw) {
balance -= withdraw;
}
void deposit(double deposit) {
balance += deposit;
}
@Override
public String toString() {
return "Account ID: " + getId() + "\nBalance: " + getBalance() +
"\nDate created " + getDateCreated() + "\nCurrent Annual Rate: " + getAnnualInterestRate() + "\n";
}
}
//小节:数据域、常量应该私有;自定义方法应该独立于main方法;学会用toString方法打印全部数据域
输出结果:
Account ID: 1122
Balance: 20500.0
Date created Mon Apr 17 11:40:35 BST 2023
Current Annual Rate: 4.5
Monthly Interest: 76.875
设计一个名为Fan的类来表示一个风扇。这个类包括:
• 三个名为SLOW、MEDIUM和FAST而值为1、2和3的常量,表示风扇的速度
• 一个名为speed的int类型私有数据域,表示风扇的速度(默认值为SLOW)
• 一个名为on的boolean类型私有数据域,表示风扇是否打开(默认值为 false)
• 一个名为radius的double类型私有数据域,表示风扇的半径(默认值为5)
• 一个名为color的string类型数据域,表示风扇的颜色(默认值为blue)
• 这四个数据域的访问器和修改器
• 一个创建默认风扇的无参构造方法
• 一个名为toString()的方法返回描述风扇的字符串。如果风扇是打开的,那么该方法在一个组合的字符串中返回风扇的速度、顔色和半径。如果风扇没有打开,该方法就会返回一个由“fan is off”和风扇颜色及半径组合成的字符串
画出该类的UML图并实现这个类。编写一个测试程序,创建两个Fan对象。将第一个对象设置为最大速度、半径为10、颜色为yellow、状态为打开。将第二个对象设置为中等速度、半径为5、颜色为blue、状态为关闭。通过调用它们的toString方法显示这些对象。
public class Test {
public static void main(String[] args) {
Fan fan1 = new Fan();
fan1.setSpeed(Fan.FAST);
fan1.setRadius(10);
fan1.setColor("yellow");
fan1.setOn(false);
System.out.println("Fan1: \n" + fan1.toString());
Fan fan2 = new Fan();
fan1.setSpeed(Fan.MUDIUM);
fan1.setRadius(50);
fan1.setColor("blue");
fan1.setOn(true);
System.out.println("Fan2: \n" + fan2.toString());
}
}
//__________________________UML DIAGRAM_____________________________*
/* |
* Fan |
*------------------------------------------------------------------|
* +SLOW: int |
* |
* +MEDIUM: int |
* |
* +FAST: int |
* |
* -speed : int |
* |
* -on : boolean |
* |
* -radius : double |
* |
* -color : String |
*------------------------------------------------------------------|
* Fan() |
* |
* getSpeed(): int |
* |
* getOn(): boolean |
* |
* getRadius(): double |
* |
* getColor(): String |
* |
* setSpeed(newSpeed: int): void |
* |
* setOn(newOn: boolean): void |
* |
* setRadius(newRadius: double): void |
* |
* setColor(newColor: String): void |
* |
* toString(): String |
*__________________________________________________________________| */
public class Fan {
public final static int SLOW = 1;
public final static int MUDIUM = 2;
public final static int FAST = 3;
private int speed;
private boolean on;
private double radius;
private String color;
Fan() {
speed = 1;
on = false;
radius = 5;
color = "Blue";
}
int getSpeed() {
return speed;
}
void setSpeed(int newSpeed) {
this.speed = newSpeed;
}
boolean getOn() {
return on;
}
void setOn(boolean newOn) {
this.on = newOn;
}
double getRadius() {
return radius;
}
void setRadius(double newRadius) {
this.radius = newRadius;
}
String getColor() {
return color;
}
void setColor(String newColor) {
this.color = newColor;
}
@Override
public String toString() {
if (on == false)
return "Fan is off. " + "\nColor: " + getColor() + "\nRadius: " + getRadius();
else
return "Speed: " + getSpeed() + "\nColor: " + getColor() + "\nRadius: " + getRadius();
}
}
Fan1:
Fan is off.
Color: yellow
Radius: 10.0
Fan2:
Fan is off.
Color: Blue
Radius: 5.0
在一个正n边形中,所有边的长度都相同,且所有角的度数都相同(即这个多边形是等边等角的)。设计一个名为RegularPolygon的类,该类包括:
• 一个名为n的int型私有数据域定义多边形的边数,默认值为3。
• 一个名为side的double型私有数据域存储边的长度,默认值为1。
• 一个名为×的double型私有数据域定义多边形中点的x坐标,默认值为0。
• 一个名为y的double型私有数据域定义多边形中点的y坐标,默认值为0。
• 一个创建带默认值的正多边形的无参构造方法。
• 一个能创建带指定边数和边长度、中心在(0, 0)的正多边形的构造方法。
• 一个能创建带指定边数和边长度、中心在(x, y)的正多边形的构造方法。
• 所有数据域的访问器和修改器。
• 一个返回多边形周长的方法getPerimeter()
• 一个返回多边形面积的方法getArea()。计算正多边形面积的公式是:
面积 = n ∗ s 2 4 ∗ t a n ( π n ) 面积=\frac{n * s^2}{4 * tan(\frac{\pi}{n})} 面积=4∗tan(nπ)n∗s2
画出该类的UML图并实现这个类。编写一个测试程序,分别使用无参构造方法、RegularPolygon(6, 4)和RegularPolygon(10, 4, 5.6, 7.8)创建三个RegularPolygon对象。显示每个对象的周长和面积。
public class Test {
public static void main(String[] args) {
RegularPolygon test1 = new RegularPolygon();
RegularPolygon test2 = new RegularPolygon(6, 4);
RegularPolygon test3 = new RegularPolygon(10, 4, 5.6, 7.8);
System.out.println("test1的周长是:" + test1.getPerimeter() + ",面积是" + test1.getArea());
System.out.println("test1的周长是:" + test2.getPerimeter() + ",面积是" + test2.getArea());
System.out.println("test1的周长是:" + test3.getPerimeter() + ",面积是" + test3.getArea());
}
}
//_______________________ UML DIAGRAM_______________________________*
/* |
* RegularPolygon |
*------------------------------------------------------------------|
* -n: int (number of sides default 3) |
* |
* -side: double (length of side default 1) |
* |
* -x: double (x of center coordinate default 0) |
* |
* -y: double (y of center coordinate default 0) |
*------------------------------------------------------------------|
* RegularPolygon() |
* |
* RegularPolygon(n: int, side: double) |
* |
* RegularPolygon(n: int, side: double, x: double, y: double) |
* |
* getN(): int |
* |
* setN(newN: int): void |
* |
* getSide(): double |
* |
* setSide(new Side: double): void |
* |
* getX(): double |
* |
* setX(newX: double): void |
* |
* getY(): double |
* |
* setY(newY: double): void |
* |
* getPerimeter(): double |
* |
* getArea(): double |
*__________________________________________________________________| */
class RegularPolygon {
private int n;
private double side;
private double x;
private double y;
RegularPolygon() {
n = 3;
side = 1;
x = 0;
y = 0;
}
RegularPolygon(int n, double side) {
this.n = n;
this.side = side;
x = 0;
y = 0;
}
RegularPolygon(int n, double side, double x, double y) {
this.n = n;
this.side = side;
this.x = x;
this.y = y;
}
int getN() {
return n;
}
void setN(int newN) {
this.n = newN;
}
double getSide() {
return side;
}
void setSide(double newSide) {
this.side = newSide;
}
double getX() {
return x;
}
void setX(double newX) {
this.x = newX;
}
double getY() {
return y;
}
void setY(double newY) {
this.y = newY;
}
double getPerimeter() {
return side * n;
}
double getArea() {
return (n * side * side) / (4 * Math.tan(Math.PI/n));
}
}
输出结果:
test1的周长是:3.0,面积是0.43301270189221946
test1的周长是:24.0,面积是41.569219381653056
test1的周长是:40.0,面积是123.10734148701015
*9.10( 代数:二次方程式)
为二次方程式 a x 2 + b x + c − 0 ax^2+bx+c-0 ax2+bx+c−0设计一个名为QuadraticEquation的类。这个类包括:
• 代表三个系数的私有数据域a、b和c。
• 一个参数为a、b和c的构造方法。
• a、b、c的三个get方法。
• 一个名为getDiscriminant()的方法返回判别式, b 2 − 4 a c b^2-4ac b2−4ac。
• 名为getRoot1()和getRoot2()的方法返回等式的两个根:
r 1 = − b + b 2 − 4 a c 2 a r_1 = \frac{-b + \sqrt{b^2 - 4ac}}{2a} r1=2a−b+b2−4ac r 2 = − b − b 2 − 4 a c 2 a r_2 = \frac{-b - \sqrt{b^2 - 4ac}}{2a} r2=2a−b−b2−4ac
这些方法只有在判别式为非负数时才有用。如果判别式为负,这些方法返回0。
画出该类的UML图并实现这个类。编写一个测试程序,提示用户输入a、b和c的值,然后显示判别式的结果。如果判别式为正数,显示两个根;如果判别式为0,显示一个根;否则, 显示“The equation has no roots.”(这个方程无根)。参见编程练习题3.1的运行示例。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Please input a, b and c accordingly: ");
double a = scanner.nextDouble();
double b = scanner.nextDouble();
double c = scanner.nextDouble();
QuadraticEquation test1 = new QuadraticEquation(a, b, c);
if (test1.getDiscriminant() < 0)
System.out.println("The equation has no roots.");
else if (test1.getDiscriminant() == 0)
System.out.println("The root is " + test1.getRoot1());
else
System.out.println("The root is" + test1.getRoot1() + " and " + test1.getRoot2());
}
}
//_______________________ UML DIAGRAM_______________________________*
/* |
* QuadraticEquation |
*------------------------------------------------------------------|
* -a: double |
* |
* -b: double |
* |
* -c: double |
*------------------------------------------------------------------|
* QuadraticEquation(a: double, b: double, c: double) |
* |
* getA(): double |
* |
* getB(): double |
* |
* getC(): double |
* |
* getDiscriminant(): double |
* |
* getRoot1(): double |
* |
* getRoot2(): double |
*__________________________________________________________________| */
class QuadraticEquation {
private double a;
private double b;
private double c;
QuadraticEquation(double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
double getA() {
return a;
}
double getB() {
return b;
}
double getC() {
return c;
}
double getDiscriminant() {
return Math.pow(b, 2) - 4 * a * c;
}
double getRoot1() {
return (-b + Math.pow(getDiscriminant(), 0.5)) / (2 * a);
}
double getRoot2() {
return (-b - Math.pow(getDiscriminant(), 0.5)) / (2 * a);
}
}
输出结果:
Please input a, b and c accordingly:
1 2 3
The equation has no roots.
*9.11(代数:2×2的线性方程)
为一个2×2的线性方程设计一个名为LinearEquation的类:
a x + b y = e ax+by=e ax+by=e
c x + d y = f cx+dy=f cx+dy=f
x = e d − b f a d − b c x=\frac{ed-bf}{ad-bc} x=ad−bced−bf
y = a f − e c a d − b c y=\frac{af-ec}{ad-bc} y=ad−bcaf−ec
这个类包括:
• 私有数据域a、b、c、d、e和f。
• 一个参数为a、b、c、d、e、f的构造方法。
• a、b、c、d、e、f的六个get方法。
• 一个名为isSolvable()的方法,如果ad-bc不为0则返回true。
• 方法getX()和getY()返回这个方程的解。
画出该类的UML图并实现这个类。编写一个测试程序,提示用户输入a、b、c、d、e、f的值, 然后显示它的结果。如果ad-bc为0,就报告“The equation has no solution.”。参见编程练习题3.3的运行示例。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Please input a, b, c, d, e and f accordingly: ");
double a = scanner.nextDouble();
double b = scanner.nextDouble();
double c = scanner.nextDouble();
double d = scanner.nextDouble();
double e = scanner.nextDouble();
double f = scanner.nextDouble();
LinearEquation test1 = new LinearEquation(a, b, c, d, e, f);
if (test1.isSolvable() == false)
System.out.println("The equation has no solution.");
System.out.println("X is " + test1.getX() + " and Y is " + test1.getY());
}
}
//____________________________________ UML DIAGRAM_____________________________________________*
/* |
* LinearEquation |
*----------------------------------------------------------------------------------------------|
* -a: double |
* |
* -b: double |
* |
* -c: double |
* |
* -d: double |
* |
* -e: double |
* |
* -f: double |
*----------------------------------------------------------------------------------------------|
* LinearEquation(a: double, b: double, c: double, d: double, e: double, f: double) |
* |
* getA(): double |
* |
* getB(): double |
* |
* getD(): double |
* |
* getE(): double |
* |
* getF(): double |
* |
* isSolvable(): boolean |
* |
* getX(): double |
* |
* getY(): double |
*______________________________________________________________________________________________| */
class LinearEquation {
private double a;
private double b;
private double c;
private double d;
private double e;
private double f;
LinearEquation(double a, double b, double c, double d, double e, double f) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
}
double getA() {
return a;
}
double getB() {
return b;
}
double getC() {
return c;
}
double getD() {
return d;
}
double getE() {
return e;
}
double getF() {
return f;
}
boolean isSolvable() {
if (a * d - b * c != 0) {
return true;
}
return false;
}
double getX() {
return (e * d - b * f) / (a * d - b * c);
}
double getY() {
return (a * f - e * c) / (a * d - b * c);
}
}
输出结果:
Please input a, b, c, d, e and f accordingly:
1 2 3 4 5 6
X is -4.0 and Y is 4.5
假设两条线段相交。第一条线段的两个端点是(x1, y1)和(x2, y2),第二条线段的两个端点是(x3, y3)和(x4, y4)。编写一个程序,提示用户输入这四个端点,然后显示它们的交点。如编程练习题3.25所讨论的,可以通过对一个线性方程求解来得到。使用编程练习题9.11中的LinearEquation类来求解该方程。参见编程练习题3.25的运行示例。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter four endpoints for two lines: x1, y1, x2, y2, x3, y3, x4, y4: ");
double[] nums = new double[8];
for (int i = 0; i < 8; i++) {
nums[i] = in.nextDouble();
}
double a = nums[1] - nums[3];
double b = -(nums[0] - nums[2]);
double c = nums[5] - nums[7];
double d = -(nums[4] - nums[6]);
double e = (nums[1] - nums[3]) * nums[0] - (nums[0] - nums[2]) * nums[1];
double f = (nums[5] - nums[7]) * nums[4] - (nums[4] - nums[6]) * nums[5];
LinearEquation linearEquation = new LinearEquation(a, b, c, d, e, f);
if (linearEquation.isSolvable()) {
System.out.printf("The intersecting point is at (%.2f, %.2f)", linearEquation.getX(),
linearEquation.getY());
} else {
System.out.println("The equation does not have a solution with the points provided.");
}
}
}
测试类在9.11中已经给出代码
输出结果:
Enter four endpoints for two lines: x1, y1, x2, y2, x3, y3, x4, y4:
1 1 2 2 3 3 4 4
The equation does not have a solution with the points provided.
设计一个名为Location的类,定位二维数组中的最大值及其位置。这个类包括公共的数据域row、column和maxValue,二维数组中的最大值及其下标用int型的row 和column以及double型的maxValue存储。
编写下面的方法,返回一个二维数组中最大值的位置。
public static Location locateLargest(double[][]a)
返回值是一个Location的实例。编写一个测试程序,提示用户输入一个二维数组,然后显示这个数组中最大元素的位置。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//让用户选择数组的行数和列数,并创建对应的数组
Scanner scanner = new Scanner(System.in);
System.out.print("Please select the number of lines and columns of an array: ");
int numLine = scanner.nextInt();
int numColumn = scanner.nextInt();
double[][] numbers = new double[numLine][numColumn];
//让用户填充数据进入创建好的数组
System.out.print("Please specify your array: ");
for (int a = 0; a < numbers.length; a++) {
for (int b = 0; b < numbers[a].length; b++) {
numbers[a][b] = scanner.nextDouble();
}
}
//引用方法寻找最大值
Location location = new Location();
System.out.println("The loction of the largest element is " + numbers[location.findMaxX(numbers)][location.findMaxY(numbers)] + " at (" + location.findMaxX(numbers) + ", " + location.findMaxY(numbers) + ")");
}
}
class Location {
private int line;
private int column;
private double max = Integer.MIN_VALUE;
int i = 0;
int j = 0;
//返回最大值所对应的数组的行号
int findMaxX(double[][] a) {
for (; i < a.length; i++) {
for (; j < a[i].length; j++) {
if(a[i][j] > max) {
max = a[i][j];
}
}
}
//注意要用i-1,是因为for循环的i在最后一次无法循环而退出时,仍然会+1
return i - 1;
}
//返回最大值所对应的数组的列号
int findMaxY(double[][] a) {
for (; i < a.length; i++) {
for (; j < a[i].length; j++) {
if(a[i][j] > max) {
max = a[i][j];
}
}
}
//注意要用j-1,是因为for循环的j在最后一次无法循环而退出时,仍然会+1
return j - 1;
}
}
输出结果:
Please select the number of lines and columns of an array: 3 3
Please specify your array: 1 2 3 4 5 6 7 8 9
The loction of the largest element is 9.0 at (2, 2)