上帝视角学JAVA- 基础09-异常【2021-08-08】

1、异常

Exception 异常:程序执行中发送的不正常情况称为异常

你写错了,逻辑错了不是异常。

错误Error:JVM虚拟机无法解决的严重问题。

如jvm内部错误,资源不足等。Error一般不针对代码进行处理。

一般处理的是运行时异常以及编译时异常。

常见的有 空指针异常、文件不存在异常、网络异常、数组下标越界异常等

 

编译时异常就是从java文件到class文件时出现的异常

运行时异常就是class文件被jvm运行时的异常。

JAVA中定义的异常: 顶级类是 java.lang.Throwable 类

Throwable 有2个子类,一个是 Error 另一个是 Exception

img

1、 Error 错误

ErrorThrowable 的子类,用于指示合理的应用程序不应该试图捕获的严重问题。大多数这样的错误都是异常条件。虽然 ThreadDeath 错误是一个“正规”的条件,但它也是 Error 的子类,因为大多数应用程序都不应该试图捕获它。

在执行该方法期间,无需在其 throws 子句中声明可能抛出但是未能捕获的 Error 的任何子类,因为这些错误可能是再也不会发生的异常条件。

这段话是 java官方介绍翻译的中文。简单讲就是写代码时不用去管他它。

AnnotationFormatError, AssertionError, AWTError, CoderMalfunctionError, FactoryConfigurationError, FactoryConfigurationError, IOError, LinkageError, ServiceConfigurationError, ThreadDeath, TransformerFactoryConfigurationError, VirtualMachineError 
    这些都是Error的子类

2、Exception 异常

Exception 类及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。

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 
有这些已知子类。这里面分成2类,一类是编译时异常,另一类是运行时异常。运行时异常就一个: RuntimeException

这个 RuntimeException 是 Exception 的直接子类。不代表运行时异常只有1种。因为 RuntimeException 这个玩意也有很多子类。

AnnotationTypeMismatchException, ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, EnumConstantNotPresentException, EventException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IncompleteAnnotationException, IndexOutOfBoundsException, JMRuntimeException, LSException, MalformedParameterizedTypeException, MirroredTypeException, MirroredTypesException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NoSuchMechanismException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, RejectedExecutionException, SecurityException, SystemException, TypeConstraintException, TypeNotPresentException, UndeclaredThrowableException, UnknownAnnotationValueException, UnknownElementException, UnknownTypeException, UnmodifiableSetException, UnsupportedOperationException, WebServiceException 
    这些就是 RuntimeException 已知的直接子类。不用去记忆,知道就好。他们可是还有子类的。。。

1.1 异常处理

异常处理有2种,一种是捕获处理,另一种就是直接抛出去

1.1.1 try{} catch{} finally{}捕获异常

try的意思就是尝试,尝试运行的意思。将可能发送异常的代码放在try后面的大括号里面。

catch的意思就是捕获,当出现异常时,捕获异常进行操作。

finally最终的,就是说不管发不发生异常,都要干的事。

看一个例子:

class ExceptionDemo
{
    public static void main(String[] args) {
        try {
            // 可能会有异常的代码,放在try里面
            throw new Exception("My Exception");
            // catch 捕获异常,这里捕获的是 Exception 异常。用的是 Throwable的子类 Exception。也是异常的顶级类。接收异常
        } catch (Exception e) {
           // 输出一下 异常的消息  e.getMessage()
            System.err.println("getMessage():" + e.getMessage());
            System.err.println("getLocalizedMessage():" + e.getLocalizedMessage());
            System.err.println("toString():" + e);
            System.err.println("printStackTrace():");
            // 打印一下异常
            e.printStackTrace();
        }
    }
}

上面的代码没有使用finally,说明 finally 并不是必须的结构。当没有必须要做的事时,就可以不写finally。

catch 是可以写多个的。里面的形参可以是任意异常类。上面直接捕获了最大的异常类,就无需写多个catch。

