返回信息流既然对于类无论如何java的默认初始化都会在构造器调用之前进行,那为什么还要设计构造器来确保初始化,或者既然要调用构造器来确保对象得到合理的初始化,那为什么系统还要给默认初始化。小白,求教
通过『我邮2.0』发布
这是一条镜像帖。来源:北邮人论坛 / java / #52488同步于 2016/8/18
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
java初始化疑问
cjby
2016/8/18镜像同步22 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
你指的是类的成员变量的默认的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芯片不能解决的,如果不行就两枚。)
总之,时代变了。编程语言比原来更安全,也不奇怪。
[ema17][ema17][ema17]
【 在 nuanyangyang 的大作中提到: 】
: 你指的是类的成员变量的默认的0值吗?比如0,0.0,null?
:
: 这个问题不简单。
从横向和纵解答了我的疑问,完美。。大赞暖神
【 在 nuanyangyang (暖羊羊) 的大作中提到: 】
: 你指的是类的成员变量的默认的0值吗?比如0,0.0,null?
: 这个问题不简单。
: 编程语言设计大概有两种不同的流派:
: ...................
通过『我邮2.0』发布
小白怎么觉的这个问题就有问题呢?调用构造器不是为了确保初始化吧。比如三个成员变量,定义有一个参数的构造函数,怎么确保初始化呢?
通过『我邮2.0』发布