异常处理

当我们程序出现问题时,在java中,我们使用异常机制进行错误处理;

模式:1.在方法中,抛出异常,(在方法后面加 throws Exception)

          2. 在调用时,捕获异常;(用 try ... catch ... 来捕获异常)

抛出异常:在检测到错误发生时,抛出异常对象

int  str( String  s) throws Exception
                {
                   if (  错误1发生 )
                       throw  new Exception("错误1");
                   if(  错误2发生 )
                       throw  new Exception("错误2");
                  }

捕获异常:  

try{

         可能抛出异常的代码1

         可能抛出异常的代码2

               ..........

        }catch(Exception e){
         进行异常处理

     }



例子我们写一个把字符串转成数字的程序,就可能出现以下情况:

1.字符串可能含有字母;

2.用int保存数字,数字太大就会出现越界;

下面,我们通过写这个程序,以及处理异常情况来了解java的异常处理机制。

情况一:我们用 if...else 来处理以上情况。

/******Converter.java******/
package my;
public class Converter
{
	public int status = 0; 
	public int str2int (String str)
	{
		status = 0;
		if(str.length()>11) 
		{
			status = -2; // 第2种情况
			return 0;
		}		
		int result = 0;
		for(int i=0; i<str.length(); i++)
		{
			char ch = str.charAt(i);
			if( ! isValid(ch) )
			{
				status = -1; // 第1种情况
				return 0;
			}
			result = result * 10 + (ch - '0'); 			
		}
		return result;
	}	
	private boolean isValid(char ch)
	{
		if(ch >= '0' && ch <= '9')return true;
		if(ch == '-') return true;
		return false;
	}
}

在main函数中调用:

/*****Test.java*****/
package my;
public class Test
{
	public static void main(String[] args)
	{
		Converter conv = new Converter();
		int result = conv.str2int("201k8");
		if(conv.status == 0)
		{
			System.out.println("转换结果: " + result);			
		}
		else
		{
			if(conv.status == -1)
				System.out.println("非法字符");	
			else if(conv.status == -2)
				System.out.println("超出范围");	
		}		
	}
}



可以看出,用if...else也可以处理错误,但是非常繁琐,而且情况多的时候处理起来非常麻烦。

情况二:添加try...catch

把Converter.java改写如下

/******Converter.java******/
package my;
public class Converter
{	
	public int str2int (String str) throws Exception
	{
		if(str.length()>11)
		{
			Exception ex = new Exception("超出范围");//抛出异常
			throw ex;
		}		
		int result = 0;
		for(int i=0; i<str.length(); i++)
		{
			char ch = str.charAt(i);
			if( ! isValid(ch) )
				throw new Exception("非法字符");	//抛出异常
			result = result * 10 + (ch - '0'); 			
		}
		return result;
	}	
	private boolean isValid(char ch)
	{
		if(ch >= '0' && ch <= '9')return true;
		if(ch == '-') return true;
		return false;
	}
}

把Test.java改写如下

/********Test.java***********/
package my;
public class Test
{
	public static void main(String[] args)
	{
		Converter conv = new Converter();
		try {
			int result = conv.str2int("201k8");
			System.out.println("正常:" + result);
		}
		catch( Exception e)
		{
			System.out.println(e.getMessage());
		}		
		System.out.println("exit");
	}

}

在Converter.java中抛出异常,在调用时如果try中的代码有错误,就会在catch中捕获到。

自定义异常

现在,我们想更精确的处理错误,想知道错误的具体原因:

若是“非法字符”异常,需要知道哪个字符输入错误了;若是“长度超限”异常,需要知道输入了多少个字符。

可以通过自定义异常解决

try ... catch  ... catch ... 可以匹配不同类型的异常
try {  }
catch ( AException e1) {   }
catch ( BException  e2) {   }
catch ( Exception ex)    {   }     // 肯定匹配

1 自定义异常:用于携带出错时的具体信息
2 按类型捕获:对不同的异常类型做不同的处理

添加两个文件   InvalidCharException.java 和  TooLargeException.java 来处理“非法字符”和“长度超限”

/******InvalidCharException.java*******/
package my;
public class InvalidCharException extends Exception
{
	public int pos;  // 非法字符出现的位置
	public char ch;  // 非法字符	
	public InvalidCharException(int pos, char ch)
	{		
		this.pos = pos;
		this.ch = ch;
	}
	@Override
	public String getMessage()
	{
		return "非法字符'" + ch + "',位置:" + pos;
	}		
}
/******TooLargeException.java*************/
package my;
// 当字符串太长时,抛出此异常
public class TooLargeException extends Exception
{
	public int length; // 实际长度	
	public TooLargeException(int length)
	{
		this.length = length;
	}
	@Override
	public String getMessage()
	{
		return "字符串太长(" + length + ")";
	}		
}

把test.java 和 Converter.java 改写如下:

/******Converter.java*******/
package my;
public class Converter
{	
	public int str2int (String str) throws Exception
	{
		if(str.length()>11)
		{
			Exception ex = new TooLargeException(str.length());
			throw ex;
		}		
		int result = 0;
		for(int i=0; i<str.length(); i++)
		{
			char ch = str.charAt(i);
			if( ! isValid(ch) )
				throw new InvalidCharException(i, ch);			
			result = result * 10 + (ch - '0'); 			
		}
		return result;
	}	
	private boolean isValid(char ch)
	{
		if(ch >= '0' && ch <= '9')return true;
		if(ch == '-') return true;
		return false;
	}
}
/*********Test.java**************/
package my;
public class Test
{
	public static void main(String[] args)
	{
		Converter conv = new Converter();
		try {
			int result = conv.str2int("201k8");
			System.out.println("正常:" + result);
		}
		catch( InvalidCharException e1)
		{
			System.out.println(e1.getMessage());
		}
		catch ( TooLargeException e2)
		{
			System.out.println(e2.getMessage());
		}
		catch( Exception e)//若以上错误都不执行,就会执行这个
		{
			System.out.println(e.getMessage());
		}		
		System.out.println("exit");
	}
}

这时,我们在main方法中就可以通过catch不同类型的错误进行处理。