我想知道Exception的两个构造函数的实现细节,于是我找他的父类Throwable,当我找到他的父类Throwable后发现它implements Serializable,而Throwable自己的构造函数里面是: public Throwable() {
fillInStackTrace();
}
和
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
也就是Exception的两个构造函数的间接原型,我又往上追究Serializable(因为Throwable implements Serializable),但是我却发现Serializable仅仅是一个接口,仅仅说明了这个接口,这下我崩溃了,还是没有找到Exception的两个构造函数的实现细节???可能是我找错了吧,还望高手指点一下Exception的两个构造函数的实现细节,我快崩溃了,我不想稀里糊涂地用自定义的异常类super调用他的父类构造函数(继承自Exception的两个构造函数)!!!
fillInStackTrace();
}
和
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
也就是Exception的两个构造函数的间接原型,我又往上追究Serializable(因为Throwable implements Serializable),但是我却发现Serializable仅仅是一个接口,仅仅说明了这个接口,这下我崩溃了,还是没有找到Exception的两个构造函数的实现细节???可能是我找错了吧,还望高手指点一下Exception的两个构造函数的实现细节,我快崩溃了,我不想稀里糊涂地用自定义的异常类super调用他的父类构造函数(继承自Exception的两个构造函数)!!!
private StackTraceElement[] stackTrace; //这个就是记录用的数组, 以便使用public StackTraceElement[] getStackTrace()把记录的异常调出来
private StackTraceElement[] stackTrace;
//这两个构造函数我就不说了。
public Throwable() {
fillInStackTrace();
}public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
public Throwable(String message, Throwable cause) {
fillInStackTrace();
detailMessage = message;
this.cause = cause;
}//这句代码说明了在构造函数中所调用的fillInStackTrace()是一个本地方法,即,这个函数的实现不是由Java代码来实现,而是用别的语言来实现的,也许是C,也许是C++。
public synchronized native Throwable fillInStackTrace();好了,至此为止,分析完毕。很明显,你不会满意的。但我想和你说:同学,如果按你现在的思路,因为没搞清楚父类的构造函数是如何实现的,就不能写自定义异常了,那是不是每一个学开车的人都应该先学会怎么制造汽车呢?是不是牛顿还没有发现万有引力之前,大家都没法活了呢?这个世界我们不知道的东西太多太多了,不能说我们不知道,我们就不能去做事情了。通常,我们把你这种行为称为钻牛角尖。执着是好事情,有助于发现真相,但过份执着就是钻牛角尖,这会让你的学习停滞不前的。最后,如果你还是不满意,那我还是给你一条路,尽管我觉得你现在还不应该去走。native关键字的意思就是“本地”,而Java就是通过native声明来调用其他语言的函数的。想要更详细的了解,请查看关于“JNI(Java Native Interface)”的知识。如果你还是不满意,那我再告诉你:现在Java虚拟机的源代码也已经全部开源了,你可以去查看JVM关于异常处理的代码(但你一定会比现在更晕)。有的时候,不知道比知道更好。老人常说,等你长大了,你就明白了。这句话有两个意思,第一:因为你缺乏相关知识经验,现在怎么讲,你都不会明白的,而知识经验的积累是需要很长时间的。第二:当你具备了相关知识经验,不用再解释你也会明白。我估计照你现在的方式研究下去,你的目标将不是如何去写一个自定义异常类,而会变成如何实现Java虚拟机。弱弱的问一句:这真是你现阶段的目标么?
public synchronized native Throwable fillInStackTrace(); 好了,至此为止,分析完毕。 很明显,你不会满意的。 但我想和你说:同学,如果按你现在的思路,因为没搞清楚父类的构造函数是如何实现的,就不能写自定义异常了,那是不是每一个学开车的人都应该先学会怎么制造汽车呢?是不是牛顿还没有发现万有引力之前,大家都没法活了呢? 这个世界我们不知道的东西太多太多了,不能说我们不知道,我们就不能去做事情了。 通常,我们把你这种行为称为钻牛角尖。 执着是好事情,有助于发现真相,但过份执着就是钻牛角尖,这会让你的学习停滞不前的。 最后,如果你还是不满意,那我还是给你一条路,尽管我觉得你现在还不应该去走。 native关键字的意思就是“本地”,而Java就是通过native声明来调用其他语言的函数的。 想要更详细的了解,请查看关于“JNI(Java Native Interface)”的知识。 如果你还是不满意,那我再告诉你:现在Java虚拟机的源代码也已经全部开源了,你可以去查看JVM关于异常处理的代码(但你一定会比现在更晕)。 有的时候,不知道比知道更好。 老人常说,等你长大了,你就明白了。 这句话有两个意思,第一:因为你缺乏相关知识经验,现在怎么讲,你都不会明白的,而知识经验的积累是需要很长时间的。第二:当你具备了相关知识经验,不用再解释你也会明白。 我估计照你现在的方式研究下去,你的目标将不是如何去写一个自定义异常类,而会变成如何实现Java虚拟机。弱弱的问一句:这真是你现阶段的目标么?
谢谢你的解释,其实我应经很满意了,只是我现在见识还太少,我以为要是我一直往上追溯的话就能找到构造函数的原型,有时候觉得用函数太随意了,知道不知道都只管调用,觉得没意思,想追根问底,其实就现阶段我的水平来说,会用继承来自父类的构造函数就行了,不过还是不甘心,感觉一定要定义几个自己写的类,然后自己调用自己的函数才甘心!!!见笑了,都怪我浅薄!!!
你现在根本没必要搞清楚那个JVM本地实现,因为在不同系统下的JVM,对本地实现还不一样的。正因为JVM负责了和本地系统打交道,JAVA字节码运行在虚拟机上,所以java才有系统无关系。在说两句,关于那个Serializable接口,这个接口更和你的问题无关。Serializable接口是一个标记性接口,用来标示一个类可序列化。一个可序列化的类,必须全部成员变量(除了用transient关键字修饰的变量)都是可序列化的。
而可序列化的意思是,你现在可以简单理解为可以保存到硬盘上。
这引发了我另外一个问题,
为什么fillStackTrace要用native来实现?
而我们通常看到的Stacktrace是不包含native代码的?
Exception()
构造详细消息为 null 的新异常。
Exception(String message)
构造带指定详细消息的新异常。
Exception(String message, Throwable cause)
构造带指定详细消息和原因的新异常。
Exception(Throwable cause)
根据指定的原因和 (cause==null ? null : cause.toString()) 的详细消息构造新异常(它通常包含 cause 的类和详细消息)。
JAVA的有些类是SUN公司写出来的
里面的实施可能都不是用JAVA能编译出来的
有些是直接的字节码
系统自动编译
看了一下你描述中最后居然找到了Serializable这个接口,就说明你对java还不是很了解,这个接口就是一个标记,他负责序列化用的,和异常什么的根本没关系,所以楼主现在的任务主要应该是学习各个类都是做什么的,如果要看底层实现,那也是看一下比如Collections这样的类是怎样实现排序和查找之类的问题就足够了,在于java是如何实现数据结构中那些队列和堆栈之类的东西等真的没什么可研究了在去看也不迟,到时候可能你真的要看,因为你可能在想如何发明Z语言。
另外看一些设计模式的书对真正理解java源代码也是大有好处的,要不等你看IO部分的代码时肯定是要崩溃的