"Fundamentos de Java Black Book, 10.ª edición" Capítulo 13 [Ejercicio]

Ejercicios de Programación en Lenguaje Java Capítulo 13

13.1 Ejercicios del capítulo

13.1 ¿Cuál de las siguientes definiciones de clase define clases abstractas legales?

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();
}

mi)

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

F)

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

13.2 El método getArea() y el método getPerimeter() se pueden eliminar de la clase GeometricObject. ¿Cuál es el beneficio de definir estos dos métodos como métodos abstractos en la clase GeometricObject?

Durante la compilación, un objeto declarado como GeometricObject puede usar estos dos métodos

De lo contrario, no hay forma de calcular el perímetro y el área.

13.3 ¿Es verdadera o falsa la siguiente afirmación?

a. Una clase abstracta se puede usar como una clase no abstracta, excepto que no se puede crear una instancia de una clase abstracta usando el operador nuevo.

real

b. Las clases abstractas se pueden heredar

real

c. Una subclase de una clase principal no abstracta no puede ser abstracta

Falso

d. La subclase no puede anular el método específico en la clase principal y definirlo como abstracto

Falso

e. Los métodos abstractos deben ser no estáticos

real

13.3 Ejercicios de capítulo

13.4 ¿Por qué las siguientes dos líneas de código se pueden compilar con éxito, pero causarán un error de tiempo de ejecución?

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

13.5 ¿Por qué las siguientes dos líneas de código se pueden compilar con éxito, pero causarán un error de tiempo de ejecución?

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

13.6 Dé la salida del siguiente código.

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 ¿Qué tiene de malo el siguiente código? (Observe que el método compareTo de las clases Integer y Double se describe en la Sección 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 ¿Qué está mal en el siguiente código?

// 很好的例子,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 Ejercicios del capítulo

13.9 ¿Se puede usar la clase Calendario para crear un objeto Calendario?

No, Calendar es una clase abstracta.

13.10 ¿Qué método de la clase Calendario es abstracto?

añadir método

13.11 ¿Cómo creo un objeto Calendario para la hora actual?

Constructor sin parámetros de GregorianCalendar

13.12 Para un objeto Calendario c, ¿cómo obtener su año, mes, fecha, hora, minuto y segundo?

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)); 
  }
}

Resultado de salida:

Cabe señalar que el MES en la clase Calendario se cuenta desde 0

2023
4
15
9
35
25

13.5 Ejercicios de capítulo

13.13 Suponiendo que A es una interfaz, ¿se puede usar newA() para crear una instancia?

No poder

13.14 Suponiendo que A es una interfaz, ¿se puede declarar una variable de referencia x de tipo A de la siguiente manera?

A x;

Poder

13.15 ¿Cuál de las siguientes es la interfaz correcta?

// 在抽象类中,既可以有抽象方法(没有方法体),也可以有具体的方法(有方法体),子类继承抽象类后,必须实现抽象方法,可以选择性的实现具体的方法
// 在旧版本的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 Señale el error en el siguiente código

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

class B implements A {
    
    
  void m1() {
    
    
    System.out.println("m1");
  }
}

13.6 Ejercicios de capítulo

13.17 ¿La siguiente afirmación es verdadera o falsa? Si una clase implementa Comparable, entonces los objetos de esta clase pueden llamar al método compareTo

correcto

13.18 ¿Cuál de los siguientes es el encabezado de método correcto para el método compareTo en la clase String?

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

13.19 ¿Compilará el siguiente código?, ¿por qué?

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

13.20 Un método compareTo puede definirse en una clase sin implementar la interfaz Comparable. ¿Cuáles son los beneficios de implementar la interfaz Comparable?

Al implementar la interfaz Comparable, los objetos de una clase se pueden pasar a métodos que esperan un tipo Comparable.

13.21 ¿Qué está mal con el siguiente código?

// 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 Ejercicios de capítulo

13.22 Si la clase de un objeto no implementa java.lang.Cloneable, ¿se puede llamar al método clone() para clonar el objeto?¿La clase Date implementa la interfaz Cloneable?

No se informará ningún error durante la fase de compilación y se puede compilar normalmente. Pero se informará una excepción durante el tiempo de ejecución. Por lo tanto, si desea llamar a.clone() en el método principal, la clase donde se encuentra el objeto debe implementar Cloneable

Logrado. Si no se implementa, se informará una excepción al clonar

