throw/throws抛出异常
作用:可以在方法中手动抛出异常用throw,该方法也要在方法名后抛出异常用throws,但是该方法被调用的时候,调用该方法的方法同时也要抛出异常throws,也就是向上一层一层抛出。
格式:throw new Exception(“错误消息提示”);
public class Test {
public static void main(String[] args) throws Exception{
Person p1 = new Person();
p1.setAge(20);
System.out.println(p1.getAge());
Person p2 = new Person();
p2.setAge(-2);
System.out.println(p2.getAge());
System.out.println("==============");
}
}
class Person{
private int age;
void setAge(int a) throws Exception{
if(a>0&&a<130) {
this.age = a ;
}
else {
throw new Exception("年龄不合法!");
}
}
int getAge() {
return age;
}
}
运行结果:
20
Exception in thread "main" java.lang.Exception: 年龄不合法!
at com.ct.Test.Person.setAge(Test.java:31)
at com.ct.Test.Test.main(Test.java:16)
可以看到我们抛出的异常提示信息输出了。但是不会继续执行后边的代码。
注意:throw必须继续向上传递throws,交由上层处理,否则会报错。如果不用throws,就需要使用try catch块处理异常。
try...catch处理异常块
同样的题目要求,只是使用try catch 替换了throw和throws抛出异常。
public class Test {
public static void main(String[] args){
Person p1 = new Person();
p1.setAge(20);
System.out.println(p1.getAge());
Person p2 = new Person();
p2.setAge(-2);
System.out.println(p2.getAge());
System.out.println("==============");
}
}
class Person{
private int age;
void setAge(int a){
if(a>0&&a<130) {
this.age = a ;
}
else {
try {
throw new Exception("年龄不合法!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
int getAge() {
return age;
}
}
运行结果:
20
java.lang.Exception: 年龄不合法!
at com.ct.Test.Person.setAge(Test.java:32)
at com.ct.Test.Test.main(Test.java:16)
0
==============
可以看到跳过了异常并且继续执行下去输出后续内容,可以说实现了所谓的“解决”异常,而throwable中提供了三种显示异常的方式,分别是printstacktrace,输出堆栈跟踪信息,异常消息较多,和不用try..catch时的显示一致。
还可以使用getmessage()输出详细消息字符。
将上述代码的e.printStackTrace更改为system.out.println(e.getmessage());输出结果为
20
年龄不合法!
0
==============
只是简单的输出了我们throw抛出异常括号中的信息描述。
还有一种方式是直接使用tostring()方法输出信息。
system.out.println(e.getmessage())改成system.out.println(e.toString());
输出的结果如下:
20
java.lang.Exception: 年龄不合法!
0
==============
我自己的理解是使用了try..catch后,程序后边的代码还可以继续执行,但是如果只用throw/throws抛出异常的话不会继续执行后续的代码。。。
try catch块的使用中注意,如果try中出现了异常,那么try后边的代码不会继续执行,会直接跳转到catch块中执行。多个catch块要求子类异常在前,父类异常在后,或者只使用一个父类异常。
最后还有一个finally块。不可以单独使用,一般和try块一起使用,finally块在最后(不管有没有出现异常)一定会执行(除非JVM结束),一般用于释放资源使用。
如果try块中出现了return语句,但是会先去finally执行完才执行try块最后的return。在finally块中如果出现了对try块中返回值的操作。这并不会影响try块返回值。因为在执行finally之前就已经缓冲好了值,从finally回来后还是返回原来的值。
自定义异常类
实现自定义异常类型,必须继承exception或者runtimeexception;
既然是自定义异常类,那完全可以照猫画虎,看一下exception异常类是怎样书写的,有什么特点,那在我们的自定义异常类中仿照书写,加上我们自己的内容就可以了。
查看exception类部分内容如下:
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
/**
* Constructs a new exception with {@code null} as its detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*/
public Exception() {
super();
}
/**
* Constructs a new exception with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Exception(String message) {
super(message);
}
可以看到exception是继承了Throwable类的,第一行的serialVersionUID我暂时不知道有什么作用,听老师说是流传输的序列化啥啥啥。目前阶段自定义异常的时候是可以加可以不加的。
这段代码中其实也只看到了一个无参一个有参构造器,这符合我们一开始使用throw抛出异常时书写的throw new exception(“异常提示消息”);这行代码,那再继续追查看一下这个message究竟传到了哪里;
查看了throwable以后看到如下代码:
public Throwable() {
fillInStackTrace();
}
/**
* Constructs a new throwable with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* <p>The {@link #fillInStackTrace()} method is called to initialize
* the stack trace data in the newly created throwable.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
/**
在exception中的super(message)应该就是调用了父类throwable的一个参数的构造器。可以看到将message又传给了detailMessage,看到这个名字大概明白,应该是详细信息的意思。那继续再看这个detailmessage在throwable中起到了什么作用,查找后发现代码如下:
/**
* Returns the detail message string of this throwable.
*
* @return the detail message string of this {@code Throwable} instance
* (which may be {@code null}).
*/
public String getMessage() {
return detailMessage;
}
这也就是上边说查看异常消息方法中的getMessage方法,他是throwable类中的一个方法,当然父类的方法子类一定继承可以调用,所以上边也用到了这个方法,最终可以知道我们自定义异常类中的有参构造器后边的内容是传到这里。
自定义异常类,检测年龄是否合法:代码如下
public class TestDefinition {
public static void main(String[] args) {
Student s1 = new Student();
s1.setAge(200);
System.out.println(s1.getAge());
}
}
class Student{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>0&&age<100) {
this.age = age;
System.out.println("年龄合法,操作成功!");
}
else {
try {
throw new NoageException("年龄数值不合法!!!");
} catch (NoageException e) {
System.out.println(e.getMessage());
}
}
}
class NoageException extends Exception{
/**
*
*/
private static final long serialVersionUID = -8149725010943027546L;
public NoageException() {
super();
}
public NoageException(String msg) {
super(msg);
}
}
运行结果:
年龄数值不合法!!!
0
其实这个异常类定义的我有点小尴尬,这和exception没啥区别。。。也是才疏学浅,期待着以后可以深入学习自定义异常类中可以扩展的内容!
个人见解,如有错误,还望指教;