1、Java异常
定义:
Java异常是Java提供的用于处理程序中错误的一种机制。
所谓错误是指程序在运行的过程中发生的一些异常操作(如除0导致的溢出、数组下标越界、所要读取的文件不存在等)。
异常的分类
Error:是程序中无法处理的错误,表示运行应用程序中出现了严重的错误。此类错误一般表示代码运行时JVM出现问题。通常有Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。这种错误我们人为无法处理,交给JVM去处理就好。
Exception:所有异常类的父类,其子类对应了各种可能出现的异常事件,一般需要用户显式的声明或捕捉
CheckedException:这种错误必须由人为捕捉并处理。
RuntimeException:其产生比较频繁,如果显式的声明或捕捉将会对程序可读性和运行效率产生较大影响。因此由系统自动检测并把他们交给缺省的异常处理程序。(用户可不必对其进行处理)
下面举两个RuntimeException的例子:
public class Main {
public static void main(String args[]) {
System.out.println(1/0);
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:3)
Process finished with exit code 1
//这个是除0溢出异常
public class Main {
public static void main(String args[]) {
int a[] = new int[4];
System.out.println(a[5]);
}
}
//这个是数组下标越界异常
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at Main.main(Main.java:4)
有一些异常是我们必须捕捉的:
import java.io.*;
public class Main {
public static void main(String args[]) {
FileInputStream in = null;
try {
in = new FileInputStream("EnglishWord.txt");
int b;
b = in.read();
while(b != -1) {
System.out.println(b);
}
}catch (FileNotFoundException fe) {
fe.printStackTrace();
}catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
java.io.FileNotFoundException: EnglishWord.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at Main.main(Main.java:7)
异常捕获与处理的书写格式:
public class Main {
public static void main(String args[]) {
try {
//可能会抛出异常的代码
} catch (someException1 e) {
} catch (someException2 e) {
} finally {
}
}
}
与异常有关的五个关键字:
try关键字:
Try后面的程序执行会被监视,一旦发现异常立即停止执行,并跳转到catch;如果未发现异常则跳转到finally。
catch关键字:
一个try后面可以跟随多个catch。catch方法的参数为异常类对象,这个对象会在异常发生时自动生成。
因为Exception是所有异常类的父类,所以当第一个catch语句定义成Exception类型时,所有的异常将会直接执行该catch而不会执行下面其他的catch语句,即便其他catch中的异常类型与当前类型一致,因此当定义了Exception的catch语句又定义了其他的异常类型时,Exception的catch语句最好放在最后面,即:捕获更广泛的异常要放在捕获更确切的异常之后。
finally关键字:
finally段的代码无论是否出现异常都会执行。finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态做出统一的管理。
无论try所指定的程序块是否抛出异常,finally所指定的代码都要被执行。
通常在finally语句中可以进行资源的清除工作,如:关闭打开的文件、删除临时的文件等。
throws关键字:
throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
语法:(修饰符)(返回值类型) (方法名) ([参数列表]) [throws (异常类)] {…}
throw关键字:
作用:
1、可以在指定的方法中用throw关键字抛出指定的异常
2、在写方法过程中,首先使用throw关键字对传进来的参数进行检验。如果参数不合法,需要抛出异常并描述原因。
格式: throw new XXXException(“异常原因”)
注意:
1.throw关键字必须写在方法内部
2.throw后面new的对象必须是Exception或者是Exception的子类
3.throw关键字抛出异常对象可能我们需要对其进行处理。当throw创建的对象是RuntimeException或者是他的子类,我们可以不处理,交给JVM中断程序;否则我们则需要处理,使用try catch或者throws
import javax.imageio.IIOException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.MalformedParameterizedTypeException;
public class Main {
public static void main(String args[]) {
Test t1 = new Test();
try {
t1.f1();
} catch (Exception e) {
e.printStackTrace();
}
try {
t1.f2();
} catch (FileNotFoundException fe) {
fe.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
class Test {
public static void f1() {//如果方法内抛出的异常为RuntimeException异常,则这里可以不用声明throws
int a[] = new int[3];
int i = 4;
if(i>2) {
throw new ArrayIndexOutOfBoundsException();//抛出可能发生的异常
}
else {
System.out.println(a[4]);
}
}
//如果方法内抛出的异常不是RuntimeException异常,则必须声明throws
public static void f2() throws FileNotFoundException,IOException {
FileInputStream in = new FileInputStream("file123.txt");
int c;
c = in.read();
while (c == -1) {
System.out.println(c);
c = in.read();
}
}
}
java.lang.ArrayIndexOutOfBoundsException
at Test.f1(Main.java:31)
at Main.main(Main.java:11)
java.io.FileNotFoundException: file123.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at Test.f2(Main.java:40)
at Main.main(Main.java:17)
Process finished with exit code 0
import javax.imageio.IIOException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.MalformedParameterizedTypeException;
public class Main {
public static void main(String args[]) {
Test t1 = new Test();
try {
t1.f3();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Test {
public static void f1() {
int a[] = new int[3];
int i = 4;
if(i>2) {
throw new ArrayIndexOutOfBoundsException();
}
else {
System.out.println(a[4]);
}
}
//如果一个方法调用了抛出异常的方法,那么这个方法可以不用try catch对其处理,而是继续向上抛出异常
public static void f2() throws ArrayIndexOutOfBoundsException {
f1();
}
public static void f3() throws ArrayIndexOutOfBoundsException {
f2();
}
}
自定义异常
步骤:
1、通过继承java.lang.Exception类声明自己的异常类
2、在方法适当的位置生成自定义异常类的实例,并用throw语句抛出
3、在方法声明部分用throws语句声明该方法可能抛出的异常
public class Main {
public static void main(String args[]) {
people p = new people();
try {
p.set(-1,3);
} catch (MyException e) {
e.printStackTrace();
e.getId();
}
}
}
class people {
int age;
int height;
public void set(int age,int height) throws MyException{//这里必须声明可能抛出的异常
this.age = age;
this.height = height;
if(age<0) {
throw new MyException("年龄不能小于零",3);
}
}
}
class MyException extends Exception {
private int id;
public MyException(String s,int n) {
super(s);
id = n;
}
public void getId() {
System.out.println(id);
}
}
注意:
重写方法需要抛出和原方法所抛出的异常类型一致的异常或者不抛出异常。
2、Java常用类
- java.lang.Math
public class Main {
public static void main(String args[]) {
double i[] = new double[11];
i[0] = Math.abs(-1);//获取绝对值函数
i[2] = Math.acos(2.5);//反余弦
i[3] = Math.asin(1);//反正弦
i[4] = Math.log(10);//对数
i[5] = Math.log10(20);//对数
i[6] = Math.random();//获取随机数.
i[7] = Math.round(2.4);//四舍五入(获得整形值)
i[8] = Math.floor(2.1);//得到小于该数的最大整数
i[9] = Math.ceil(3.9);//得到大于该数的最小整数
i[10] = Math.sqrt(16);//开平方
for(double j:i) {
System.out.println(j);
}
}
}
//result:
1.0
0.0
NaN
1.5707963267948966
2.302585092994046
1.3010299956639813
0.15603577085297138
2.0
2.0
4.0
4.0
- java.lang.String
import java.util.Locale;
public class Main {
public static void main(String args[]) {
String s = new String("people");
System.out.println(s.startsWith("p"));//字符串是否由指定字符开头.
System.out.println(s.endsWith("m"));//字符串是否由指定字符结尾.
System.out.println(s.indexOf("op"));//返回子串在父串中第一次出现的下标(从左起)
System.out.println(s.isEmpty());//判断是否为空串
System.out.println(s.toUpperCase());//将小写字母变为大写
System.out.println(s.toLowerCase());//将大写字母变为小写
System.out.println(s.length());//输出字符串长度
System.out.println(s.replace(s,"boy"));//用新字符串内容,替换父串中原有的字符串内容.
System.out.println(s.matches("people"));//验证字符
System.out.println(s.compareTo("java"));//判断字符串大小
System.out.println(s.contains("poe"));//判断是否包含某个串或字符
}
}
//result
true
false
2
false
PEOPLE
people
6
boy
true
6
false
- java.util.Calendar
- java.util.Date
import java.util.Calendar;
import java.util.Date;
public class Main {
public static void main(String args[]) {
Date d = new Date();
System.out.println(d.getTime());//返回1970年至今的毫秒数
System.out.println(d.toString());//直接返回当前时间
/**没有构造器,因为Calendar类是abstract的,无法通过new实例
只能通过getInstance()方法获取实例,或者通过Calendar 的子类 GregorianCalendar 获取实例
*/
Calendar c = Calendar.getInstance();
System.out.println(c.getTime());//直接返回当前时间
c.setTime(d);//设置日历
}
}
- java.util.Arrays
import java.util.Arrays;
import java.util.Random;
public class Main {
public static void main(String args[]) {
int a[][] = new int[3][10];
Arrays.fill(a[0],2);//数组a的第0行元素全都赋值2
Arrays.fill(a[1],3,7,9);//数组a的第1行元素下标为3到6的都赋值为9
int b[] = {1,8,4,2,5,3,0,4,9,0};
Arrays.sort(b);//给所有数按升序排序
int c[] = {9,8,7,6,5,4,3,2,1};
Arrays.sort(c,2,6);//给第3位(下标2开始)到第6位排序
int []arr1 = {1,2,3};
int []arr2 = {1,2,3};
System.out.println(Arrays.equals(arr1,arr2));//比较数组元素是否相等
int []arr = {10,20,30,40,50};
System.out.println(Arrays.binarySearch(arr, 20));//二分查找法找指定元素的索引值(下标)
}
}
- java.util.Radom
import java.util.Random;
public class Main {
public static void main(String args[]) {
Random r = new Random();//构建一个新的随机数生成器
int a = r.nextInt(10);//返回一个 0 ~ 9之间的随机数
}
}
- java.lang.Object
import java.util.Random;
public class Main {
public static void main(String args[]) {
Dog d1 = new Dog();
Dog d2 = new Dog();
d1.toString();//返回描述该对象值的字符串。在自定义类中应覆盖这个方法
d1.equals(d2);//比较两个对象是否相等。在自定义类中应覆盖这个方法
d1.hashCode();//返回对象的散列码
d1.getClass();//返回包含对象信息的类对象
}
}
class Dog {
}
3、Java容器
概念:
容器可以管理对象的生命周期、对象与对象之间的依赖关系,你可以使用一个配置文件(通常是XML),在上面定义好对象的名称、如何产生(Prototype 方式或Singleton 方式)、哪个对象产生之后必须设定成为某个对象的属性等。在启动容器之后,所有的对象都可以直接取用,不用编写任何一行程序代码来产生对象,或是建立对象与对象之间的依赖关系。
换个更直白点的说明方式:容器是一个Java 所编写的程序,原先必须自行编写程序以管理对象关系,现在容器都会自动帮你做好。
包含:
Java容器类包含List、ArrayList、Vector及Map、HashTable、HashMap。
ArrayList和HashMap是异步的,Vector和HashTable是同步的,所以Vector和HashTable是线程安全的,而 ArrayList和HashMap并不是线程安全的。因为同步需要花费机器时间,所以Vector和HashTable的执行效率要低于 ArrayList和HashMap。
常用方法:
boolean add(Object obj):向容器中添加指定的元素
Iterator iterator():返回能够遍历当前集合中所有元素的迭代器
Object[] toArray():返回包含此容器中所有元素的数组。
Object get(int index):获取下标为index的那个元素
Object remove(int index):删除下标为index的那个元素
Object set(int index,Object element):将下标为index的那个元素置为element
Object add(int index,Object element):在下标为index的位置添加一个对象element
Object put(Object key,Object value):向容器中添加指定的元素
Object get(Object key):获取关键字为key的那个对象
int size():返回容器中的元素数
整体框架:
下面我们来分别介绍这几个
1、List
(LinkedList)
LinkedList采用双向链表实现的列表,因此可以被用作队列、堆栈、双端队列;顺序访问高效,随机访问性能较差、适用于需要经常添加和删除的数据。
LinkedList不支持同步
(ArrayList)
特点:
ArrayList是采用数组实现的列表,因此它支持随机访问,不适合频繁删除和插入操作。对于需要经常进行查询的数据建议采用此结构。
ArrayList与java数组的一个大的区别是ArrayList能够自动扩容
ArrayList不支持同步
(注:Vector用法和ArrayList用法很相似,它们的区别在于Vector是线程同步的而且Vector有另外的遍历方式。)
2、Set
(1)HashSet
基于散列函数的集和,采用HashMap实现,可以容纳null元素,不支持同步(可以通过Collections.synchronizedSet(new HashSet<…>()来使它同步)
(2)HashLinkedSet
继承HashSet ,基于散列函数和双向链表的集和,可以容纳null元素,通过双向链表维护了插入顺序,从而支持排序,但不支持同步(可以通过Collections.synchronizedSet(new HashSet<…>()来使它同步)
(3)TreeSet
基于树结构的集和,印次支持排序,不能容纳null元素,同样不支持同步
3、Map
(1)Hashtable
key和value都不能为空,HashTable是线程安全的、同步的,但只适合用于小数据量
(2)HashMap
HashMap允许有null,不支持同步(支持通过Collections.synchronizedMap(new Map<…,…>() 实现同步),所以线程不安全。但可以存储大量数据
(3)LinkedHashMap
基于双向链表用于维持插入顺序的HashMap,继承自HashMap
(4)TreeMap
基于红黑树的Map,可以根据key的自然排序或者compareTo方法排序输出
(5)Properties
继承自Hashtable。特有的方法有load()、store()等等。