error和exception
Error类和Exception类都继承自Throwable类。
- Error的继承关系:
java.lang.Object java.lang.Throwable
java.lang.Error
- Exception的继承关系:
java.lang.Objectjava.lang.Throwable
java.lang.Exception
二者的不同之处:
Exception:
1.可以是可被控制(checked) 或不可控制的(unchecked)
unchecked:NullPointerException、ClassCastException和IndexOutOfBoundsException都是RuntimeException的子类,RuntimeException及其所有的子集通常都是unchecked的。
2.表示一个由程序员导致的错误
3.应该在应用程序级被处理
Error:
1.总是不可控制的(unchecked)
2.经常用来用于表示系统错误或低层资源的错误
3.如何可能的话,应该在系统级被捕捉
Java 中定义了两类异常:
1) Checked exception: 这类异常都是Exception的子类 。异常的向上抛出机制进行处理,假如子类可能产生A异常,那么在父类中也必须throws A异常。可能导致的问题:代码效率低,耦合度过高。
2) Unchecked exception:
这类异常都是RuntimeException的子类,虽然RuntimeException同样也是Exception的子类,但是它们是非凡的,它们
不能通过client code来试图解决,所以称为Unchecked exception 。
Java 中异常类的继承关系图:
- 什么是unchecked异常?
即RuntimeException(运行时异常)
不需要try...catch...或throws
机制去处理的异常
- 列举最常用的五种RuntimeException:
这是JAVA认证考试中最常见的题目,事实上,runtime exception中最常见的,经常碰到的,也就5,6种,如下:
ArithmeticException | int a=0; int b= 3/a; |
ClassCastException: | Object x = new Integer(0); System.out.println((String)x); |
IndexOutOfBoundsException ArrayIndexOutOfBoundsException, StringIndexOutOfBoundsException |
int [] numbers = { 1, 2, 3 }; int sum = numbers[3]; |
IllegalArgumentException NumberFormatException |
int a = Interger.parseInt("test"); |
NullPointerExceptionextends |
- 除了RuntimeException,其他继承自java.lang.Exception得异常统称为Checked Exception,他们有多少种呢?
下面是JDK API中列出的异常类:
除了RuntimeException以外的,都是checked
Exception
java.lang.Object
java.lang.Throwable java.lang.Exception 所有已实现的接口: Serializable 直接已知子类: AclNotFoundException, ActivationException, AlreadyBoundException, ApplicationException, AWTException, BackingStoreException, BadAttributeValueExpException, BadBinaryOpValueExpException, BadLocationException, BadStringOperationException, BrokenBarrierException, CertificateException, ClassNotFoundException, CloneNotSupportedException, DataFormatException, DatatypeConfigurationException, DestroyFailedException, ExecutionException, ExpandVetoException, FontFormatException, GeneralSecurityException, GSSException, IllegalAccessException, IllegalClassFormatException, InstantiationException, InterruptedException, IntrospectionException, InvalidApplicationException, InvalidMidiDataException, InvalidPreferencesFormatException, InvalidTargetObjectTypeException, InvocationTargetException, IOException, JAXBException, JMException, KeySelectorException, LastOwnerException, LineUnavailableException, MarshalException, MidiUnavailableException, MimeTypeParseException, MimeTypeParseException, NamingException, NoninvertibleTransformException, NoSuchFieldException, NoSuchMethodException, NotBoundException, NotOwnerException, ParseException, ParserConfigurationException, PrinterException, PrintException, PrivilegedActionException, PropertyVetoException, RefreshFailedException, RemarshalException, RuntimeException, SAXException, ScriptException, ServerNotActiveException, SOAPException, SQLException, TimeoutException, TooManyListenersException, TransformerException, TransformException, UnmodifiableClassException, UnsupportedAudioFileException, UnsupportedCallbackException, UnsupportedFlavorException, UnsupportedLookAndFeelException, URIReferenceException, URISyntaxException, UserException, XAException, XMLParseException, XMLSignatureException, XMLStreamException, XPathException |
算术异常类:ArithmeticExecption
空指针异常类:NullPointerException
类型强制转换异常:ClassCastException
数组负下标异常:NegativeArrayException
数组下标越界异常:ArrayIndexOutOfBoundsException
违背安全原则异常:SecturityException
文件已结束异常:EOFException
文件未找到异常:FileNotFoundException
字符串转换为数字异常:NumberFormatException
操作数据库异常:SQLException
输入输出异常:IOException
方法未找到异常:NoSuchMethodException
java.lang.AbstractMethodError
抽象方法错误。当应用试图调用抽象方法时抛出。
java.lang.AssertionError
断言错。用来指示一个断言失败的情况。
java.lang.ClassCircularityError
类循环依赖错误。在初始化一个类时,若检测到类之间循环依赖则抛出该异常。
java.lang.ClassFormatError
类格式错误。当Java虚拟机试图从一个文件中读取Java类,而检测到该文件的内容不符合类的有效格式时抛出。
java.lang.Error
错误。是所有错误的基类,用于标识严重的程序运行问题。这些问题通常描述一些不应被应用程序捕获的反常情况。
java.lang.ExceptionInInitializerError
初始化程序错误。当执行一个类的静态初始化程序的过程中,发生了异常时抛出。静态初始化程序是指直接包含于类中的static语句段。
java.lang.IllegalAccessError
违法访问错误。当一个应用试图访问、修改某个类的域(Field)或者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。
java.lang.IncompatibleClassChangeError
不兼容的类变化错误。当正在执行的方法所依赖的类定义发生了不兼容的改变时,抛出该异常。一般在修改了应用中的某些类的声明定义而没有对整个应用重新编译而直接运行的情况下,容易引发该错误。
java.lang.InstantiationError
实例化错误。当一个应用试图通过Java的new操作符构造一个抽象类或者接口时抛出该异常.
java.lang.InternalError
内部错误。用于指示Java虚拟机发生了内部错误。
java.lang.LinkageError
链接错误。该错误及其所有子类指示某个类依赖于另外一些类,在该类编译之后,被依赖的类改变了其类定义而没有重新编译所有的类,进而引发错误的情况。
java.lang.NoClassDefFoundError
未找到类定义错误。当Java虚拟机或者类装载器试图实例化某个类,而找不到该类的定义时抛出该错误。
java.lang.NoSuchFieldError
域不存在错误。当应用试图访问或者修改某类的某个域,而该类的定义中没有该域的定义时抛出该错误。
java.lang.NoSuchMethodError
方法不存在错误。当应用试图调用某类的某个方法,而该类的定义中没有该方法的定义时抛出该错误。
java.lang.OutOfMemoryError
内存不足错误。当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误。
java.lang.StackOverflowError
堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出时抛出该错误。
java.lang.ThreadDeath
线程结束。当调用Thread类的stop方法时抛出该错误,用于指示线程结束。
java.lang.UnknownError
未知错误。用于指示Java虚拟机发生了未知严重错误的情况。
java.lang.UnsatisfiedLinkError
未满足的链接错误。当Java虚拟机未找到某个类的声明为native方法的本机语言定义时抛出。
java.lang.UnsupportedClassVersionError
不支持的类版本错误。当Java虚拟机试图从读取某个类文件,但是发现该文件的主、次版本号不被当前Java虚拟机支持的时候,抛出该错误。
java.lang.VerifyError
验证错误。当验证器检测到某个类文件中存在内部不兼容或者安全问题时抛出该错误。
java.lang.VirtualMachineError
虚拟机错误。用于指示虚拟机被破坏或者继续执行操作所需的资源不足的情况。
java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
java.lang.ArrayStoreException
数组存储异常。当向数组中存放非数组声明类型对象时抛出。
java.lang.ClassCastException
类造型异常。假设有类A和B(A不是B的父类或子类),O是A的实例,那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常。
java.lang.ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
java.lang.CloneNotSupportedException
不支持克隆异常。当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出该异常。
java.lang.EnumConstantNotPresentException
枚举常量不存在异常。当应用试图通过名称和枚举类型访问一个枚举对象,但该枚举对象并不包含常量时,抛出该异常。
java.lang.Exception
根异常。用以描述应用程序希望捕获的情况。
java.lang.IllegalAccessException
违法的访问异常。当应用试图通过反射方式创建某个类的实例、访问该类属性、调用该类方法,而当时又无法访问类的、属性的、方法的或构造方法的定义时抛出该异常。
java.lang.IllegalMonitorStateException
违法的监控状态异常。当某个线程试图等待一个自己并不拥有的对象(O)的监控器或者通知其他线程等待该对象(O)的监控器时,抛出该异常。
java.lang.IllegalStateException
违法的状态异常。当在Java环境和应用尚未处于某个方法的合法调用状态,而调用了该方法时,抛出该异常。
java.lang.IllegalThreadStateException
违法的线程状态异常。当县城尚未处于某个方法的合法调用状态,而调用了该方法时,抛出异常。
java.lang.IndexOutOfBoundsException
索引越界异常。当访问某个序列的索引值小于0或大于等于序列大小时,抛出该异常。
java.lang.InstantiationException
实例化异常。当试图通过newInstance()方法创建某个类的实例,而该类是一个抽象类或接口时,抛出该异常。
java.lang.InterruptedException
被中止异常。当某个线程处于长时间的等待、休眠或其他暂停状态,而此时其他的线程通过Thread的interrupt方法终止该线程时抛出该异常。
java.lang.NegativeArraySizeException
数组大小为负值异常。当使用负数大小值创建数组时抛出该异常。
java.lang.NoSuchFieldException
属性不存在异常。当访问某个类的不存在的属性时抛出该异常。
java.lang.NoSuchMethodException
方法不存在异常。当访问某个类的不存在的方法时抛出该异常。
java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。
java.lang.NumberFormatException
数字格式异常。当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。
java.lang.RuntimeException
运行时异常。是所有Java虚拟机正常操作期间可以被抛出的异常的父类。
java.lang.SecurityException
安全异常。由安全管理器抛出,用于指示违反安全情况的异常。
java.lang.StringIndexOutOfBoundsException
字符串索引越界异常。当使用索引值访问某个字符串中的字符,而该索引值小于0或大于等于序列大小时,抛出该异常。
java.lang.TypeNotPresentException
类型不存在异常。
1,“简要的叙述error和exception”)。就像Mary Campione的“The Java Tutorial”中所写的:“exception就是在程序执行中所发生的中断了正常指令流的事件(An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions.)。”依照美国传统辞典(American Heritage Dictionary)所解释的,error就是:“效果或情况背离了可接受的一般法则(The act or an instance of deviating from an accepted code of behavior.)”
背离(deviation)、中断(disruption),有什么区别呢?让我们来这样想:如果你驱车在公路上行驶时有人拦住了你,这就叫做“中断”。如果车根本就无法发动,那就叫做“背离”。
这与Java有什么关系呢?很多。Java中有一个相当有趣的error和exception的结构。
是的,非常正确:所有使用try{} catch(Exception e){}的代码块只能找到你一半的错误。但是,是否try并catch Throwable取决于你捕捉它的原因。快速的看一下Error的子类,它们的名字类似VirtualMachineError,ThreadDeath,LinkageError。当你想捕获这些家伙们的时候,你要确定你需要捕获它们。因为那些都是很严重的错误。
但是ClassCastException是一个error吗?不完全是。ClassCastException或任何类型的exception只是虚拟机(VM,VirtualMachine)让你知道有问题发生的方式,这说明,开发者产生了一个错误,现在有一个机会去修正它。
另一方面,error是虚拟机的问题(通常是这样,但也可能是操作系统的问题)。引用Java文档中关于error的说明:“Error是Throwable的子类,它的出现说明出现了严重的问题。一般应用程序除非有理由,否则不应该捕捉Error。通常这是非常反常的情况。”
所以,error非常强大,而且但处理它远比一般开发者想象的要难(当然不是你)。如果你在做一项很简单的工作的话,你认为有必要去处理error?
首先,记住,error跟exception抛出的方式大体相同的,只有一点不同。就是一个抛出error的方法不需要对此进行声明(换句话说,这是一个unchecked exception(也被称做Runtime Exception))。
public void myFirstMethod() throws Exception
//Since it's an exception, I have to declare
//it in the throws clause {
throw new Exception();
}
public void mySecondMethod()
//Because errors aren't supposed to occur, you
//don't have to declare them.
{
throw new Error();
}
注意,有一些exception是不可控制的(unchecked exception),跟error的表现是一样的,如:NullPointerException,ClassCastException和IndexOutOfBoundsException,它们都是RuntimeException的子类。RuntimeException和其子类都是unchecked excception。
那应该如何处理这些令人讨厌的unchecked exception呢?你可以在可能出现问题的地方catch它们,但这只是一个不完整的解决方法。这样虽然解决了一个问题,但其余的代码仍可能被其他unchecked exception所中断。这里有一个更好的办法,感谢ThreadGroup类提供了这个很棒的方法:
public class ApplicationLoader extends ThreadGroup
{
private ApplicationLoader()
{
super("ApplicationLoader");
}
public static void main(String[] args)
{
Runnable appStarter = new Runnable()
{
public void run()
{
//invoke your application
(i.e. MySystem.main(args)
}
}
new Thread(new ApplicationLoader(), appStarter).start();
}
//We overload this method from our parent
//ThreadGroup , which will make sure that it
//gets called when it needs to be. This is
//where the magic occurs.
public void uncaughtException(Thread thread, Throwable exception)
{
//Handle the error/exception.
//Typical operations might be displaying a
//useful dialog, writing to an event log, etc.
}
这个技巧太棒了。想想这种情况,你对你的GUI程序进行了修改,然后一个unchecked exception被抛出了。并且你的GUI程序常常具有了错误的状态(对话框仍旧开着,按钮失效了,光标状态出现错误)。但是,使用这个技巧,你可以将你的GUI程序恢复原始状态并通知用户出现了错误。对自己感觉很棒吧,因为你写了一个高质量的应用程序。
这个技巧并不只适用于GUI程序。服务器端应用程序可以使用这个技巧来释放资源,防止虚拟机进入不稳定状态。较早的捕获错误并聪明的将其处理是好的程序员和普通程序员的区别之一。你已经明白了这些,我知道你想成为哪一类程序员。
关于作者
Josh Street是Bank of America的构架设计师。他主要负责电子商务平台的开发。他的联系方式是rjstreet@computer.org。
附1
简要的叙述error和exception
Error和Exception都继承自Throwable,他们下列不同处:
Exceptions
1.可以是 可被控制(checked) 或 不可控制的(unchecked)
2.表示一个由程序员导致的错误
3.应该在应用程序级被处理
Errors
1.总是 不可控制的(unchecked)
2.经常用来用于表示系统错误或低层资源的错误
3.如何可能的话,应该在系统级被捕捉