本小节主要介绍Java中有关异常、字符串和常见类的相关知识。
Error
和Exception
是两个继承于Throwable类
的最重要的类。Error类一般指的是‘系统错误’,比如:虚拟机错误、线程死锁、内存溢出等等;Exception类一般指的是‘编码、环境、用户操作输入出现问题’。RuntimeException类
和CheckException类
。RuntimeException类常被称为‘非检查异常’或‘运行时异常’,CheckException类常被称为‘检查异常’。IOException类(文件异常)
:如文件不存在;SQLException类(SQL异常)
:如数据库连接错误。NullPointerException类(空指针异常)
:如引用了一个空对象的属性或方法;ArrayIndexOutOfBoundsException类(数组下标越界异常)
:如数组访问越界;ClassCastException类(类型转换异常)
:如一个错误的类型转换;ArithmeticException类(算术异常)
:如用整数去整除0。String str = null;
System.out.println(str.length());
int[] ary={1,2,3};
for(int i = 0; i <= 3; i++){
System.out.println(ary[i]);
}
class Animal{
}
class Dog extends Animal{
}
class Cat extends Animal{
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Animal a1 = new Dog();
Animal a2 = new Cat();
Dog d1 = (Dog)a1;
Dog d2 = (Dog)a2;
}
}
int one = 12;
int two = 0;
System.out.println(one/two);
try{
// 一些会抛出异常的方法
// 抛出异常的方法会终止执行!
// 程序的控制权将被移交给catch块中的异常处理程序
}catch(Exception e){
// 处理该异常的代码块
// 可以发出一些警告提示信息或进行一些错误日志的记录等
}
// 多重catch块的语法
try{
// ...
}catch(Exception1 e){
// ...
}catch(Exception2 e){
// ...
}
// 利用finally语句块来进行一些最终要执行的代码或语句块
try{
// 一些会抛出异常的方法
}catch(Exception1 e){
// 处理Exception的代码块
}catch(Exception2 e){
// 处理Exception2的代码块
}finally{
// 最终将要执行的一些代码
}
使用多重语句块一定要注意顺序问题,即:先小后大,先子类后父类的顺序来编写多重语句块。
throw
和throws
public void 方法名(参数列表)throws 异常列表{
// 调用会抛出异常的方法或者:
throw new Exception();
}
· 自定义异常
class 自定义异常类 extends 异常类型{
}
// 例:
public class DrunkException extends Exception{
// 一个无参的构造器
public DrunkException(){
}
// 一个带有字符串类型参数的构造器
public DrunkException(String message){
// 调用父类(Exception)的构造器。
super(message);
}
}
// 例如:
public class ChainTest{
public static void main(String[] args){
ChainTest ct = new ChainTest();
try{
ct.test2();
}catch(Exception e){
e.printStackTrace();
}
}
public void test1() throws DrunkException{
throw new DrunkException(“喝酒别开车!”);
}
public void test2(){
try{
test1();
}catch(DrunkException e){
RuntimeException newExc = new RuntimeException(“行车不规范,亲人两行泪!!”);
newExc.initCause(e);
throw newExc;
}
}
}
String s1 = “Hello World”;
String s2 = “Hello World”;
String s3 = new String(“Hello World”);
String s4 = new String(“Hello World”);
// 多次出现的字符常量,Java编译程序只创建一个,所以返回true
System.out.println(s1 == s2);
// s1和s3是不同的对象,所以返回false
System.out.println(s1 == s3);
// s3和s4是不同的对象,所以返回false
System.out.println(s3 == s4);
s1 = s1 + "!!!";
// 字符串s1被修改,指向新的内存空间
System.out.println(s1);
StringBuffer
或者StringBuilder
。// 例如:
int i = 10; // 定义一个int基本类型值
Integer x = new Integer(i); // 手动装箱
Integer y = i; // 自动装箱
Integer j = new Integer(8); // 定义一个Integer包装类对象,值为8
int m = j.intValue(); // 手动拆箱为int类型
int n = j; // 自动拆箱为int类型
// 例如:
int c = 10;
String str1 = Integer.toString(c); // 方法一
String str2 = String.valutOf(c); // 方法二
String str3 = c + “”; // 方法三
· 将字符串转换为基本类型的两种方法:
1)调用包装类的parseXxx静态方法
2)调用包装类的valueOf()方法转换为基本类型的包装类,会自动拆箱。
// 例如:
String str = “8”;
int d = Integer.parseInt(str); // 方法一
int e = Integer.valueOf(str); // 方法二
Date d = new Date();
System.out.println(d);
使用Date类的默认无参构造方法创建出的对象就代表当前时间。
· java.text.SimpleDateFormat类:可以用来对日期时间进行格式化,如可以将日期转换为指定格式的文本,也可将文本转换为日期。
1)使用format()方法将日期转换为指定格式的文本。
2)使用parse()方法将文本转换为日期
Calendar c = Calendar.getInstance();
getTime()方法
,用来获取Date对象,完成Calendar和Date的转换,还可通过getTimeInMillis()方法
,获取此Calendar的时间值,以毫秒为单位。Math.round();
要求:
- 定义字符串数组保存图书信息
- 提示用户输入,分别按“书名”和“图书序号”查找图书
- 根据输入信息进行适当的异常处理
核心源码如下,对于核心代码块的解析已包含在程序中:
package com.borrow_book;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* 在主函数main()中对Test类进行实例化,并调用其借书的方法
*/
Test test = new Test();
test.borrow_book_test();
}
public void borrow_book_test(){
// 对对象数组book[5]本身分配内存空间
Book[] book = new Book[5];
/**
* 对数组元素进行初始化,否则程序会报错:
* Exception in thread "main" java.lang.NullPointerException
* at com.borrow_book.Test.init_book()
*/
for(int i = 0; i < book.length; i++){
book[i] = new Book();
}
book[0].setBook_id(1);
book[0].setBook_name("数据结构");
book[1].setBook_id(2);
book[1].setBook_name("高等数学");
book[2].setBook_id(3);
book[2].setBook_name("线性代数");
book[3].setBook_id(4);
book[3].setBook_name("概率论与数理统计");
book[4].setBook_id(5);
book[4].setBook_name("java语言教程");
// for(int i = 0; i < book.length; i++){
// System.out.println("编号为:" + book[i].getBook_id() + "的书名为:" + book[i].getBook_name());
// }
for(; ;){
/**
* 进行变量初始化
* 1."order"用于存储用户输入的命令(1或2)
* 2."book_name"用于存储用户输入的图书名称
* 3."book_id"用于存储用户输入的图书序号
* 4."flag"为一个标志位,在下面遍历数据库中图书信息时需要用到
*/
int order = 0;
String book_name;
int book_id;
int flag = 1;
// 提示用户输入命令
System.out.println("输入命令:1-按照名称查找图书;2-按照序号查找图书");
// 实例化Scanner对象,用于接收用户的输入信息
Scanner input = new Scanner(System.in);
/**
* 通过使用try-catch语句检测用户的输入是否错误
* 如果用户输入错误,则抛出RuntimeException异常
* 要特别说明的是:当用户输入的命令是数字,但并非数字1或数字2时,程序并不会自动抛出错误
* 因此,我们还需要另外使用一个if语句进行判断
*/
try{
order = input.nextInt();
}catch(RuntimeException e){
System.out.println("命令输入错误!请根据提示输入数字命令!");
continue;
}
if(order != 1 && order != 2){
System.out.println("命令输入错误!请输入数字1或数字2!");
}else{
if(order == 1){
System.out.println("输入图书名称:");
try{
book_name = input.next();
}catch(RuntimeException e){
System.out.println("您输入的信息不正确,请重新输入!");
continue;
}
/**
* 在这个for循环中的if语句判断中,需要加上一个标志位flag
* 当用户输入的图书名称信息与数据库中的某一条图书信息相匹配时,程序通过break语句跳出循环
* 此时不应该执行输出“图书不存在”语句。
* 而只有当for循环语句完成执行完毕都没有在数据库中匹配到书籍信息时才向控制台输出“图书不存在”语句。
* 因此需要在if语句中加上一个标志位来加以判断!
*/
for(int i = 0; i < book.length; i++){
// 这里是字符串的值之间的大小比较,因此不能用“==”,而应该用equals()
if(book[i].getBook_name().equals(book_name)){
System.out.println("数据库中尚有存书:" + book[i].getBook_name());
flag = 0;
break;
}
}
if(flag == 1){
System.out.println("图书不存在!");
}
}else{
System.out.println("输入图书序号:");
try{
book_id = input.nextInt();
}catch(RuntimeException e){
System.out.println("命令输入错误!请根据提示输入数字命令!");
continue;
}
if(book_id > 5){
System.out.println("图书不存在!");
}else{
for(int i = 0; i < book.length; i++){
if(book_id == book[i].getBook_id()){
System.out.println("数据库中尚有存书:" + book[i].getBook_name());
break;
}
}
}
}
}
}
}
}