13.23 ¿Qué sucede si la clase Casa (definida en el Listado 13-11) no anula el método clone(), o si la clase Casa no implementa java.lang.Cloneable?

Si clone() no está cubierto, el compilador informará un error

Si Cloneable no está implementado, se informará una excepción

13.24 Dar la salida del siguiente código

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 Da el resultado del siguiente código

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 ¿Qué está mal con el siguiente código?

// 实现接口,重写方法
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 Ejercicios de capítulo

13.27 Dé un ejemplo que muestre la ventaja de las interfaces sobre las clases abstractas.

herencia múltiple

13.28 Dar definiciones de clases e interfaces abstractas. ¿Cuáles son las similitudes y diferencias entre las clases abstractas y las interfaces?

  1. Definición: una interfaz es una clase completamente abstracta que solo contiene declaraciones de métodos pero no implementaciones; una clase abstracta es una clase que puede contener métodos abstractos e implementaciones de métodos concretos.
  2. Método de implementación: una clase puede tener múltiples interfaces, pero solo puede heredar de una clase.
  3. Constructor: una interfaz no tiene constructor, mientras que una clase abstracta puede tener un constructor.
  4. Variables miembro: solo se pueden definir constantes en las interfaces y no se pueden definir variables de instancia; las clases abstractas pueden contener variables de instancia.
  5. Herencia entre interfaces: las interfaces pueden heredar múltiples interfaces para formar una relación de herencia entre interfaces; las clases abstractas solo pueden implementar relaciones de herencia a través de la herencia de clases.

13.29 ¿Verdadero o falso?

a. Las interfaces se compilan en archivos de bytecode separados.

real

b. Las interfaces pueden tener métodos estáticos.

real

C. Una interfaz puede extender una o más interfaces.

real

d. Las interfaces pueden extender clases abstractas.

Falso

mi. Las clases abstractas pueden ampliar las interfaces.

real

13.9 Ejercicios de capítulo

13.30 Da el resultado del siguiente código.

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 ¿Qué está mal con el siguiente código?

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

13.32 ¿Qué está mal con el siguiente código?

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

13.33 ¿Cómo puedo simplificar el programa en las líneas 82-85 del Listado 13-13 usando una línea de código en lugar de una instrucción if?

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 Traza cuidadosamente la ejecución del programa, dando la salida del siguiente código.

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

13.10 Ejercicios de capítulo

13.35 Describa los principios de diseño de las clases.

13.10.1 Cohesión

13.10.2 — Coherencia

13.10.3 Encapsulación

13.10.4 Claridad

13.10.5 Integridad

13.10.6 Instancias y estáticas

13.10.7 Herencia y agregación

13.10.8 Interfaces y clases abstractas

ejercicios de programacion

**13.1 (clase Triángulo)

Diseñe una nueva clase Triangle que se extienda desde la clase abstracta GeometricObject. Dibuje el diagrama UML de la clase Triangle y la clase GeometricObject e implemente la clase Triangle. Escriba un programa de prueba que solicite al usuario los tres lados de un triángulo, un color y un valor booleano que indique si el triángulo está lleno. El programa debe crear un objeto Triángulo basado en la entrada del usuario, usando estos lados e información sobre su color y si están rellenos. El programa debe mostrar el área, el perímetro, el color y verdadero o falso para indicar si está lleno o no.

prueba.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();
	}
} 

Objeto Geométrico.java

package learning;

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

Triángulo.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;
	}
	
	@Override
	double getPerimeter() {
    
    
		return side1 + side2 + side3;
	}
	
	@Override
	double getArea() {
    
    
		return Math.pow((getPerimeter() * 0.5) * (getPerimeter() - side1) * (getPerimeter() - side2) * (getPerimeter() - side3), 0.5);
	}
	
	@Override
	public 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.";
		}
}

Resultado de salida:

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 (Lista de matriz aleatoria)

Escriba el siguiente método para codificar los números almacenados en 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 {
    
    
	// 用户可以设置希望打乱多大的数组,本例中设置为10
	private 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());
	}
} 

Resultado de salida:

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 (Ordenar ArrayList)

Escriba el siguiente método para ordenar los números almacenados en 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外只输出最终数组
	}
} 

Resultado de salida:

初始排序 :[5, 9, 2, 7, 3]
最终排序 :[2, 3, 5, 7, 9]
**13.4 (mostrar calendario)