写具体的异常的好处是可以针对具体某一个异常进行处理。但是会比较繁琐,而且如果没有考虑完全,出现了没有写完全的异常,就会捕获不到而出错。

写大类的好处是所有异常都能捕获。但是不能针对某一个具体的异常进行事先处理。怎么用看实际情况。开发中都会用到。

try{
   // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}catch(异常类型3 异常的变量名3){
  // 程序代码
}
 
try {
    file = new FileInputStream(fileName);
    x = (byte) file.read();
} catch(FileNotFoundException f) { // Not valid!
    f.printStackTrace();
    return -1;
} catch(IOException i) {
    i.printStackTrace();
    return -1;
}

至于 finally 如果需要不管是否有异常都要执行,就写在这里面。在文件操作中,对流的关闭用的很多。

像 数据库连接、输入输出流、网络编程Socket等资源 JVM是不能自动回收的,需要我们手动释放。可以放在finally里面

public class ExcepTest{
  public static void main(String args[]){
    int a[] = new int[2];
    try{
       System.out.println("Access element three :" + a[3]);
    }catch(ArrayIndexOutOfBoundsException e){
       System.out.println("Exception thrown  :" + e);
    }
    finally{
       // 不管是否异常,都会执行的代码
       a[0] = 6;
       System.out.println("First element value: " +a[0]);
       System.out.println("The finally statement is executed");
    }
  }
}
  • 在 try/catch 后面添加 finally 块并非强制性要求的。

  • catch 不能独立于 try 存在,try 代码后不能既没 catch 块也没 finally 块。即try catch可以,try finally也可以。但是只有try 或者只有catch 不可以。

  • try, catch, finally 块之间不能添加任何代码。

1.1.2 throws 抛出去

抛出去就是不去管它。让我编译通过。你尽管执行就是了。

不处理的后果就是如果真的发送异常,java程序就会在异常发生处终止。后面的代码就不会再执行。

如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。

import java.io.*;
public class className{
   public void withdraw(double amount) throws RemoteException,
                              InsufficientFundsException{
       // Method implementation
   }
   //Remainder of class definition
}

上面的代码用 throws 抛出了异常,而且抛出了2个异常,用逗号隔开了。

什么时候用这个?

一般运行时异常不用try catch finally 进行处理,而是直接抛出去。针对 编译时异常才会进行 try catch finally

  • 在子类重写父类方法的情况下,子类重写方法抛出的异常要不大于父类中抛出的异常。

  • try catch 是真正处理异常,而throws 是将异常丢给调用方

1.2 手动抛异常

可以手动抛出异常

用 throw 关键字 抛出一个异常对象。

这个手动抛出的关键字 没有s,是throw

异常声明在方法后面是 throws 注意区别。

有些时候我们会自动手动去抛出异常。配合下面讲的自定义异常。

什么时候会需要手动抛出呢?

在不符合业务逻辑时,但是是符合java语法规范时。就需要手动抛出。

比如,我们需要接收1个txt文件,而接收了一个png文件。程序是不会报错的。但是不符合我们的要求,可以抛出一个自定义异常,提示文件类型错误。我们抛的一般都是运行时异常,编译时不会报错。无需处理。因为是运行时,某个操作不符合逻辑,而不是编译时就有错误。当然,直接抛出运行时异常也是没问题的。抛出自定义异常是为了异常好追溯,方便处理。

1.3 自定义异常

  • 所有异常都必须是 Throwable 的子类。

  • 如果希望写一个检查性异常类,则需要继承 Exception 类。

  • 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。

但是,我们一般都是自定义 RuntimeException 的子类。

  • 通常还需要编写几个重载的构造器。

  • 自定义异常需要提供serialVersionUID

  • 自定义异常的名字很关键,一般是根据业务确定。

public class MyException extends RuntimeException{
    // 这个 serialVersionUID 随便写一个 long型的数字。有什么用后面再讲
    public static long serialVersionUID = -12312412L;
    
    public MyException(){
        
    }
    // 重载的构造器
    public MyException(String msg){
        super(msg);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值