首页 > 代码库 > AssertionError、Error和Throwable

AssertionError、Error和Throwable

AssertionError继承Error,提供了多个构造方法,代码如下:

/* *  Licensed to the Apache Software Foundation (ASF) under one or more *  contributor license agreements.  See the NOTICE file distributed with *  this work for additional information regarding copyright ownership. *  The ASF licenses this file to You under the Apache License, Version 2.0 *  (the "License"); you may not use this file except in compliance with *  the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, software *  distributed under the License is distributed on an "AS IS" BASIS, *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *  See the License for the specific language governing permissions and *  limitations under the License. */package java.lang;/** * Thrown when an assertion has failed. * * @since 1.4 */public class AssertionError extends Error {    private static final long serialVersionUID = -5013299493970297370L;    /**     * Constructs a new {@code AssertionError} with no message.     */    public AssertionError() {    }    /**     * Constructs a new {@code AssertionError} with the given detail message and cause.     * @since 1.7     * @hide 1.7     */    public AssertionError(String detailMessage, Throwable cause) {        super(detailMessage, cause);    }    /**     * Constructs a new {@code AssertionError} with a message based on calling     * {@link String#valueOf(Object)} with the specified object. If the object     * is an instance of {@link Throwable}, then it also becomes the cause of     * this error.     *     * @param detailMessage     *            the object to be converted into the detail message and     *            optionally the cause.     */    public AssertionError(Object detailMessage) {        super(String.valueOf(detailMessage));        if (detailMessage instanceof Throwable) {            initCause((Throwable) detailMessage);        }    }    /**     * Constructs a new {@code AssertionError} with a message based on calling     * {@link String#valueOf(boolean)} with the specified boolean value.     *     * @param detailMessage     *            the value to be converted into the message.     */    public AssertionError(boolean detailMessage) {        this(String.valueOf(detailMessage));    }    /**     * Constructs a new {@code AssertionError} with a message based on calling     * {@link String#valueOf(char)} with the specified character value.     *     * @param detailMessage     *            the value to be converted into the message.     */    public AssertionError(char detailMessage) {        this(String.valueOf(detailMessage));    }    /**     * Constructs a new {@code AssertionError} with a message based on calling     * {@link String#valueOf(int)} with the specified integer value.     *     * @param detailMessage     *            the value to be converted into the message.     */    public AssertionError(int detailMessage) {        this(Integer.toString(detailMessage));    }    /**     * Constructs a new {@code AssertionError} with a message based on calling     * {@link String#valueOf(long)} with the specified long value.     *     * @param detailMessage     *            the value to be converted into the message.     */    public AssertionError(long detailMessage) {        this(Long.toString(detailMessage));    }    /**     * Constructs a new {@code AssertionError} with a message based on calling     * {@link String#valueOf(float)} with the specified float value.     *     * @param detailMessage     *            the value to be converted into the message.     */    public AssertionError(float detailMessage) {        this(Float.toString(detailMessage));    }    /**     * Constructs a new {@code AssertionError} with a message based on calling     * {@link String#valueOf(double)} with the specified double value.     *     * @param detailMessage     *            the value to be converted into the message.     */    public AssertionError(double detailMessage) {        this(Double.toString(detailMessage));    }}

其父类Error继承自Throwable,有四个构造方法,如下:

/* *  Licensed to the Apache Software Foundation (ASF) under one or more *  contributor license agreements.  See the NOTICE file distributed with *  this work for additional information regarding copyright ownership. *  The ASF licenses this file to You under the Apache License, Version 2.0 *  (the "License"); you may not use this file except in compliance with *  the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, software *  distributed under the License is distributed on an "AS IS" BASIS, *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *  See the License for the specific language governing permissions and *  limitations under the License. */package java.lang;/** * {@code Error} is the superclass of all classes that represent unrecoverable * errors. When errors are thrown, they should not be caught by application * code. * * @see Throwable * @see Exception * @see RuntimeException */public class Error extends Throwable {    private static final long serialVersionUID = 4980196508277280342L;    /**     * Constructs a new {@code Error} that includes the current stack trace.     */    public Error() {    }    /**     * Constructs a new {@code Error} with the current stack trace and the     * specified detail message.     *     * @param detailMessage     *            the detail message for this error.     */    public Error(String detailMessage) {        super(detailMessage);    }    /**     * Constructs a new {@code Error} with the current stack trace, the     * specified detail message and the specified cause.     *     * @param detailMessage     *            the detail message for this error.     * @param throwable     *            the cause of this error.     */    public Error(String detailMessage, Throwable throwable) {        super(detailMessage, throwable);    }    /**     * Constructs a new {@code Error} with the current stack trace and the     * specified cause.     *     * @param throwable     *            the cause of this error.     */    public Error(Throwable throwable) {        super(throwable);    }}


