打字猴:1.700441216e+09
1700441216
1700441217 这段代码并不复杂,只是在构造函数中初始化了其他类,想想看这段代码的运行结果是什么?是打印“Hi, show me something”吗?
1700441218
1700441219 答案是这段代码不能运行,报StackOverflowError异常,栈(Stack)内存溢出。这是因为声明s变量时,调用了Son的无参构造函数,JVM又默认调用了父类Father的无参构造函数,接着Father类又初始化了Other类,而Other类又调用了Son类,于是一个死循环就诞生了,直到栈内存被消耗完毕为止。
1700441220
1700441221 可能有读者会觉得这样的场景不可能在开发中出现,那我们来思考这样的场景:Father是由框架提供的,Son类是我们自己编写的扩展代码,而Other类则是框架要求的拦截类(Interceptor类或者Handle类或者Hook方法),再来看看该问题,这种场景不可能出现吗?
1700441222
1700441223 那有读者可能要说了,这种问题只要系统一运行就会发现,不可能对项目产生影响。
1700441224
1700441225 那是因为我们在这里展示的代码比较简单,很容易一眼洞穿,一个项目中的构造函数可不止一两个,类之间的关系也不会这么简单的,要想瞥一眼就能明白是否有缺陷这对所有人员来说都是不可能完成的任务,解决此类问题的最好办法就是:不要在构造函数中声明初始化其他类,养成良好的习惯。
1700441226
1700441227
1700441228
1700441229
1700441230 编写高质量代码:改善Java程序的151个建议 [:1700438105]
1700441231 编写高质量代码:改善Java程序的151个建议 建议36:使用构造代码块精炼程序
1700441232
1700441233 什么叫代码块(Code Block)?用大括号把多行代码封装在一起,形成一个独立的数据体,实现特定算法的代码集合即为代码块,一般来说代码块是不能单独运行的,必须要有运行主体。在Java中一共有四种类型的代码块:
1700441234
1700441235 (1)普通代码块
1700441236
1700441237 就是在方法后面使用“{}”括起来的代码片段,它不能单独执行,必须通过方法名调用执行。
1700441238
1700441239 (2)静态代码块
1700441240
1700441241 在类中使用static修饰,并使用“{}”括起来的代码片段,用于静态变量的初始化或对象创建前的环境初始化。
1700441242
1700441243 (3)同步代码块
1700441244
1700441245 使用synchronized关键字修饰,并使用“{}”括起来的代码片段,它表示同一时间只能有一个线程进入到该方法块中,是一种多线程保护机制。
1700441246
1700441247 (4)构造代码块
1700441248
1700441249 在类中没有任何的前缀或后缀,并使用“{}”括起来的代码片段。
1700441250
1700441251 我们知道,一个类至少有一个构造函数(如果没有,编译器会无私地为其创建一个无参构造函数),构造函数是在对象生成时调用的,那现在的问题来了:构造函数和构造代码块是什么关系?构造代码块是在什么时候执行的?在回答这个问题之前,我们先来看看编译器是如何处理构造代码块的,看如下代码:
1700441252
1700441253 public class Client{
1700441254
1700441255 {
1700441256
1700441257 //构造代码块
1700441258
1700441259 System.out.println(“执行构造代码块”);
1700441260
1700441261 }
1700441262
1700441263 public Client(){
1700441264
1700441265 System.out.println(“执行无参构造”);
[ 上一页 ]  [ :1.700441216e+09 ]  [ 下一页 ]