java上机测试错题回顾(4)
不要哇...天啊,期末成绩占比60%,我不行了,不能这么说,我行的,我行的,我行的!!
1 Object参数类型
Java
Object
是所有类的超类,任何对象(包括数组)都可以赋值给Object
类型的变量。- 需要通过 类型转换(casting)才能访问子类的特有属性或方法。
public void process(Object obj) {if (obj instanceof String) {String str = (String) obj; // 类型转换System.out.println(str.length());}
}
2 JAVA的泛型
Java 的泛型(Generics)是 JDK 5 引入的一项特性,它提供了编译时类型安全检查机制,允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
泛型的核心概念
- 类型参数化:将类型作为参数传递,增强代码的复用性。
- 编译时类型检查:在编译阶段进行类型安全检查,减少运行时错误。
- 消除强制类型转换:提高代码可读性和安全性。
- 泛型擦除:泛型信息在编译后被擦除,只保留原始类型。
泛型的使用
泛型类
java
// 定义泛型类
public class Box<T> {private T t;public void set(T t) {this.t = t;}public T get() {return t;}
}// 使用泛型类
Box<Integer> integerBox = new Box<>();
integerBox.set(10);
Integer integer = integerBox.get(); // 无需强制类型转换
泛型接口
java
// 定义泛型接口
public interface Comparable<T> {public int compareTo(T o);
}// 实现泛型接口
public class Person implements Comparable<Person> {private int age;@Overridepublic int compareTo(Person other) {return Integer.compare(this.age, other.age);}
}
泛型方法
java
// 定义泛型方法
public static <T> T getMiddle(T... a) {return a[a.length / 2];
}// 使用泛型方法
String middleString = getMiddle("A", "B", "C");
Integer middleInteger = getMiddle(1, 2, 3);
通配符
泛型通配符用于处理泛型类型的继承关系,提供了更灵活的类型匹配。
? extends T
:上界通配符,表示类型必须是 T 或其子类。? super T
:下界通配符,表示类型必须是 T 或其父类。?
:无界通配符,表示任意类型。
java
// 上界通配符
public static double sumOfList(List<? extends Number> list) {double sum = 0.0;for (Number n : list) {sum += n.doubleValue();}return sum;
}// 下界通配符
public static void addNumbers(List<? super Integer> list) {for (int i = 1; i <= 10; i++) {list.add(i);}
}
泛型擦除
Java 的泛型是通过类型擦除(Type Erasure)实现的,这意味着:
- 泛型信息在编译后被擦除,只保留原始类型(Raw Type)。
- 泛型类型参数不能是基本类型,必须是引用类型。
- 运行时无法获取泛型的实际类型参数。
java
// 编译后的字节码中,泛型类型被擦除
List<Integer> list = new ArrayList<>();
// 擦除后等价于
List list = new ArrayList();
泛型的限制
- 不能实例化泛型类型参数:
T obj = new T(); // 错误
- 不能使用基本类型作为泛型类型参数:
List<int> list; // 错误
- 不能创建泛型数组:
T[] array = new T[10]; // 错误
- 不能在静态上下文中使用泛型类型参数:
static T value; // 错误
- 不能捕获泛型类型的异常:
catch (T e) { } // 错误
最佳实践
- 明确指定泛型类型:避免使用原始类型(Raw Type)。
- 使用有意义的类型参数名称:如
T
(Type)、K
(Key)、V
(Value)等。 - 合理使用通配符:根据需要使用上界或下界通配符。
- 优先使用泛型方法:当泛型只在某个方法中使用时。
泛型的优势
- 类型安全:在编译时捕获类型错误,避免运行时异常。
- 代码复用:编写通用的算法和数据结构。
- 可读性增强:明确表达代码可以处理的类型。
- 更好的 API 设计:提供清晰的类型约束。
泛型是 Java 中非常强大的特性,它使得代码更加安全、灵活和可维护。理解泛型的工作原理和限制,能够帮助你更好地设计和使用 Java API。
=========================================================================
这其实是上课试图做一点点笔记呢,嗯,然后这个JAVA我不行了,我不能说我不行了。其实我行的,我行的,我行的,我行的......
3 Arrays.toString方法
Arrays.toString
是 Java 中 java.util.Arrays
类的一个静态方法,用于将数组转换为字符串表示形式。以下是一些编写或使用它的提示:
1. 方法的基本用途
这个方法的主要目的是将数组的元素用逗号分隔,并包裹在方括号 []
中,形成一个字符串。例如,对于一个整数数组 [1, 2, 3]
,它会返回 "[1, 2, 3]"
。
2. 导入必要的包
由于 Arrays
类位于 java.util
包中,你需要在 Java 文件的开头导入这个包。
java
import java.util.Arrays;
3. 方法调用
要使用 Arrays.toString
方法,你需要传递一个数组作为参数。以下是一个简单的示例框架:
java
// 声明并初始化一个数组
type[] array = {element1, element2, ...};// 调用 Arrays.toString 方法
String result = Arrays.toString(array);// 打印结果
System.out.println(result);
在上面的代码中,type
是数组的元素类型,element1
, element2
, ... 是数组的元素。
4. 不同类型的数组
Arrays.toString
方法可以处理各种基本数据类型的数组(如 int[]
, double[]
, char[]
等)和对象数组(如 String[]
)。对于不同类型的数组,使用方法是一样的,只是数组的声明和初始化可能会有所不同。
5. 注意事项
- 这个方法只适用于一维数组。如果你有多维数组,需要使用
Arrays.deepToString
方法。 - 对于对象数组,
toString
方法会调用每个元素的toString
方法来获取元素的字符串表示形式。
---------------------------------------------------------------------------------------------------------------------------------我现在特别困啊,今天,现在是8点,今天又快过去了我什么也不会什么也没干,打起精神来!!!打起精神来,今天起码还有时间,能学一点是一点打起精神来!!!
4 java.lang包里面的异常应该怎么使用输出语句,可以重写toString吗?
在 Java 里,java.lang
包中的异常类在输出异常信息时,有多种方式,一般不建议重写toString
方法,下面为你详细介绍:
1. 直接使用toString
方法
Throwable
类(所有异常类的父类)已经实现了toString
方法,它会返回包含异常类名和详细信息的字符串。所以,你可以直接调用异常对象的toString
方法来输出异常信息。
java
package PTA_training.Test3_5;import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] arrays = new int[n];for (int i = 0; i < arrays.length; i++) {while (true) {try {arrays[i] = scanner.nextInt();break;} catch (Exception e) {// 直接使用 toString 方法输出异常信息System.out.println(e.toString()); scanner.nextLine(); }}}System.out.println(Arrays.toString(arrays));scanner.close();}
}
2. 使用getMessage
方法
getMessage
方法会返回异常的详细描述信息,不包含异常类名。如果你只想要具体的错误信息,可以使用此方法。
java
package PTA_training.Test3_5;import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] arrays = new int[n];for (int i = 0; i < arrays.length; i++) {while (true) {try {arrays[i] = scanner.nextInt();break;} catch (Exception e) {// 输出异常类名和详细信息System.out.println(e.getClass().getName() + ": " + e.getMessage()); scanner.nextLine(); }}}System.out.println(Arrays.toString(arrays));scanner.close();}
}
3. 使用printStackTrace
方法
printStackTrace
方法会将异常的堆栈信息打印到标准错误输出流,对于调试来说很有帮助,它能显示异常发生的完整调用链。
java
package PTA_training.Test3_5;import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] arrays = new int[n];for (int i = 0; i < arrays.length; i++) {while (true) {try {arrays[i] = scanner.nextInt();break;} catch (Exception e) {// 打印异常堆栈信息e.printStackTrace(); scanner.nextLine(); }}}System.out.println(Arrays.toString(arrays));scanner.close();}
}
关于重写toString
方法~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
通常不建议重写java.lang
包中异常类的toString
方法,因为这些类是 Java 标准库的一部分,重写可能会影响其他依赖默认实现的代码。如果你有特殊需求,需要自定义异常信息格式,建议创建自定义异常类,在自定义异常类中重写toString
方法。
java
class CustomNumberFormatException extends NumberFormatException {public CustomNumberFormatException(String s) {super(s);}@Overridepublic String toString() {return "Custom: " + super.toString();}
}
然后在捕获异常时使用自定义异常:
java
try {// 可能抛出异常的代码
} catch (NumberFormatException e) {CustomNumberFormatException customEx = new CustomNumberFormatException(e.getMessage());System.out.println(customEx.toString());
}
综上所述,你可以根据具体需求选择合适的输出异常信息的方式。
5 对比一下,感受不足
我写的错误百出的代码
package PTA_training.Test3_5;import java.util.Arrays;
import java.util.Scanner;/*
7-5 jmu-Java-06异常-02-使用异常机制处理异常输入
使用异常处理输入机制,让程序变得更健壮。
main方法:
输入n,创建大小为n的int数组。
输入n个整数,放入数组。输入时,有可能输入的是非整型字符串,这时候需要输出异常信息,然后重新输入。
使用Arrays.toString输出数组中的内容。
输入样例:
5
1
2
a
b
4
5
3输出样例:
java.lang.NumberFormatException: For input string: "a"
java.lang.NumberFormatException: For input string: "b"
[1, 2, 4, 5, 3]*/
public class Main {public static void main(String[] args) {Scanner scanner =new Scanner(System.in);int n = scanner.nextInt();int [] arrays = new int [n];try {for (int i = 0; i < arrays.length; i++) {arrays[i] = scanner.nextInt();}} catch (Exception e) {throw new NumberFormatException(e.toString());}System.out.println(Arrays.toString(arrays));scanner.close();}
}
ai给的改正的优化的代码:
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 读取数组大小int n = scanner.nextInt();scanner.nextLine(); // 消耗换行符// 创建数组int[] array = new int[n];// 循环读取n个整数for (int i = 0; i < n; i++) {boolean validInput = false;while (!validInput) {try {// 读取输入String input = scanner.nextLine();// 尝试转换为整数array[i] = Integer.parseInt(input);validInput = true;} catch (NumberFormatException e) {// 捕获并打印异常信息System.out.println(e);}}}// 输出数组内容System.out.println(Arrays.toString(array));scanner.close();}
}
这个题目对我来说有一点点复杂了,我不知道怎么做了。。
我存在的问题有:
while (true)
循环的使用
- 问题:
while (true)
循环的位置和使用方式可能不符合预期。在当前代码中,它会导致一些逻辑混乱,因为循环内部的break
语句会在第一次成功读取一个整数后就跳出内层的for
循环,而不是处理整个数组的输入。 - 提示:需要重新考虑
while (true)
循环的位置,确保它能够在遇到异常时重新读取输入,直到整个数组都被正确填充。
try-catch
块的位置
- 问题:
try-catch
块放在for
循环内部,并且在捕获异常后直接抛出新的NumberFormatException
,这会导致程序在遇到异常时终止,而不是继续尝试读取输入。 - 提示:可以将
try-catch
块放在for
循环内部,但在捕获异常后,应该输出异常信息并跳过当前的输入,继续尝试读取下一个有效的整数。
finally
块的使用
- 问题:
finally
块中输出数组内容,这会导致在每次尝试读取输入时都会输出数组内容,而不是在数组完全填充后输出。 - 提示:将输出数组内容的代码移到数组完全填充后,即在
for
循环结束后。
scanner.close()
的位置
- 问题:
scanner.close()
语句在finally
块之前,这会导致在捕获异常后,scanner
已经关闭,后续无法继续读取输入。 - 提示:将
scanner.close()
语句移到数组完全填充后,确保在读取完所有输入后再关闭scanner
。
3. 异常处理提示
- 捕获异常时,应该捕获
InputMismatchException
而不是通用的Exception
,因为输入非整数时会抛出InputMismatchException
。 - 在捕获异常后,需要使用
scanner.nextLine()
方法清除输入缓冲区中的无效输入,以便继续读取下一个输入。