前言
本小节主要介绍Java中有关异常、字符串和常见类的相关知识。
Java语言中的异常与异常处理
- 异常概念:阻止当前方法或作用域,称之为异常
- 异常处理的作用和意义:能够将异常提示给编程人员或用户,使得本来已经中断的程序以适当的方式运行或退出,并且能够保存用户的当前操作或者进行数据回滚,最后再把占用的资源释放掉。
- Java异常体系结果简介
· Throwable类:Java中所有的异常类都继承于它。Error
和Exception
是两个继承于Throwable类
的最重要的类。Error类一般指的是‘系统错误’,比如:虚拟机错误、线程死锁、内存溢出等等;Exception类一般指的是‘编码、环境、用户操作输入出现问题’。
· Exception类下去又可分为RuntimeException类
和CheckException类
。RuntimeException类常被称为‘非检查异常’或‘运行时异常’,CheckException类常被称为‘检查异常’。
· ‘运行时异常’会由Java虚拟机自动抛出,并自动捕获。而‘运行时异常’的出现,绝大部分情况下说明了代码本身有问题,应该从逻辑上改进代码;‘检查异常’需要手动添加捕获以及处理语句。
· CheckException类(检查异常)下面又可分为:IOException类(文件异常)
:如文件不存在;SQLException类(SQL异常)
:如数据库连接错误。
· RuntimeException类下面又可分为: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以及try-catch-finally来捕获异常
try{
// 一些会抛出异常的方法
// 抛出异常的方法会终止执行!
// 程序的控制权将被移交给catch块中的异常处理程序
}catch(Exception e){
// 处理该异常的代码块
// 可以发出一些警告提示信息或进行一些错误日志的记录等
}
// 多重catch块的语法
try{
// ...
}catch(Exception1 e){
// ...
}catch(Exception2 e){
// ...
}
// 利用finally语句块来进行一些最终要执行的代码或语句块
try{
// 一些会抛出异常的方法
}catch(Exception1 e){
// 处理Exception的代码块
}catch(Exception2 e){
// 处理Exception2的代码块
}finally{
// 最终将要执行的一些代码
}
使用多重语句块一定要注意顺序问题,即:先小后大,先子类后父类的顺序来编写多重语句块。
- Java中的异常抛出以及自定义异常
· 两个关键字:throw
和throws
throw:是一个动词,它写在方法体里面,它指的是具体的抛出异常这个动作;如果某个方法调用到了会抛出异常的方法,那么必须添加try…catch…语句去尝试捕获这种异常或者添加throws声明来将异常抛出给更上一层的调用者进行处理。
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;
}
}
}
Java中字符串部分的内容
- 简介:Java中字符串被作为String类型的对象处理。String类位于java.lang包中。默认情况下,该包被自动导入所有的程序。
- Java中字符串的不变性:String对象创建后则不能被修改,是不可变的,所谓的修改其实是创建了新的对象,所指向的内存空间不同。
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
。 - 每次new一个字符串就是创建一个新的对象,即便两个字符串的内容相同,使用“==”比较时也为“false”,如果只需比较内容是否相同,应使用“equals()方法”。即:“==”判断的是两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象;equals()比较存储在两个字符串对象中的内容是否一致。
- String类的常用方法:
· 字符串中字符的索引从0开始,范围为0到xx.length()-1
· 使用indexOf进行字符或者字符串查找时,如果匹配返回位置索引;如果没有匹配结果,返回-1。
· 使用substring(beginIndex, endIndex)进行字符串截取时,包括beginIndex位置的字符,不包括endIndex位置的字符。 - Java中的StringBuilder类、StringBuffer类和String类的区别:
· String类具有不可变性,当频繁操作字符串时,就会额外产生很多临时变量。而使用StringBuffer或StringBuilder就能避免这个问题。
· StringBuffer与StringBuilder基本相似,StringBuffer是线程安全的,而StringBuilder没有实现线程安全功能,性能略高。一般情况下,优先考虑使用StringBuilder类。 - StringBuilder类的常用方法:
Java中的常用类总结
- 包装类
· 为了让基本数据类型也具备对象的特性,Java为每个基本数据类型都提供了一个包装类,使得我们可以像操作对象那样来操作基本数据类型。
· 基本数据类型和包装类之间的对应关系:
· 包装类提供了两大类方法:
1)将本类型和其他基本类型进行转换的方法
2)将字符串和本类型及包装类互相转换的方法
· Integer包装类的构造方法:
· Integer包装类的常用方法:
- 基本类型与包类型之间的转换
· Java中的装箱操作:把基本类型转换成包装类,使其具有对象的性质,又可分为手动装箱和自动装箱。
· Java中的拆箱操作:把包装类对象转换成基本类型的值,又可分为手动拆箱和自动拆箱。
// 例如:
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类型
- 基本类型与字符串之间的转换
· 基本类型转换为字符串的三种方法:
1)使用包装类的toString()方法
2)使用String类的valueOf()方法
3)用一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串。
// 例如:
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和SimpleDateFormat类表示时间
· java.util.Date类:最主要的作用就是获取当前时间,如:
Date d = new Date();
System.out.println(d);
使用Date类的默认无参构造方法创建出的对象就代表当前时间。
· java.text.SimpleDateFormat类:可以用来对日期时间进行格式化,如可以将日期转换为指定格式的文本,也可将文本转换为日期。
1)使用format()方法将日期转换为指定格式的文本。
2)使用parse()方法将文本转换为日期
- Calendar类的应用
· java.util.Calendar类是一个抽象类,可以通过调用getInstance()静态方法获取一个Calendar对象,此对象已由当前日期时间初始化,即默认代表当前时间,如Calendar c = Calendar.getInstance();
· Calendar类提供了getTime()方法
,用来获取Date对象,完成Calendar和Date的转换,还可通过getTimeInMillis()方法
,获取此Calendar的时间值,以毫秒为单位。 - 使用Math类操作数据
· Math类位于java.lang包中,包含用于执行基本数学运算的方法,Math类的所有方法都是静态方法,所以使用该类中的方法时,可以直接使用类名.方法名,如: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;
}
}
}
}
}
}
}
}
输出结果如下图所示: