思考Throwable类的4个构造器的实际适用场景？

1，Throwable()
	创建一个可抛出的对象，其程序状态错误信息和异常源(父异常)都为空。
	适用场景：异常程序无须传达一些关键的状态信息，根据异常类型名就知道发生了什么错误，

且状态单一。如 {@link NullPointerException}，它表示调用了null对象的字段或方法。用户自定义的

异常类不适合使用这种方式构造，因为这样做的话会丢失整个父异常栈踪迹信息（"Caused by: "）。

2，Throwable(String message)
	创建一个包含具体错误状态信息的可抛出对象，但异常源为空。
	适用场景：其可传达一些关键的程序错误状态信息，且是程序发生异常的根源，非常适用于参

数有效性的检查操作。如JDK大量使用 {@link IllegalArgumentException} ，表示方法参数值非法或不

合理。因为JDK自动的非法参数异常属于运行时异常，应用程序不应该捕获它。大型应用程序都使用自定

义的异常，通过定义类似的构造方法来实现类似功能。

3，Throwable(String message, Throwable cause)
	创建一个包含具体错误状态信息和异常源的可抛出对象。
	适用场景：非常适用于应用程序向上传递异常的同时，记录当前程序的一些关键错误状态信息

。所以，对应用程序自定义的异常非常适合，既能知道底层发生了什么，也能知晓当前执行点的上下文

状态。

4，Throwable(Throwable cause)
	创建一个包含异常源和来自异常源的具体错误状态信息的可抛出对象。
	适用场景：当可抛出对象直接包装其他可抛出对象时，这个构造器非常有用。优点是它通过包

装对异常类型进行转换，缺点是其与父异常包含相同的错误状态信息。

一般，用户自定义的异常只需实现后面3个构造器即可，可以参考 UserCustomException.java 实现。