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

Java语言程序设计 习题第九章

9.3章节习题

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.4章节习题

9.5 构造方法和普通方法之间的区别是什么?

构造方法没有返回值,普通方法有返回值

构造方法的功能用来初始化对象,普通方法的功能随需求而定

构造方法会在创建对象时一定会执行一次,普通方法可以在创建对象后多次执行

9.6 什么时候类将有一个默认构造方法?

程序中没有定义任何构造方法的时候

9.5章节习题

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.6章节习题

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.7章节习题

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.9章节习题

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.10章节习题

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.11章节习题

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.12章节习题

9.28 如果类中仅包含私有数据域并且没有设置set方法,该类可以改变吗?

如果get方法返回了数据域中的可变引用类型,就可以通过这个引用改变数据域的值

9.29 如果类中的所有数据域是私有的基本数据类型,并且类中没有包含任何set方法,该类可以改变吗?

不可以改变,因为没有引用类型

9.30 下面的类可以改变吗?

public class A { 
  private int[] values;

	public int[] getValues() {
		return values; 
  }
}

可以改变,因为数组是引用类型

9.13章节习题

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.14章节习题

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.1 (矩形类Rectangle)

遵照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 (股票类Stock)

遵照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%
*9.3 (使用日期类Date)

编写程序创建一个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
*9.4 (使用随机类Random)

编写一个程序,创建种子是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 
*9.5 (使用公历类GregorianCalendar)

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
*9.6 (秒表)

设计一个名为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
9.8 (风扇类Fan)

设计一个名为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
**9.9(几何:正n边形)

在一个正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})} 面积=4tan(nπ)ns2

画出该类的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+c0设计一个名为QuadraticEquation的类。这个类包括:

• 代表三个系数的私有数据域a、b和c。

• 一个参数为a、b和c的构造方法。

• a、b、c的三个get方法。

• 一个名为getDiscriminant()的方法返回判别式, b 2 − 4 a c b^2-4ac b24ac

• 名为getRoot1()和getRoot2()的方法返回等式的两个根:

r 1 = − b + b 2 − 4 a c 2 a r_1 = \frac{-b + \sqrt{b^2 - 4ac}}{2a} r1=2ab+b24ac r 2 = − b − b 2 − 4 a c 2 a r_2 = \frac{-b - \sqrt{b^2 - 4ac}}{2a} r2=2abb24ac

这些方法只有在判别式为非负数时才有用。如果判别式为负,这些方法返回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=adbcedbf

y = a f − e c a d − b c y=\frac{af-ec}{ad-bc} y=adbcafec

这个类包括:

• 私有数据域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
**9.12 (几何:交点)

假设两条线段相交。第一条线段的两个端点是(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.
**9.13 (位置类Location)

设计一个名为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)

你可能感兴趣的:(java,jvm,开发语言)