Reescriba la clase PrintCalendar en el Listado 6-12 para usar las clases Calendar y GregorianCalendar para mostrar un calendario para un mes determinado. Su programa obtiene la entrada de mes y año desde la línea de comando, por ejemplo:

java Exercisel3_04 5 2016

También es posible ejecutar el programa sin ingresar un año. En este caso, el año es el año actual. Si no especifica el mes y el año para ejecutar el programa, se refiere al mes actual

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 calendar
    printMonthTitle(year, month);

    // Print the body of the calendar
    printMonthBody(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 month
    int startDay = getStartDay(year, month);

    // Get number of days in the month
    int numberOfDaysInMonth = getNumberOfDaysInMonth(year, month);

    // Pad space before the first day of the month
    int 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/year
    int totalNumberOfDays = getTotalNumberOfDays(year, month);

    // Return the start day for month/1/year
    return (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/year
    for (int i = 1800; i < year; i++)
      if (isLeapYear(i))
        total = total + 366;
      else
        total = total + 365;

    // Add days from Jan to the month prior to the calendar month
    for (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);
  }
}

Resultado de salida:

// 不指定年月
java /Users/kevinwang/eclipse-workspace/test/src/learning/Test.java
         May 2023
-----------------------------
 Sun Mon Tue Wed Thu Fri Sat
       1   2   3   4   5   6
   7   8   9  10  11  12  13
  14  15  16  17  18  19  20
  21  22  23  24  25  26  27
  28  29  30  31
*13.5 (hace que la clase GeometricObject sea comparable)

Modifique la clase GeometricObject para implementar la interfaz Comparable y defina un método máximo estático para encontrar el mayor de los dos objetos GeometricObject en la clase GeometricObject. Dibuje el diagrama UML e implemente esta nueva clase GeometricObject. Escriba un programa de prueba que use el método max para encontrar el mayor de dos círculos y el mayor de dos rectángulos.

prueba.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);
	}
}

Objeto Geométrico.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需要覆写,如果当前抽象类没有覆写,继承抽象类的常规子类就必须覆写
	@Override
	public 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());
		else
			System.out.println("Equal");
	}
	
	// 需要注意的是,如果GeometricObject类,Circle类和Rectangle类都覆写了toString,那么调用哪个toString,会根据多态,取决于变量的实际类型
	// 如果Circle类和Rectangle类没有覆写toString,那么就会调用GeometricObject类的toString
	// 例如,GeometricObject类,Circle类和Rectangle类都覆写了toString,那么下面的toString就不会被调用
	@Override
	public String toString() {
    
    
		return "I will not be invoked";
	}
}

círculo.java

package learning;

class Circle extends GeometricObject{
    
    
	double radius;
	
	Circle(double radius) {
    
    
		this.radius = radius;
	}

	// GeometricObject实现了抽象方法getArea,子类必须强制调用
	@Override
	double getArea() {
    
    
		return Math.PI * radius * radius;
	}
	
	@Override
	public String toString() {
    
    
		return "The " + radius + " radius object is larger";
	}
}

Rectángulo.java

package learning;

class Rectangle extends GeometricObject{
    
    
	double width;
	double height;
	
	Rectangle(double width, double height) {
    
    
		this.width = width;
		this.height = height;
	}

	// GeometricObject实现了抽象方法getArea,子类必须强制调用
	@Override
	double getArea() {
    
    
		return Math.PI * width * height;
	}	
	
	@Override
	public String toString() {
    
    
		return "The " + width + " width and " + height + " height object is larger";
	}
}

Resultado de salida:

The 10.0 radius object is larger
The 10.0 width and 20.0 height object is larger
*13.6 (Círculo comparable类)

Cree una clase llamada ComparableCircle que herede de la clase Circle e implemente la interfaz Comparable. Dibuje el diagrama UML e implemente el método compareTo para comparar dos círculos según su área. Escriba un programa de prueba que encuentre la mayor de dos instancias de un objeto ComparableCircle.

prueba.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));
	}
}

círculo.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;
	}
	
	@Override
	double getArea() {
    
    
		return Math.PI * radius * radius;
	}
	
	@Override
	public int compareTo(ComparableCircle o) {
    
    
		if (getArea() > o.getArea())
			return 1;
		else if (getArea() < o.getArea())
			return -1;
		else
			return 0;
	}
}

Resultado de salida:

-1
*13.7 (interfaz coloreable Coloreable)

