(1)什么是异常
当出现程序无法控制的外部环境问题(用户提供的文件不存在,文件内容损坏,网络不可用...)时,JAVA就会用异常对象来描述。
JAVA中用2种方法处理异常:
1.在发生异常的地方直接处理;
2.将异常抛给调用者,让调用者处理。
JAVA异常可分为3种:
A,检查性异常:java.lang.Exception.检查性异常------程序正确,但因为外在的环境条件不满足引发。例如:用户错误及I/O问题----程序试图打开一个并不存在的远程Socket端口。这不是程序本身的逻辑错误,而很可能是远程机器名字错误(用户拼写错误)。JAVA编译器强制要求处理这类异常,如果不捕获这类异常,程序将不能被编译。
B,运行期异常:java.lang.RuntimeException.运行期异常------这意味着程序存在bug,如数组越界,0被除,入参不满足规范.....这类异常需要更改程序来避免,JAVA编译器强制要求处理这类异常。
C,错误:java.lang.Error.错误------它可能源于程序的bug,但一般更可能源于环境问题,如内存耗尽。错误在程序中无须处理,而由运行环境处理。
顶层是java.lang.Throwable类,检查性异常,运行期异常,错误都是这个类的子孙类。java.lang.Exception和java.lang.Error继承自java.lang.Throwable,而java.lang.RuntimeException继承自java.lang.Exception
(2)如何处理异常?
A,try...catch 。程序运行产生异常时,将从异常发生点中断程序并向外抛出异常信息。
说明:ArithmeticException和ArrayIndexOutOfBoundsException都属运行期异常(java.lang.RuntimeException),如果不用try...catch捕获,程序也是可通过编译的;但如果属于检查性异常(java.lang.Exception),必须而且一定要用try...catch...对其进行处理才能编译。
int x = (int)(Math.random()*5);
int y = (int)(Math.random()*10);
int [] z =new int[5];
try
{
System.out.println("y/x="+(y/x));
System.out.println("y="+y+"z[y]="+z[y]);
}
catch (ArithmeticException exc1)
{
System.out.println("算术运算异常:"+exc1.getMessage());
}
catch (ArrayIndexOutOfBoundsException exc2)
{
System.out.println("数据越界异常:"+exc2.getMessage());
}
B,finally。如果把finally块置try...catch...语句后,finally块一般都会得到执行,它相当于一个万能的保险,即使前面的try块发生异常,而又没有对应异常的catch块,finally块将马上执行。
以下情形,finally块将不会被执行:
(1)finally块中发生了异常;
(2)程序所在线程死亡;
(3)在前面的代码中用了System.exit();
(4)关闭CPU。
C,抛出异常,即throws的使用。
package draw;
import java.util.Scanner;
public class Sub{
public static void main(String[] agrs ){
try {
divide(); //2.我们在mian方法中调用下面抛出异常的方法,这个时候我们用try-catch语句进行处理
} catch (Exception e) {
System.out.println("除数不能为零");
e.printStackTrace(); ///3.这个方法的意思打印出异常信息
}
}
public static void divide() throws Exception{//1.这里我们就抛出了一个Exception的异常,把这个申明为static是为了不用创建对象就可以调用它。
Scanner input = new Scanner(System.in);
System.out.println("请输入被除数:");
int num = input.nextInt();
System.out.println("请输入除数:");
int num2 = input.nextInt();
System.out.println("num除以num2的商是:"+num/num2);
}
}
以上就是一个抛出异常--调用方法的时候捕获异常的一般过程。如果我们在上面的例子中不希望在调用方法时候用try-catch来捕获异常,我们可以把异常交给调用他的main方法,进行再次抛出。新的代码示例如下:
package draw;
import java.util.Scanner;
public class Sub{
public static void main(String[] agrs ) throws Exception{ //这里我们对异常进行再次抛出,此例子中,我们交给了java虚拟机进行处理,如果是一个普通的方法,就有两种选择一是再次抛出,二是try-catch进行处理,异常抛到最后必须进行处理。平时遇到我们一般不像例子这样写,一般在遇到main方法的时候,就用try-catch处理就完了
divide();
}
public static void divide() throws Exception{
Scanner input = new Scanner(System.in);
System.out.println("请输入被除数:");
int num = input.nextInt();
System.out.println("请输入除数:");
int num2 = input.nextInt();
System.out.println("num除以num2的商是:"+num/num2);
}
}
Exception是所有可捕获异常类的父类,我在捕获的时候不想捕获它下面的其他的异常,我们只想捕获其中的一个或者几个这个时候我们怎么办呢?请看写法:
public static void divide()throws ArithmeticException,InputMismatchException{代码块}中间用逗号隔开,可以使用Thows关键字指定多种抛出的异常。
(3)多个异常的处理规则:
定义多个catch可精确地定位异常。如果为子类的异常定义了特殊的catch块,而父类的异常则放在另外一个catch块中,此时,必须满足以下规则:子类异常的处理块必须在父类异常处理块的前面,否则会发生编译错误。所以,越特殊的异常越在前面处理,越普遍的异常越在后面处理。这类似于制订防火墙的规则次序:较特殊的规则在前,较普通的规则在后。
自己也可以定义并抛出异常,方法是2步:创建异常,抛出异常(首先实例化一个异常对象,然后用throw抛出)。将创建异常、抛出异常合在一起的好处是:创建异常时,会包含异常创建处的行信息,异常被捕获时可以通过堆栈迹(stack Trace)的形式报告这些信息。如果在同一行代码创建和抛出异常,对于程序的调试将非常有用。所以,throw new XXX()已经成为一个标准的异常抛出范式。如下:
public String getString(int id) throws NotFoundException {
CharSequence res = getText(id);
if (res != null) {
return res.toString();
}
throw new NotFoundException("String resource ID #0x"
+ Integer.toHexString(id));
}
=====================================================================================================
在执行JAVA IO的时候,常常需要把各种类型的数据转成byte[]的格式;在对端接收到报文以后,又要进行相反的过程,将byte[]转换成相应的数据类型。需要了解下byteValue。Integer类的byteValue()方法怎样使用?该方法的作用是以byte类型返回该 Integer 的值。只取低八位的值,高位不要,byteValue()其实和(byte)int效果是一样的。
(1)long类型转成byte数组
public static byte[] longToByte(long number) {
long temp = number;
byte[] b = new byte[8];
for (int i = 0; i < b.length; i++) {
b[i] = new Long(temp & 0xff).byteValue();
temp = temp >> 8; // 向右移8位
}
return b;
}
//byte数组转成long
public static long byteToLong(byte[] b) {
long s = 0;
long s0 = b[0] & 0xff;// 最低位
long s1 = b[1] & 0xff;
long s2 = b[2] & 0xff;
long s3 = b[3] & 0xff;
long s4 = b[4] & 0xff;// 最低位
long s5 = b[5] & 0xff;
long s6 = b[6] & 0xff;
long s7 = b[7] & 0xff;
// s0不变
s1 <<= 8;
s2 <<= 16;
s3 <<= 24;
s4 <<= 8 * 4;
s5 <<= 8 * 5;
s6 <<= 8 * 6;
s7 <<= 8 * 7;
s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
return s;
}
(2)int类型转成byte数组
public static byte[] intToByte(int number) {
int temp = number;
byte[] b = new byte[4];
for (int i = 0; i < b.length; i++) {
b[i] = new Integer(temp & 0xff).byteValue();// 将最低位保存在最低位
temp = temp >> 8; // 向右移8位
}
return b;
}
byte数组转成int类型
public static int byteToInt(byte[] b) {
int s = 0;
int s0 = b[0] & 0xff;// 最低位
int s1 = b[1] & 0xff;
int s2 = b[2] & 0xff;
int s3 = b[3] & 0xff;
s3 <<= 24;
s2 <<= 16;
s1 <<= 8;
s = s0 | s1 | s2 | s3;
return s;
}
(3)short类型转成byte数组
public static byte[] shortToByte(short number) {
int temp = number;
byte[] b = new byte[2];
for (int i = 0; i < b.length; i++) {
b[i] = new Integer(temp & 0xff).byteValue();
temp = temp >> 8; // 向右移8位
}
return b;
}
byte数组转成short类型
public static short byteToShort(byte[] b) {
short s = 0;
short s0 = (short) (b[0] & 0xff);// 最低位
short s1 = (short) (b[1] & 0xff);
s1 <<= 8;
s = (short) (s0 | s1);
return s;
}