BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #52488同步于 2016/8/18
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

java初始化疑问

cjby
2016/8/18镜像同步22 回复
既然对于类无论如何java的默认初始化都会在构造器调用之前进行,那为什么还要设计构造器来确保初始化,或者既然要调用构造器来确保对象得到合理的初始化,那为什么系统还要给默认初始化。小白,求教 通过『我邮2.0』发布
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
nuanyangyang机器人#1 · 2016/8/18
你指的是类的成员变量的默认的0值吗?比如0,0.0,null? 这个问题不简单。 编程语言设计大概有两种不同的流派: 1. 充分信任程序员。程序员犯一点点错误,都是灾难性的后果。 2. 不信任程序员。提供很多“防护网”,即使程序写得不完全正确,也不至于太坏。 显然,C语言属于第一种:C语言里,除了静态变量(含全局变量)自动初始化为0以外,局部变量和new出来的堆内存,都没有初始值。在没有赋值之前读取值,是“未定义行为”,注意,不是“读到随机的值”,而是什么都允许发生,从什么都不发生到机器冒烟都可以发生。同样的,数组越界、NULL指针访问、除0错误,都是“未定义行为”。 但Java属于第二种:Java里没有未定义行为。错误的动作都会有固定的错误结果。比如,类成员自动初始化为0或者null;局部变量未赋值而先读取,是编译错误;数组越界抛ArrayIndexOutOfBoundException,null访问抛NullPointerException,除0错误抛ArithmeticException。 早期的编程语言偏向于第一种。原因是检查错误或者防止错误是有代价的,比如自动初始化为0、数组越界检查、指针访问检查null等。早期计算资源非常宝贵,代码量也很重要,估计负担不起这么多的检查。还有一个原因,人们对一些基本操作的结果还没有共识,比如float和double各有多长(IEEE754是个新事物),除以0到底发生什么(到今天,还有处理器在除以0的时候返回0,-2147483648/-1==-1,而不是抛硬件异常)。所以,C语言这样的语言不愿意做太多限制,想让各个平台自由发挥,于是就有了这么多的“未定义行为”。 但摩登的编程语言在越来越向后者靠拢。原因很多: 1. 人们逐渐意识到,程序规模越大,查错越重要。而且,出错的时候能够快速定位错误,对修正bug也非常重要。最近Mozilla在Firefox里开始使用Rust语言的组件。目前用于了媒体元数据解码器。因为元数据解析经常被黑客用来作为攻击对象,如果C++程序里有数组越界错误的话,很可能这个错误会安静地溜走,或者造成缓冲区溢出,使得黑客在用户的机器上执行任意代码。但rust从设计上就是一个安全的语言,通过很多安全机制(包括运行时的检查)来避免数组越界错误。 2. 优化编译器可以省略很多不必要的检查。比如数组越界。如果编译器可以证明访问数组的时候下标肯定不会越界(通过循环的界限可以分析出来),那么就可以把边界检查省略掉。 3. 很多高级的语言、虚拟机实现策略使得这些安全机制的代价很低。 比如,null错误的检查,可以用page protection来完成:null一般用0地址来表示。如果把0地址所在的页保护起来(其实装载的进程的时候一般根本不会映射这块地址),试图读取0地址,就会抛出硬件异常。通过操作系统的信号处理(一般是segmentation fault),运行环境(虚拟机)可以将控制流转移到Java语言的异常处理(catch)部分,就好像抛出了一个NullPointerException异常一样。 又如,初始化0。初始化其实很便宜。在有垃圾回收的语言里,可以大批量地整页整页地清零。为了对cache友好,可以使用cpu提供的non-temporal write指令(比如x86的MOVNTDQA),这样就不影响普通程序的cache命中率。现在多核CPU越来越流行,可以把垃圾回收在另一个核上并行地做。这样即使是单线程的Java应用程序,在多核CPU上也会跑得快。近年来流行了“非对称”的多核,比如ARM的big.LITTLE构架(中国最近开发的“神威·太湖之光”用的CPU也是这种非对称的多核构架),由少量“高串行性能、高耗电量”的大核和大量“低耗电量、计算能力稍差”的小核组成。如果有这种构架,可以把“垃圾回收+清零”的工作放在小核上,毕竟对这个工作来说,内存才是瓶颈。这样,在单位能源的条件下可以带来更高的性能。(这样理解:只要有钱,只要有电池,只要能散热,现在你要多少核就能有多少核,集成电路上要多少元件就能放多少元件。现在不像80年代,门的数量已经不是问题了。但散热是问题,耗电量是问题,成本也是问题。如果能够提高能源效率,花同样的钱、耗同样的电、散同样的热,就能往芯片上放更多的计算单元。没有什么问题是一枚Shenwei芯片不能解决的,如果不行就两枚。) 总之,时代变了。编程语言比原来更安全,也不奇怪。
dss886机器人#2 · 2016/8/18
[ema17][ema17][ema17] 【 在 nuanyangyang 的大作中提到: 】 : 你指的是类的成员变量的默认的0值吗?比如0,0.0,null? : : 这个问题不简单。
cjby机器人#3 · 2016/8/18
从横向和纵解答了我的疑问,完美。。大赞暖神 【 在 nuanyangyang (暖羊羊) 的大作中提到: 】 : 你指的是类的成员变量的默认的0值吗?比如0,0.0,null? : 这个问题不简单。 : 编程语言设计大概有两种不同的流派: : ................... 通过『我邮2.0』发布
SCSsong机器人#4 · 2016/8/19
暖神说的很棒。 不过我看到lz叙述还以为lz是在纠结构造器初始化和定义时初始化两种机制是不是冗余。
lxsh0917机器人#5 · 2016/8/19
小白怎么觉的这个问题就有问题呢?调用构造器不是为了确保初始化吧。比如三个成员变量,定义有一个参数的构造函数,怎么确保初始化呢? 通过『我邮2.0』发布
EMyuan机器人#6 · 2016/8/19
暖洋洋头像换了,认不出来了
naxienian机器人#7 · 2016/8/19
膜拜暖神,之前也有过这样的疑问,但没有暖神理解得那么透彻 通过『我邮2.0』发布
TonyFromDire机器人#8 · 2016/8/19
大清早给暖神秀了一脸
DaveSun机器人#9 · 2016/8/19
b d