Diseñe una interfaz llamada Colorable con un método vacío llamado howToColor(). Cada clase de un objeto Colorable debe implementar la interfaz Colorable. Diseñe una clase llamada Square, que herede de la clase CeometricObject e implemente la interfaz Colorable. Implemente el método howToColor para mostrar un mensaje Colorea los cuatro lados (colorea los cuatro lados).

Dibuje un diagrama UML que incluya Colorable, Square y CeometricObject. Escriba un programa de prueba que cree una matriz de cinco objetos GeometricObject. Para cada objeto de la matriz, si el objeto es coloreable, se llama al método howToColor.

prueba.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();
	}
}

Objeto Geométrico.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;
	}
	
	@Override
	public void howToColor() {
    
    
		System.out.println("Color all four sides");
	}
}

Colorable.java

package learning;

interface Colorable {
    
    
	void howToColor();
}
*13.8 (clase MyStack modificada)

Reescriba la clase MyStack en el Listado 11-10 para realizar una copia profunda del campo de lista

Prueba.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());
    }

}

Mi pila.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);

    }

    @Override
    public 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;
    }

    @Override
    public String toString() {
    
    
        return "Stack: " + list.toString();

    }
}

Resultado de salida:

false
Cloned Stack: [One, Two, Three]
Original Stack: [One, Two, Three, Four]
*13.9 (Cambiar clase de Círculo a Comparable)

Reescriba la clase Circle en el Listado 13-2, que hereda de la clase GeometricObject e implementa la interfaz Comparable. Anula el método equals en la clase Object. Dos objetos Circle son idénticos cuando tienen el mismo radio. Dibuje un diagrama UML que incluya Circle, GeometricObject y Comparable.

prueba.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));
    }
}

círculo.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;
  }

  @Override
  public int compareTo(Circle c) {
    
    
	  if (getArea() > c.getArea())
		  return 1;
	  else if (getArea() < c.getArea())
		  return -1;
	  else 
		  return 0;
  }
  
  @Override
  public boolean equals(Object ob) {
    
    
	  Circle circle = (Circle) ob;
	    return this.radius == circle.radius;
	}
}

Objeto Geométrico.java

package learning;

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

Resultado de salida:

true
0
* 13.10 (hacer comparable la clase Rectangle)

Reescriba la clase Rectangle en el Listado 13-3, que hereda de la clase GeometricObject e implementa la interfaz Comparable. Anula el método equals en la clase Object. Dos objetos Rectángulo son idénticos si tienen la misma área. Dibuja diagramas UML que incluyen Rectangle, GeometricObject y Comparable

prueba.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));
    }
}

Objeto Geométrico.java

package learning;

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

Rectángulo.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;
    }

    @Override
    public int compareTo(Rectangle obj) {
    
    
        if (this.getArea() > obj.getArea()) {
    
    
            return 1;
        } else if (this.getArea() < obj.getArea()) {
    
    
            return -1;
        } else
            return 0;

    }

    @Override
    public boolean equals(Object ob) {
    
    
        Rectangle r = (Rectangle) ob;
        double thisArea = this.getArea();
        double rArea = r.getArea();
        // 等号的左边必须是变量,因此前面新声明了一个变量表示面积
        return thisArea == rArea;

    }
}
*13.11 (clase octágono Octágono)

Escriba una clase llamada Octagon que herede de la clase GeometricObject e implemente las interfaces Comparable y Cloneable. Suponga que los ocho lados del octágono tienen todos la misma longitud. Su área se puede calcular con la siguiente fórmula:

Área = ( 2 + 4 / √ 2 ) × longitud del lado × longitud del lado Área = (2+4/√2) × longitud del lado × longitud del ladoárea=( 2+4/√2 )×largo de lado×largo de lado

Dibuje diagramas UML que incluyen Octagon, GeometricObject, Comparable y Cloneable. Escriba un programa de prueba para crear un objeto octágono cuya longitud lateral sea 5 y luego muestre su área y perímetro. Cree un nuevo objeto usando el método de clonación y compare los dos objetos usando el método compareTo.

prueba.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));
    }
}

Objeto Geométrico.java

package learning;

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

octágono.java

package learning;

class Octagon extends GeometricObject implements Cloneable, Comparable<Octagon>{
    
    
	private double side;
	
	Octagon() {
    
    
		this(1.0);
	}
	
	Octagon(double side) {
    
    
		this.side = side;
	}
	
	@Override
	protected double getPerimeter() {
    
    
		return side * 8;
	}
	