而Throwable是所有异常和错误的超类,里面有两个native方法,代码如下:

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package java.lang;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.PrintStream;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Collections;import java.util.List;import libcore.util.EmptyArray;/** * The superclass of all classes which can be thrown by the VM. The * two direct subclasses are recoverable exceptions ({@code Exception}) and * unrecoverable errors ({@code Error}). This class provides common methods for * accessing a string message which provides extra information about the * circumstances in which the {@code Throwable} was created (basically an error * message in most cases), and for saving a stack trace (that is, a record of * the call stack at a particular point in time) which can be printed later. * <p> * A {@code Throwable} can also include a cause, which is a nested {@code * Throwable} that represents the original problem that led to this {@code * Throwable}. It is often used for wrapping various types of errors into a * common {@code Throwable} without losing the detailed original error * information. When printing the stack trace, the trace of the cause is * included. * * @see Error * @see Exception * @see RuntimeException */public class Throwable implements java.io.Serializable {    private static final long serialVersionUID = -3042686055658047285L;    /**     * The message provided when the exception was created.     */    private String detailMessage;    /**     * The cause of this Throwable. Null when there is no cause.     */    private Throwable cause = this;    /**     * Throwables suppressed by this throwable. Null when suppressed exceptions     * are disabled.     */    private List<Throwable> suppressedExceptions = Collections.emptyList();    /**     * An intermediate representation of the stack trace.  This field may     * be accessed by the VM; do not rename.     */    private transient volatile Object stackState;    /**     * A fully-expanded representation of the stack trace.     */    private StackTraceElement[] stackTrace;    /**     * Constructs a new {@code Throwable} that includes the current stack trace.     */    public Throwable() {        fillInStackTrace();    }    /**     * Constructs a new {@code Throwable} with the current stack trace and the     * specified detail message.     *     * @param detailMessage     *            the detail message for this {@code Throwable}.     */    public Throwable(String detailMessage) {        this();        this.detailMessage = detailMessage;    }    /**     * Constructs a new {@code Throwable} with the current stack trace, the     * specified detail message and the specified cause.     *     * @param detailMessage     *            the detail message for this {@code Throwable}.     * @param throwable     *            the cause of this {@code Throwable}.     */    public Throwable(String detailMessage, Throwable throwable) {        this();        this.detailMessage = detailMessage;        cause = throwable;    }    /**     * Constructs a new {@code Throwable} with the current stack trace and the     * specified cause.     *     * @param throwable     *            the cause of this {@code Throwable}.     */    public Throwable(Throwable throwable) {        this();        this.detailMessage = throwable == null ? null : throwable.toString();        cause = throwable;    }    /**     * Constructs a new {@code Throwable} with the current stack trace, the     * specified detail message and the specified cause.     *     * @param enableSuppression if false, throwables passed to {@link     *     #addSuppressed(Throwable)} will be silently discarded.     * @since 1.7     * @hide 1.7     */    protected Throwable(String detailMessage, Throwable throwable, boolean enableSuppression) {        this(detailMessage, throwable);        if (!enableSuppression) {            this.suppressedExceptions = null;        }    }    /**     * Records the stack trace from the point where this method has been called     * to this {@code Throwable}. This method is invoked by the {@code Throwable} constructors.     *     * <p>This method is public so that code (such as an RPC system) which catches     * a {@code Throwable} and then re-throws it can replace the construction-time stack trace     * with a stack trace from the location where the exception was re-thrown, by <i>calling</i>     * {@code fillInStackTrace}.     *     * <p>This method is non-final so that non-Java language implementations can disable VM stack     * traces for their language. Filling in the stack trace is relatively expensive.     * <i>Overriding</i> this method in the root of a language‘s exception hierarchy allows the     * language to avoid paying for something it doesn‘t need.     *     * @return this {@code Throwable} instance.     */    public Throwable fillInStackTrace() {        // Fill in the intermediate representation        stackState = nativeFillInStackTrace();        // Mark the full representation as empty        stackTrace = null;        return this;    }    /**     * Returns the extra information message which was provided when this     * {@code Throwable} was created. Returns {@code null} if no message was     * provided at creation time.     *     * @return this {@code Throwable}‘s detail message.     */    public String getMessage() {        return detailMessage;    }    /**     * Returns the extra information message which was provided when this     * {@code Throwable} was created. Returns {@code null} if no message was     * provided at creation time. Subclasses may override this method to return     * localized text for the message. Android returns the regular detail message.     *     * @return this {@code Throwable}‘s localized detail message.     */    public String getLocalizedMessage() {        return getMessage();    }    /**     * Returns the array of stack trace elements of this {@code Throwable}. Each     * {@code StackTraceElement} represents an entry in the call stack. The     * element at position 0 is the top of the stack, that is, the stack frame     * where this {@code Throwable} is thrown.     *     * @return a copy of the array of {@code StackTraceElement}s representing     *         the call stack. Changes in the array obtained from this call will     *         not change the call stack stored in this {@code Throwable}.     * @see #printStackTrace()     */    public StackTraceElement[] getStackTrace() {        return getInternalStackTrace().clone();    }    /**     * Sets the array of stack trace elements. Each {@code StackTraceElement}     * represents an entry in the call stack. A copy of the specified array is     * stored in this {@code Throwable}. will be returned by {@code     * getStackTrace()} and printed by {@code printStackTrace()}.     *     * @param trace     *            the new array of {@code StackTraceElement}s. A copy of the     *            array is stored in this {@code Throwable}, so subsequent     *            changes to {@code trace} will not change the call stack stored     *            in this {@code Throwable}.     * @throws NullPointerException     *             if any element in {@code trace} is {@code null}.     * @see #printStackTrace()     */    public void setStackTrace(StackTraceElement[] trace) {        StackTraceElement[] newTrace = trace.clone();        for (int i = 0; i < newTrace.length; i++) {            if (newTrace[i] == null) {                throw new NullPointerException("trace[" + i + "] == null");            }        }        stackTrace = newTrace;    }    /**     * Writes a printable representation of this {@code Throwable}‘s stack trace     * to the {@code System.err} stream.     *     */    public void printStackTrace() {        printStackTrace(System.err);    }    /**     * Counts the number of duplicate stack frames, starting from the     * end of the stack.     *     * @param currentStack a stack to compare     * @param parentStack a stack to compare     *     * @return the number of duplicate stack frames.     */    private static int countDuplicates(StackTraceElement[] currentStack,            StackTraceElement[] parentStack) {        int duplicates = 0;        int parentIndex = parentStack.length;        for (int i = currentStack.length; --i >= 0 && --parentIndex >= 0;) {            StackTraceElement parentFrame = parentStack[parentIndex];            if (parentFrame.equals(currentStack[i])) {                duplicates++;            } else {                break;            }        }        return duplicates;    }    /**     * Returns an array of StackTraceElement. Each StackTraceElement     * represents a entry on the stack.     *     * @return an array of StackTraceElement representing the stack     */    private StackTraceElement[] getInternalStackTrace() {        if (stackTrace == null) {            stackTrace = nativeGetStackTrace(stackState);            stackState = null; // Clean up intermediate representation        }        return stackTrace;    }    /**     * Writes a printable representation of this {@code Throwable}‘s stack trace     * to the specified print stream. If the {@code Throwable} contains a     * {@link #getCause() cause}, the method will be invoked recursively for     * the nested {@code Throwable}.     *     * @param err     *            the stream to write the stack trace on.     */    public void printStackTrace(PrintStream err) {        try {            printStackTrace(err, "", null);        } catch (IOException e) {            // Appendable.append throws IOException but PrintStream.append doesn‘t.            throw new AssertionError();        }    }    /**     * Writes a printable representation of this {@code Throwable}‘s stack trace     * to the specified print writer. If the {@code Throwable} contains a     * {@link #getCause() cause}, the method will be invoked recursively for the     * nested {@code Throwable}.     *     * @param err     *            the writer to write the stack trace on.     */    public void printStackTrace(PrintWriter err) {        try {            printStackTrace(err, "", null);        } catch (IOException e) {            // Appendable.append throws IOException, but PrintWriter.append doesn‘t.            throw new AssertionError();        }    }    /**     * @param indent additional indentation on each line of the stack trace.     *     This is the empty string for all but suppressed throwables.     * @param parentStack the parent stack trace to suppress duplicates from, or     *     null if this stack trace has no parent.     */    private void printStackTrace(Appendable err, String indent, StackTraceElement[] parentStack)            throws IOException {        err.append(toString());        err.append("\n");        StackTraceElement[] stack = getInternalStackTrace();        if (stack != null) {            int duplicates = parentStack != null ? countDuplicates(stack, parentStack) : 0;            for (int i = 0; i < stack.length - duplicates; i++) {                err.append(indent);                err.append("\tat ");                err.append(stack[i].toString());                err.append("\n");            }            if (duplicates > 0) {                err.append(indent);                err.append("\t... ");                err.append(Integer.toString(duplicates));                err.append(" more\n");            }        }        // Print suppressed exceptions indented one level deeper.        if (suppressedExceptions != null) {            for (Throwable throwable : suppressedExceptions) {                err.append(indent);                err.append("\tSuppressed: ");                throwable.printStackTrace(err, indent + "\t", stack);            }        }        Throwable cause = getCause();        if (cause != null) {            err.append(indent);            err.append("Caused by: ");            cause.printStackTrace(err, indent, stack);        }    }    @Override    public String toString() {        String msg = getLocalizedMessage();        String name = getClass().getName();        if (msg == null) {            return name;        }        return name + ": " + msg;    }    /**     * Initializes the cause of this {@code Throwable}. The cause can only be     * initialized once.     *     * @param throwable     *            the cause of this {@code Throwable}.     * @return this {@code Throwable} instance.     * @throws IllegalArgumentException     *             if {@code Throwable} is this object.     * @throws IllegalStateException     *             if the cause has already been initialized.     */    public Throwable initCause(Throwable throwable) {        if (cause != this) {            throw new IllegalStateException("Cause already initialized");        }        if (throwable == this) {            throw new IllegalArgumentException("throwable == this");        }        cause = throwable;        return this;    }    /**     * Returns the cause of this {@code Throwable}, or {@code null} if there is     * no cause.     *     * @return Throwable this {@code Throwable}‘s cause.     */    public Throwable getCause() {        if (cause == this) {            return null;        }        return cause;    }    /**     * Adds {@code throwable} to the list of throwables suppressed by this. The     * throwable will included when this exception‘s stack trace is printed.     *     * @throws IllegalArgumentException if {@code throwable == this}.     * @throws NullPointerException if {@code throwable == null}.     * @since 1.7     * @hide 1.7     */    public final void addSuppressed(Throwable throwable) {        if (throwable == this) {            throw new IllegalArgumentException("throwable == this");        }        if (throwable == null) {            throw new NullPointerException("throwable == null");        }        if (suppressedExceptions != null) {            // suppressed exceptions are enabled            if (suppressedExceptions.isEmpty()) {                // ensure we have somewhere to place suppressed exceptions                suppressedExceptions = new ArrayList<Throwable>(1);            }            suppressedExceptions.add(throwable);        }    }    /**     * Returns the throwables suppressed by this.     *     * @since 1.7     * @hide 1.7     */    public final Throwable[] getSuppressed() {        return (suppressedExceptions != null && !suppressedExceptions.isEmpty())                ? suppressedExceptions.toArray(new Throwable[suppressedExceptions.size()])                : EmptyArray.THROWABLE;    }    private void writeObject(ObjectOutputStream out) throws IOException {        // ensure the stackTrace field is initialized        getInternalStackTrace();        out.defaultWriteObject();    }    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {        in.defaultReadObject();        if (suppressedExceptions != null) {            // the deserialized list may be unmodifiable, so just create a mutable copy            suppressedExceptions = new ArrayList<Throwable>(suppressedExceptions);        }    }    /*     * Creates a compact, VM-specific collection of goodies, suitable for     * storing in the "stackState" field, based on the current thread‘s     * call stack.     */    private static native Object nativeFillInStackTrace();    /*     * Creates an array of StackTraceElement objects from the data held     * in "stackState".     */    private static native StackTraceElement[] nativeGetStackTrace(Object stackState);}

从源码中容易理解他们的层次和调用关系。