CS61B sp2018笔记 | Exceptions, Iterators, Iterables

1. Throwing and catching

1.1 Throwing Exceptions

在程序运行过程中,可能会遇到某些错误需要终止,这时程序就会抛出一个异常。

让我们看看一个常见的情况——IndexOutOfBounds异常。下面的程序向ArrayMap中插入value为5,key为”hello”的一组数据,试图获取key为”yolp”的value:

public static void main (String[] args) {
    ArrayMap<String, Integer> am = new ArrayMap<String, Integer>();
    am.put("hello", 5);
    System.out.println(am.get("yolp"));
}

运行这个程序时,发现这个key值根本不存在,然后造成混乱,结果打印了一些错误信息:

$ java ExceptionDemo
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at ArrayMap.get(ArrayMap.java:38)
at ExceptionDemo.main(ExceptionDemo.java:6)

这是隐式的异常,是由Java本身抛出的错误。这个错误告诉我们ArrayIndexOutOfBoundsException错误造成了程序混乱,但是它并没有明确那个数据或是那个步骤造成了这个错误,对用户来讲并没有给出很多有价值的提示。

不过,我们可以使用throw关键字,抛出自己的异常信息。比如说,我们可以重新实现get方法:

public V get(K key) {
    intlocation = findKey(key);
if(location < 0) {
    throw newIllegalArgumentException("Key " + key + " does not exist in map."\); 
}
    return values[findKey(key)];
}

这时候再运行程序,我们就可以清楚的看到出错的位置:

$java ExceptionDemo
Exception in thread "main" java.lang.IllegalArgumentException: Key yolp does not exist in map.
at ArrayMap.get(ArrayMap.java:40)
at ExceptionDemo.main(ExceptionDemo.java:6)

1.2 Catching Exceptions

我们已经知道,当程序运行出错时会抛出异常,那么当抛出异常时我们还能做些什么呢?考虑一下下面这些异常情况:

  • 你试图使用3831240亿个字节的内存
  • 你试图把一个对象转换成dog,但这个对象的动态类型不是dog
  • 你试图调用一个指向null的引用类型的方法
  • 你试图访问数组-1位置的元素

我们进行如下操作:

Object o = "mulchor";
Planet x = (Planet) o;

将会导致问题:

Exception in thread "main" java.lang.ClassCastException: 
java.lang.String cannot be cast to Planet

接着,我们用显示的异常处理提供错误信息:

public static void main(String[] args) {
    System.out.println("ayyy lmao");
    throw new RuntimeException("For no reason.");
}

这种情况下运行程序:

$ java Alien
ayyy lmao
Exception in thread "main" java.lang.RuntimeException: For no reason.
at Alien.main(Alien.java:4)

于是我们发现,即使程序中没有错误,我们也可以实例化RuntimeException类来抛出异常

RuntimeException类抛出异常

更为常规的做法是,使用trybreak方法捕捉可能发生异常的代码,考虑下面的例子:

Dog d = new Dog("Lucy", "Retriever", 80);
d.becomeAngry();

try {
    d.receivePat();
} catch (Exception e) {
    System.out.println("Tried to pat: " + e);
}
System.out.println(d);

程序的结果可能会是这样:

$ java ExceptionDemo
Tried to pat: java.lang.RuntimeException: grrr... snarl snarl
Lucy is a displeased Retriever weighing 80.0 standard lb units.

1.3 The Philosophy Of Exceptions

异常的设计不仅仅是为了捕获程序中的错误,提供给用户更准确的信息。更重要的是,它能把处理错误的程序彼此分开。考虑一下下面的情况:

func readFile: {
    open the file;
    determine its size;
    allocate that much memory;
    read the file into memory;
    close the file;
}

这是一些对文件操作的程序,每个部分都可能导致错误,没有try-catch的异常处理手段,我们可能写出这样的代码:

func readFile: {
    open the file;
    if (theFileIsOpen) {
        determine its size;
        if (gotTheFileLength) {
            allocate that much memory;
        } else {
            return error("fileLengthError");
        }
            if (gotEnoughMemory) {
                read the file into memory;
            if (readFailed) {
                return error("readError");
            }
        ...
        } else {
            return error("memoryError");
        }
    } else {
        return error("fileOpenError")
    } 
}

然而,用异常处理的手段代码就变得简洁多了:

func readFile: {
    try {
        open the file;
        determine its size;
        allocate that much memory;
        read the file into memory;
        close the file;
    } catch (fileOpenFailed) {
        doSomething;
    } catch (sizeDeterminationFailed) {
        doSomething;
    } catch (memoryAllocationFailed) {
        doSomething;
    } catch (readFailed) {
        doSomething;    
    } catch (fileCloseFailed) {
        doSomething;
    }
}

2. Checked vs Unchecked Exceptions

上面谈论到的异常都是运行时异常,我们可以称之为“unchecked” exceptions;可有些错误简直连编译器都看不过去了,编译时期就会报错,我们称之为“checked” exceptions

异常的类型

3. Iterators and Iterables

3.1 Iteration

我们知道Java允许我们这样来遍历一个链表:

List<Integer> friends =
new ArrayList<Integer>();
friends.add(5);
friends.add(23);
friends.add(42);
for (int x : friends) {
    System.out.println(x);
}

我们也可以使用iterator来遍历,先在List.java中定义:

public Iterator<E> iterator();

然后我们就可以使用它来遍历:

List<Integer> friends = new ArrayList<Integer>();
...
Iterator<Integer> seer = friends.iterator();

while (seer.hasNext()) {
    System.out.println(seer.next());
}

猜你喜欢

转载自blog.csdn.net/qq_40950957/article/details/81324531