	@Override
	protected double getArea() {
    
    
		return (2 + 4 / Math.pow(2, 0.5) * side * side);
	}
	
	@Override
	public 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();
	}
}

Resultado de salida:

40.0
72.71067811865474
0
*13.12 (encontrar la suma de las áreas de objetos geométricos)

Escribe un método que encuentre la suma de las áreas de todos los objetos geométricos en la matriz. La firma del método es la siguiente:

public static double sumArea(Geometricobject[] a)

Escriba un programa de prueba que cree una matriz de cuatro objetos (dos círculos y dos rectángulos) y luego use el método sumArea para encontrar su área total.

prueba.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;
    }
}

Objeto Geométrico.java

package learning;

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

círculo.java

package learning;

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

Rectángulo.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;
	}
	
	@Override
	protected double getArea() {
    
    
		return width * height;
	}
	
}

Resultado de salida:

110.53981633974483
*13.13 (hace que la clase del curso sea copiable)

Reescriba la clase Curso en el Listado 10-6, agregando un método de clonación que realiza una copia profunda en el campo de los estudiantes.

prueba.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()));
    }
}

Curso.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;
  }  
  
  @Override
  protected 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;
  }
}

Resultado de salida:

c1 == c2 is false
*13.14 (para demostrar los beneficios de la encapsulación)

Reescriba la clase Racional en la Sección 13.13 para usar la nueva representación interna del numerador y el denominador. Cree una matriz con dos enteros de la siguiente manera:

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

Use r[0] para el numerador y r[1] para el denominador. Las firmas de métodos en la clase Rational no han cambiado, por lo que las aplicaciones cliente de la clase Rational anterior pueden seguir utilizando la nueva clase Rational sin volver a compilar.

// 替换字段处即可
private long[] r = new long[2];
private long numerator = r[0];
private long denominator = r[1];
13.15 (usando BigInteger en clases de Rational)

Use Biglnteger para representar el numerador y el denominador, rediseñe e implemente

package learning;

import java.math.BigInteger;

public class Rational extends Number implements Comparable<Rational> {
    
    
    // Data fields for numerator and denominator
    private 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);
    }

    @Override
    public String toString() {
    
    
        if (denominator.intValue() == 1)
            return numerator + "";
        else
            return numerator + "/" + denominator;
    }

    @Override 
    public boolean equals(Object other) {
    
    
        if ((this.subtract((Rational) (other))).getNumerator() == 0)
            return true;
        else
            return false;
    }

    @Override 
    public int intValue() {
    
    
        return (int) doubleValue();
    }

    @Override 
    public float floatValue() {
    
    
        return (float) doubleValue();
    }

    @Override
    public 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;
        else
            return 0;
    }
}
*13.16 (crear una calculadora de números racionales)

Escriba un programa similar al Listado 7-9. En lugar de usar números enteros, usamos números racionales, como se muestra en la figura 13-10a. Debe usar el método split en la clase String presentada en la Sección 10.10.3 para obtener la cadena del numerador y la cadena del denominador, y usar el método Integer.parseInt para convertir la cadena en un número entero

prueba.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)));
         }
    }
}

Racional.java

package learning;

public class Rational extends Number implements Comparable<Rational> {
    
    
	  // Data fields for numerator and denominator
	  private 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 + "";
	    else
	      return 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;
	    else
	      return 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 Number
	  public long longValue() {
    
    
	    return (long)doubleValue();
	  }

	  @Override // Implement the compareTo method in Comparable
	  public int compareTo(Rational o) {
    
    
	    if (this.subtract(o).getNumerator() > 0)
	      return 1;
	    else if (this.subtract(o).getNumerator() < 0)
	      return -1;
	    else
	      return 0;
	  }
	}

Resultado de salida:

1/9
*13.17 (Matemáticas: Clase compleja)

Un número complejo es un número de la forma a+bi, donde a y b son números reales y i es − 1 \sqrt{-1}1 raíz cuadrada de . Los números a y b se denominan partes real e imaginaria de un número complejo, respectivamente. La suma, la resta, la multiplicación y la división de números complejos se pueden realizar mediante las siguientes fórmulas:

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)

El valor absoluto de un número complejo también se puede obtener mediante la siguiente fórmula:

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

(El número complejo se puede interpretar como un punto en un plano, y el valor (a, b) se usa como la coordenada del punto. El valor absoluto del número complejo es la distancia desde el punto hasta el origen, como se muestra en la Figura 13-10b.)

