学习笔记12(异常)

1、尝试“修复”异常

在之前的例子中,我们都只是抓住了异常,但是并没有尝试修复它。

下面我们看一个例子:

public class SalesReport
{
    public static void main(String[] args)
    {
        String filename = "SalesData.txt"; // File name
        int months = 0; // Month counter
        double oneMonth; // One month's sales
        double totalSales = 0.0; // Total sales
        double averageSales; // Average sales

        try
        {
            // Open the file.
            File file = new File(filename);
            Scanner inputFile = new Scanner(file);

            // Process the contents of the file.
            while (inputFile.hasNext())
            {
                // Get a month's sales amount.
                oneMonth = inputFile.nextDouble();

                // Accumulate the amount.
                totalSales += oneMonth;

                // Increment the month counter
                months++;
            }

            // Close the file.
            inputFile.close();

            // Calculate the average.
            averageSales = totalSales / months;

            // Display the results.
            JOptionPane.showMessageDialog(null,
                    String.format("Number of months: %d\n" +
                                    "Total Sales: $%,.2f\n" +
                                    "Average Sales: $%,.2f",
                            months, totalSales, averageSales));
        }
        catch(FileNotFoundException e)
        {
            // Thrown by the Scanner constructor when
            // the file is not found.
            JOptionPane.showMessageDialog(null,
                    "The file " + filename + " does not exist.");
        }
        catch(InputMismatchException e)
        {
            // Thrown by the Scanner class's nextDouble
            // method when a non-numeric value is found.
            JOptionPane.showMessageDialog(null,
                    "Non-numeric data found in the file.");
        }

        System.exit(0);
    }
}

这个程序从文件中读取每个月的销售额,然后返回总和。程序可能遇到两个问题FileNotFoundExceptionInputMismatchException,当这两个异常出现的时候,程序虽然不会直接退出,而是会打印两条错误信息,但是接下来程序就没有办法继续执行了(何为继续执行?比如遇到InputMismatchException后,跳过这行数据,继续读取下一行的数据),如何做到不被异常影响呢?

import java.io.*; // For File class and FileNotFoundException
        import java.util.*; // For Scanner and InputMismatchException
        import javax.swing.JOptionPane; // For the JOptionPane class

/**
 This program demonstrates how exception handlers can
 be used to recover from errors.
 */

public class SalesReport2
{
    public static void main(String[] args)
    {
        String filename = "SalesData.txt"; // File name
        int months = 0; // Month counter
        double oneMonth; // One month's sales
        double totalSales = 0.0; // Total sales
        double averageSales; // Average sales

        // Attempt to open the file by calling the
        // openfile method.
        Scanner inputFile = openFile(filename);

        // If the openFile method returned null, then
        // the file was not found. Get a new file name.
        while (inputFile == null)
        {
            filename = JOptionPane.showInputDialog(
                    "ERROR: " + filename +
                            " does not exist.\n" +
                            "Enter another file name: ");
            inputFile = openFile(filename);
        }

        // Process the contents of the file.
        while (inputFile.hasNext())
        {
            try
            {
                // Get a month's sales amount.
                oneMonth = inputFile.nextDouble();

  / Accumulate the amount.
                    totalSales += oneMonth;

                // Increment the month counter.
                months++;
            }
            catch(InputMismatchException e)
            {
                // Display an error message.
                JOptionPane.showMessageDialog(null,
                        "Non-numeric data found in the file.\n" +
                                "The invalid record will be skipped.");

                // Skip past the invalid data.
                inputFile.nextLine();
            }
        }
        // Close the file.
        inputFile.close();

        // Calculate the average.
        averageSales = totalSales / months;

        // Display the results.
        JOptionPane.showMessageDialog(null,
                String.format("Number of months: %d\n" +
                                "Total Sales: $%,.2f\n" +
                                "Average Sales: $%,.2f",
                        months, totalSales, averageSales));

        System.exit(0);
    }

    /**
     The opeFile method opens the specified file and
     returns a reference to a Scanner object.
     @param filename The name of the file to open.
     @return A Scanner reference, if the file exists
     Otherwise, null is returned.
     */

