java学习_有趣代码片段(一)
来源:互联网 发布:mac开发人工智能软件 编辑:程序博客网 时间:2024/06/05 20:28
记一个有趣的代码片段
昨天看到一个十分有意思的问题,当时看到问题的我也是瞬间懵了。其实就是自己掌握的知识不扎实。现在我把它分开经行解析下,如有不对,请指正!主要还是自己对基础知识理解的不扎实,以后还会遇到许许多多的问题,就干脆起了个java学习有趣代码片段(一)。
第一个问题
代码如下
package com.zhb;public class Test { static Test test = new Test("3"); static{ System.out.println("1"); } { System.out.println("2"); } Test(String s){ System.out.println(s); } public static void staticFunction(){ System.out.println("4"); } public static void main(String[] args) { staticFunction(); }}
看到这段代码,我心想我刚刚总结了关于static代码块的总结,这个还不在话下!结果应该是 1 2 3 4 。
运行后,我发现,什么鬼!
* 正确的运行结果:2 3 1 4 *
拆解分析
1.首先我们先再复习下关于代码块的知识
package com.zhb;public class Demo1 { /** * 静态代码块 */ static{ System.out.println("静态代码块"); } /** * 构造代码 */ { System.out.println("构造代码块"); } /** * 无参构造函数 */ public Demo1(){ System.out.println("无参构造函数"); } /** * 有参数的构造函数 */ public Demo1(int num){ System.out.println("有参数的构造函数"); } public static void main(String[] args) { System.out.println("=================="); new Demo1(); System.out.println("=================="); new Demo1(2); }}
执行结果
静态代码块==================
构造代码块
无参构造函数==================
构造代码块
有参数的构造函数
从中我们可以看出
- 静态代码块它是随着类的加载而被执行,只要类加载了就会执行,而且只加载一次,主要用于给类进行初始化;
new一个对象的时候总是先执行构造代码,在执行构造函数,但是有一点需要注意构造代码不是在构造函数之前运行,它是依托构造函数执行。
构造代码块每创建一个对象时,就会执行一次。同时构造函数是给特定的对象进行初始化,而构造代码是给所有的对象进行初始化,作用域不同。
执行顺序:静态代码块> 构造代码块 > 构造函数
2,重现原题中的结构代码
package com.zhb;public class Demo2 { static Demo1 demo1 =new Demo1() ; /** * 静态构造代码 */ static{ System.out.println("Demo2静态构造代码块"); } /** * 构造代码 */ { System.out.println("Demo2构造代码块"); } /** * 无参构造函数 */ public Demo2(){ System.out.println("Demo2无参构造函数"); } /** * 有参数的构造函数 */ public Demo2(int num){ System.out.println("Demo2有参数的构造函数"); } public static void main(String[] args) { System.out.println("=================="); new Demo2(); System.out.println("=================="); new Demo2(2); }}
执行结果:
静态代码块
构造代码块
无参构造函数
Demo2静态构造代码块==================
Demo2构造代码块
Demo2无参构造函数==================
Demo2构造代码块
Demo2有参数的构造函数
从中我们知道
- 静态变量和静态构造代码块是同级别的;
- static按照顺序执行
进一步演练
package com.zhb;public class Demo2 { //static Demo1 demo1 =new Demo1() ; static Demo2 demo2 =new Demo2() ; /** * 静态构造代码 */ static{ System.out.println("Demo2静态构造代码块"); } /** * 构造代码 */ { System.out.println("Demo2构造代码块"); } /** * 无参构造函数 */ public Demo2(){ System.out.println("Demo2无参构造函数"); } /** * 有参数的构造函数 */ public Demo2(int num){ System.out.println("Demo2有参数的构造函数"); } public static void main(String[] args) { System.out.println("=================="); new Demo2(); System.out.println("=================="); new Demo2(2); }}
此时的代码结构和原题是一样的。
顺序执行静态部分,首先执行 static Demo2 demo2 =new Demo2() ;
此时,new一个对象的时候总是先执行构造代码。
执行System.out.println(“Demo2构造代码块”);执行构造函数 System.out.println(“Demo2无参构造函数”);此时demo2 结束
顺序执行静态构造代码
后面的正常执行(前面已解释)
执行结果:
Demo2构造代码块
Demo2无参构造函数
Demo2静态构造代码块==================
Demo2构造代码块
Demo2无参构造函数==================
Demo2构造代码块
Demo2有参数的构造函数
此时明白了原程序为什么是那样的结果了
第二个问题
我们把原题的程序修改成如下
package com.zhb;public class Test { static Test test = new Test(); Test test2 = new Test(); public static void main(String[] args) { }}
执行后报错
- Exception in thread “main” java.lang.StackOverflowError *
这个问题是为什么呢?
静静的分析下
1.我们知道首先运行static.
2.static Test test = new Test(); 初始化Test类,会把类的成员变量实例化
3.实例化test2,但是Test test2 = new Test();此时又会实例化test2,一直进行循环
4.导致栈溢出
这里又引出一个问题:类的实例变量初始化的过程
class B { private int b = 10; public B(){ b = 100; }}
编译成class文件后,使用命令 javap -c B.class 反编译
// 第一部分:父类的<init>()方法0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V// 第二部分:实例变量初始化,也就是定义变量时的赋值4: aload_05: bipush 107: putfield #2 // Field b:I// 第三部分:构造函数方法体10: aload_011: bipush 10013: putfield #2 // Field b:I16: return
学习到这里总结一下前面学习的内容就是:
* Java实例变量在初始化时的顺序是父类的初始化代码(xxx—>xxx—>xxx)—>定义变量时直接赋值—>构造函数代码块。*
由于我也是菜鸟一枚,很多也是一知半解,如有不对,请指正。
参考:
1.http://blog.csdn.net/chenssy/article/details/14486833
2.http://blog.csdn.net/cauchyweierstrass/article/details/48943077
- java学习_有趣代码片段(一)
- 代码片段学习(一)
- 有趣的代码片段
- 代码片段(一)
- 有趣的 JavaScript 代码片段
- Nginx学习笔记——进程代码片段(一)
- 实用代码片段(一)
- 算法代码片段(一)
- 那些不够优雅的java代码片段(一)
- Java算法片段(一)
- 5个有趣的 JavaScript 代码片段
- 5个有趣的 JavaScript 代码片段
- 5个有趣的 JavaScript 代码片段
- (转)android有用代码片段(一)
- Android 实用代码片段(一)
- Android实用代码片段(一)
- php开发常用代码片段(一)
- Android常用代码片段(一)
- 个人笔记(cin.getline与cin.get)
- Android 拍照或从相册取图片并裁剪
- IOS读取Plist文件代码
- TCP、UDP、IP报头结构体分析
- 为什么要对1000000007取模
- java学习_有趣代码片段(一)
- ABAP eclipse 打开ddl sources异常错误
- 模块设计与实现经验总结(三)
- oracle导入数据库问题:12154错误
- Spring Bean 循环依赖解决方案
- 蓝桥杯历届试题-六角填数(12)
- 《WINDOWSPE权威指南》学习笔记(一)-U盘监控器的破解
- AngularJS ng-model 指令
- 关于ThinkPHP中URL及模板文件名大小写的讨论