Diseñe un número complejo llamado Complex para representar números complejos y métodos de suma, resta, multiplicación, división y abs para completar operaciones complejas, e invalide el método toString para devolver una cadena que represente números complejos. El método toString devuelve la cadena a+bi. Si b es 0, simplemente devuelve a. La clase Complex también debería implementar la interfaz Cloneable.

Se proporcionan tres métodos de construcción Complex(a, b), Complex(a) y Complex(). Complex() crea un objeto Complex con el número 0, y Complex(a) crea un objeto Complex con b igual a 0. Los métodos getRealPart() y getImaginaryPart() también se proporcionan para devolver las partes real e imaginaria de un número complejo, respectivamente.

Escriba un programa de prueba que solicite al usuario que ingrese dos números complejos y luego muestre los resultados de sumar, restar, multiplicar y dividirlos. Aquí hay un ejemplo en ejecución:

prueba.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());
    }
}

Complejo.java

package learning;

class Complex {
    
    
	  public double a;
	  public double b;
	  
	  //会依次调用之后的两个构造方法,注意如果没有传入值,默认0.0
	  public 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
	  // 输出对象时,会自动调用toString
	  public String toString() {
    
    
		  if (b == 0)
			  return a + "";
		  else
			  return a + " + " + b + "i";
	  }
}

Resultado de salida:

0.0 + 6.5i
7.0 + 4.5i
-17.75 + -15.75i
-0.5094339622641509 + -1.7169811320754718i
6.519202405202649
13.18 (usando clases de Rational)

Escriba un programa que use la clase Rational para calcular la siguiente secuencia de suma:

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

Encontrará que la salida es incorrecta porque el número entero se desborda (demasiado grande). Para resolver este problema, consulte el ejercicio de programación 13.15.

Copie el código Rational de 13.15 directamente, y solo se proporciona a continuación la clase de prueba Test

prueba.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());

    }
}

Resultado de salida:

1/2 + 2/3 + 3/4 + ... + 97/98 + 98/99 + 99/100 = 1349247664274259951 / 1822963237492290880
13.19 (conversión de números decimales a fracciones)

Escriba un programa que solicite al usuario que ingrese un número decimal y luego muestre ese número como una fracción. Sugerencia: lea el número decimal en forma de cadena, extraiga su parte entera y su parte fraccionaria de la cadena y luego use la clase Rational implementada usando Biglnteger en el ejercicio de programación 13.15 para obtener el número racional del número decimal. Aquí hay algunos ejemplos en ejecución:

Las últimas 3 preguntas comparan las habilidades matemáticas. La lógica de programación no es difícil, pero las matemáticas son difíciles jajaja. . .

Copie el código Rational de 13.15 directamente, y solo se proporciona a continuación la clase de prueba Test

prueba.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();

    }
}

Resultado de salida:

Enter a decimal number: 3.25
The fraction number is 13/4
13.20 (Matemáticas: Resolución de ecuaciones en dos variables)

Reescriba el ejercicio de programación 3.1, si el determinante es menor que 0, use la clase Complex en el ejercicio de programación 13.17 para obtener la raíz imaginaria. Aquí hay algunos ejemplos en ejecución:

Las últimas 3 preguntas comparan las habilidades matemáticas. La lógica de programación no es difícil, pero las matemáticas son difíciles jajaja. . .

Copie directamente el código complejo de 13.17, solo la clase de prueba de prueba se proporciona a continuación

prueba.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();
        }

    }
}

Resultado de salida:

Enter a, b, c: 1 2 3
The roots are -1.0 + 1.4142135623730951i and -1.0 + -1.4142135623730951i
13.21 (Álgebra: ecuaciones de vértice)

La ecuación parabólica se puede expresar en forma estándar (y=ax 2+bx+c) o en forma de vértice (y=a(xh) 2+k). Escriba un programa que solicite al usuario los números enteros a, b y c en forma estándar y muestre los valores de h y k en forma de vértice. Aquí hay algunos ejemplos en ejecución:

Las últimas 3 preguntas comparan las habilidades matemáticas. La lógica de programación no es difícil, pero las matemáticas son difíciles jajaja. . .

Copie el código Rational de 13.15 directamente, y solo se proporciona a continuación la clase de prueba Test

prueba.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);
    }
}

Resultado de salida:

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

Supongo que te gusta

Origin blog.csdn.net/weixin_40020256/article/details/130799494
Recomendado
Clasificación