中的自定义异常怎么实现出来(自定义异常必须使用什么语句引发)

湘潭网餐饮知识
132

湘潭网小编为大家带来以下内容:

这篇文章主要介绍“Java中的自定义异常怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java中的自定义异常怎么实现”文章能帮助大家解决问题。Java中的异常

Java中默认的异常信息有哪些呢?Java程序中捕获异常之后会将异常进行输出,不知道细心的同学有没有注意到一点,输出的异常是什么东西呢?下面来看一个常见的ArithmeticException异常:

java.lang.ArithmeticException: / by zero    at greenhouse.ExceptionTest.testException(ExceptionTest.java:16)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)    at java.lang.reflect.Method.invoke(Method.java:597)    at org.junit.runners.model.frameworkMethod$1.runReflectiveCall(frameworkMethod.java:44)    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)    at org.junit.runners.model.frameworkMethod.invokeExplosively(frameworkMethod.java:41)    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

再看看一个Java程序员耳熟能详的NullPointerException空指针异常:

java.lang.NullPointerException    at greenhouse.ExceptionTest.testException(ExceptionTest.java:16)    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)    at java.lang.reflect.Method.invoke(Method.java:597)    at org.junit.runners.model.frameworkMethod$1.runReflectiveCall(frameworkMethod.java:44)    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)    at org.junit.runners.model.frameworkMethod.invokeExplosively(frameworkMethod.java:41)    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

大家有没有发现一个特点,就是异常的输出中能够精确的输出异常出现的地点,精确到每一行代码,还有后面一大堆的执行过程类调用,也都打印出来了,这些信息从哪儿来呢?

这些信息是从栈中获取的,在打印异常日志的时候,会从JVM 栈中去获取这些调用信息。能够精确的定位异常出现的异常当然是好,但是我们有时候考虑到程序的性能,以及一些需求时,我们有时候并不需要完全的打印这些信息,并且去方法调用栈中获取相应的信息,是有性能消耗的,对于一些性能要求高的程序,我们完全可以在异常处理方面为程序性能做一个性能提升。

自定义Java异常类

所以如何避免输出这些堆栈信息呢? 那么自定义异常就可以解决这个问题:

首先,自定义异常需要继承RuntimeException,然后,再通过是重写fillInStackTrace,toString 方法,例如下面我定义一个AppException异常:

package com.green.monitor.common.exception;import java.text.MessageFormat;public class AppException extends RuntimeException {private boolean isSuccess = false;private String key;private String info;public AppException(String key) {super(key);this.key = key;this.info = key;}public AppException(String key, String message) {super(MessageFormat.format("{0}[{1}]", key, message));this.key = key;this.info = message;}public AppException(String message, String key, String info) {super(message);this.key = key;this.info = info;}public boolean isSuccess() {return isSuccess;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}@Overridepublic Throwable fillInStackTrace() {return this;}@Overridepublic String toString() {return MessageFormat.format("{0}[{1}]",this.key,this.info);}}Java异常源码

那么为什么要重写fillInStackTrace,和 toString 方法呢? 我们首先来看源码是怎么一回事。

public class RuntimeException extends Exception {    static final long serialVersionUID = -7034897190745766939L;        public RuntimeException() {      super();    }        public RuntimeException(String message) {        super(message);    }        public RuntimeException(String message, Throwable cause) {        super(message, cause);    }        public RuntimeException(Throwable cause) {        super(cause);    }}

RuntimeException是继承Exception,但是它里面只是调用了父类的方法,本身是没有做什么其余的操作。那么继续看Exception里面是怎么回事。

public class Exception extends Throwable {    static final long serialVersionUID = -3387516993124229948L;        public Exception() {    super();    }        public Exception(String message) {    super(message);    }        public Exception(String message, Throwable cause) {        super(message, cause);    }        public Exception(Throwable cause) {        super(cause);    }}

从源码中可以看到,Exception里面也是直接调用了父类的方法,和RuntimeException一样,自己其实并没有做什么。那么直接来看Throwable里面是怎么一回事:

public class Throwable implements Serializable {  public Throwable(String message) {        fillInStackTrace();        detailMessage = message;    }             public synchronized native Throwable fillInStackTrace();               public StackTraceElement[] getStackTrace() {        return (StackTraceElement[]) getOurStackTrace().clone();    }    private synchronized StackTraceElement[] getOurStackTrace() {        // Initialize stack trace if this is the first call to this method        if (stackTrace == null) {            int depth = getStackTraceDepth();            stackTrace = new StackTraceElement[depth];            for (int i=0; i < depth; i++)                stackTrace[i] = getStackTraceElement(i);        }        return stackTrace;    }            native int getStackTraceDepth();        native StackTraceElement getStackTraceElement(int index);            public String toString() {        String s = getClass().getName();        String message = getLocalizedMessage();        return (message != null) ? (s + ": " + message) : s;    }

从源码中可以看到,到Throwable就几乎到头了,在fillInStackTrace() 方法是一个native方法,这方法也就是会调用底层的C语言,返回一个Throwable对象,toString 方法,返回的是throwable的简短描述信息,并且在getStackTrace 方法和 getOurStackTrace 中调用的都是native方法getStackTraceElement,而这个方法是返回指定的栈元素信息,所以这个过程肯定是消耗性能的,那么我们自定义异常中的重写toString方法和fillInStackTrace方法就可以不从栈中去获取异常信息,直接输出,这样对系统和程序来说,相对就没有那么"重",是一个优化性能的非常好的办法。

按照上面我们举例的自定义AppException异常,如果出现异常了,这个AppException异常输出是什么样的信息呢?请看下面吧:

@Test    public void testException(){        try {            String str =null;            System.out.println(str.charAt(0));        }catch (Exception e){            throw new AppException("000001","空指针异常");        }    }

执行上面单元测试,在异常异常的时候,系统将会打印我们自定义的异常信息:

000001[空指针异常]Process finished with exit code -1

关于“Java中的自定义异常怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注花开半夏行业资讯频道,小编每天都会为大家更新不同的知识点。

君子莲(www.junzilian.com)湖南省长沙、株洲、湘潭城市宣传信息网,提供房产,人才招聘,家居装饰,教育,论坛,旅游,特产,美食,天气,娱乐,企业等资讯。



最新餐饮知识

热门推荐

为你推荐