Java——异常的处理与内存的管理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_45613931/article/details/101772649


本人是个新手,写下博客用于自我复习、自我总结。
如有错误之处,请各位大佬指出。
参考教材:零基础学Java


1)异常的分类

异常就是可以预见的错误。JAVA中所有的异常都从Throwable类中继承,不过一般情况下,都会由Exception类派生出来。异常分为两个部分:一个部分是错误,另一部分是异常

对于错误来说,只能终止程序。
对于异常,又可以分为运行期异常非运行期异常。一个运行期异常是由程序员自身的错误造成的。例如,一个越界的数组访问。而这些异常被称为未检查异常,它们都不应该产生;除此之外,其他的都属于检查异常。

所以,这里主要讲述检查异常,因为这些异常编译器不能处理,通过抛出一个检查异常让异常处理器来处理,这样就可以顺利通过程序的编译。

检查异常可以分为很多种:
ArithmeticException——算术异常
NullPointerException——无空间对象异常
ArrayIndexOutOfBoundsException——数组越界异常
NegativeArraySizeException——数组长度为负值异常
ArrayStoreException——数组存储异常
IllegalArgumentException——非法参数异常
SecurityException——安全性异常
因为它们的父类都是Exception类,所以可以使用Exception来代替所
有的异常。

2)

①异常的声明:

异常的声明就是声明一个异常类,在声明之后将其抛出。

格式:方法名 throws Exception
{方法体}

②异常的抛出:

所谓异常的抛出,就是将异常抛给异常处理器,暂时不去处理它。(上述声明就也是一种异常的抛出)

格式:方法名 throws Exception
{ 方法体 throw Exception
方法体
}

③异常的捕获:

为了让异常处理器能够处理异常,可以对异常进行捕获。

同时也只有捕获了异常,在程序具体运行时才不会再出现异常报错。

语法结构:try
{可能会出现异常的程序段}
catch(Exception e)
{捕获异常后,如何处理它}

④执行finally子句:

在程序发生异常时,在try区块内发生异常的代码之后的程序段将不能继续执行,从而跳转到catch子句执行异常处理,但假如此时try区块内已经执行的代码建立了网络链接,而catch子句又没有有效关闭该链接,显然将浪费系统的资源如缓存、端口号等。所以无论try区块是否抛出异常,都希望执行关闭数据库链接的操作,此时可以使用finally子句执行所有异常处理函数之后的动作。

语法结构:try
{可能会出现异常的程序段}
catch(1)
{捕获1异常后,处理它}
catch(2)
{捕获2异常后,处理它}
catch(3)
{捕获3异常后,处理它}
finally
{无论是否有异常都会执行的操作}

也就是说,finally子句的存在很有必要。直观地说,在建立了网络链接,打开数据库,打开一个磁盘文件等后的清理工作就需要finally子句。因为在建立网络连接的过程中会发生难以预料的异常类型,无论是哪个catch子句处理触发的异常,都需要断开网络连接,释放连接资源。另外如果抛出无法被捕捉的异常,这样该异常就会一直向外层传播,直到操作系统,显然此时所谓的清理工作就无法获得执行。如果没有finally子句该问题会变得很繁琐且很不安全。若该问题拥有finally子句,那么无论发生什么事,finally子句的内容一定会被执行,那么把清理工作放在统一地点(finally子句内)就保证了这个清理工作一定会被执行。

将以上所有知识点总结在一个例题上:

 import java.io.*;
 public class file1
 {
     public static double quotient(int numerator,int denominator)throws DivideByZeroException  //抛出异常
     {
         if(denominator==0)  //当参数denominator为0时
         throw new DivideByZeroException(); //创建异常对象DivideByZeroException
         else
         return (double)numerator/denominator; //返回变量numerator
     }
     public static void main(String args[]) //主方法
     {
         try        //捕获异常
         {
             double result=quotient(3,0); //调用方法quotient()
         }
         catch(DivideByZeroException exception)
         {
             System.out.println(exception.toString());
         }
     }
     public static class DivideByZeroException extends ArithmeticException
     {
         public DivideByZeroException()
         {
             super("不能被0除");
         }
     }
 }
 运行效果:file1$DivideByZeroException:不能被0

3)自定义异常

在具体设计类的时候,偶尔也需要产生异常,让其他程序员在使用时能按照规定来使用。用户自定义异常可通过扩展Exception类来实现。这种异常类可以包含一个“普通类”所包含的任何东西。

例:

public class file2
{   //抛出异常对象ServerTimedOutException
    public static void main(String args[])throws ServerTimedOutException
    {
        try
        {   //抛出异常对象
            throw new ServerTimedOutException("Could not connect",80);
        }catch(ServerTimedOutException e)
        {   //处理异常
            System.out.println("异常信息是:"+e.toString());
        }
    }
}
class ServerTimedOutException extends Exception
{
    private String reason;
    private int port;
    public ServerTimedOutException(String reason,int port)
    {
        this.reason=reason;
        this.port=port;
    }
    public String getReason()
    {
        return reason;
    }
    public String getPort()
    {
        return port;
    }
}
运行效果: 异常信息是:ServerTimedOutException

4)运行期异常

运行期异常是不需要用户“关心”的异常,Java会自动执行此类异常检查工作,出现运行期异常由系统自动抛出,也就是说RuntimeException是唯一可以省略的异常。所有运行期异常都继承自RuntimeException异常类,在编写程序时,不必考虑此类异常,所有函数都默认自己可能抛出RuntimeException,系统会自动探测、捕获并处理运行期异常。

5)内存的管理和回收

在JAVA中无需担心如何销毁对象,即JAVA会自动进行垃圾回收。而垃圾回收是一个比较复杂的过程,当程序运行时会自动检查整个内存,检查内存中哪些对象引用不再被使用。一旦检查出来后,便会安全删除这些
对象同时回收这些对象所占用的系统资源。但是这种机制可能会影响应用程序代码的运行,即如果在执行应用程序代码的过程中,执行垃圾回收,则应用程序代码的执行时间可能延长,这会导致程序运行的延迟。由于不知道何时会进行垃圾回收,因此延迟的时间也是不可预知的。但是在实时应用程序中对时间的要求肯定会非常严格,即它们必须在确定的、已知的延迟条件下,执行应用程序代码,因此垃圾回收机制所引起的不可预知的延迟,就成为一个实时程序致命的问题。其实该问题也可以避免,可以通过代码来强制垃圾回收,就可以限制最大延迟时间,使垃圾回收成为可预知的。

虽然拥有了垃圾回收机制,但是JAVA程序本身仍然可能存在内存泄漏。

例如:在不需要组件对象时,却没将其从容器中移除。

以下为JAVA程序设计中有关内存管理的经验:

①最基本的建议就是尽早释放无用对象的引用。大多数程序员在使用临时变量的时候,都是让引用变量在退出活动域后,自动设置为null。

如:A a=new A();
a=null; //当使用对象a之后主动将其设置为空

②尽量少用finalize函数回收资源。

③尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其自己类的构造器时,造成不必要的内存资源浪费。

④尽量避免强制系统做垃圾内存的回收。

⑤尽量避免显式申请数组空间,当不得不显式地申请数组空间时,尽量准确地估计出其合理值,以免造成不必要的系统内存开销。

猜你喜欢

转载自blog.csdn.net/qq_45613931/article/details/101772649