    public static Scanner openFile(String filename)
    {
        Scanner scan;

        // Attempt to open the file.
        try
        {
            File file = new File(filename);
            scan = new Scanner(file);
        }
        catch(FileNotFoundException e)
        {
            scan = null;
        }

        return scan;
    }
}

假设程序读取的文件内如为:

24987.62

26978.97

abc

31978.47

22781.76

29871.44

运行结果:

更改之后,程序即使遇到了异常,也可以跳过异常,继续运行了。其实思路很简单,就是将try catch语句写进循环中。在某个地方出现异常后,进入catch语句,在catch语句中改变操作对象(在这个例子中,就是将Scanner的扫描对象改到下一行),然后跳出try catch,进入try catch外的循环,再进入try catch语句,这时由于try中的对象改变,try语句可能就不报错,这样就达到了跳过异常的目的。

2、finally语句

try catch语句后可以选择加一个finally语句,基本的格式如下:

try
{
 (try block statements . . . ) }
catch (ExceptionType ParameterName) {
 (catch block statements . . . ) }
finally
{
 (finally block statements . . . ) }

如果程序抛出了异常,那么finally语句就会在catch语句之后执行,如果没有抛出异常,那么finally语句就在try语句之后执行,简言之,不论程序是否抛出异常,finally语句都会执行。

3、当一个异常没有被catch的时候

异常必须由编写的或默认的异常处理程序来处理。当方法中抛出异常时,该方法的正常执行将停止,JVM将在方法中搜索匹配的异常处理程序。如果此方法中没有处理异常的handle,那么就会查找堆栈中的前一个方法(即调用出现异常方法的方法)能否处理。如果还是无法处理异常,则再次将调用堆栈传递到上一个方法。这种情况一直持续到main方法为止。如果主方法不处理异常,则程序将停止,默认异常处理程序将处理异常。

/**
 This program demonstrates the stack trace that is
 produced when an exception is thrown.
 */

public class StackTrace
{
    public static void main(String[] args)
    {
        System.out.println("Calling myMethod...");
        myMethod();
        System.out.println("Method main is done.");
    }

    /**
     MyMethod
     */

    public static void myMethod()
    {
        System.out.println("Calling produceError...");
        produceError();
        System.out.println("myMethod is done.");
    }

    /**
     produceError
     */

    public static void produceError()
    {
        String str = "abc";

        // The following statement will cause an error.
        System.out.println(str.charAt(3));
        System.out.println("produceError is done.");
    }
}
Calling myMethod...
Calling produceError...
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 3
at java.lang.String.charAt(Unknown Source)
at StackTrace.produceError(StackTrace.java:35)
at StackTrace.myMethod(StackTrace.java:22)
at StackTrace.main(StackTrace.java:11)

4、throws 

在java中,异常分为两类,一类是checked,一类是unchecked。unchecked异常包括继承自error类的异常和继承自RuntimeException的异常。继承自error类的异常没办法通过代码处理,而继承自RuntimeException的异常从一开始就应该被避免,(出了问题肯定是程序员的问题,java希望你不出问题,而不是出了问题再去解决)所以java对这两类异常的要求是:可以不在程序中写代码处理,出现了这类异常,java就会调用自己的异常处理handle。

而checked异常就是除了unchecked异常之外的所有异常,比如fileNotFound,java会要求你手动编写异常处理的handle,不然编译器会直接报错,根本不让你通过编译。(注意两种异常的区别,一种在执行的时候才会报错,也就是说没有语法错误,一种在编译的时候就是不过关的,即有语法错误(编译也就是计算机将你编写的程序,编译成计算机可以识别的语言;而运行是要执行你所编写的这个程序,实现一定的功能))

当一个方法可能会抛出一个异常,而这个异常又应该被处理的时候,我们就应该为这个方法匹配相应的handle;或者要求方法抛出异常,由调用这个方法的方法处理(如果上层方法依旧没有handle,那就继续抛出,直到找到可以处理的方法),实例如下:

public void displayFile(String name) throws FileNotFoundException

throws表示此方法里面产生的异常交给被调用处处理,调用了throws声明的方法之后,不管操作是否出现异常,都必须使用try...catch语句进行异常处理。主方法使用throws后,那么这个异常就将交给JVM进行处理,而后结束程序调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值