前几天,有个大佬考了我一个问题:为什么类的成员变量不需要指定值就可以自动赋予初始值,而方法内的局部变量就必须指定初始值呢?

说实话,这个问题确实难倒我了,之后我在网上一顿操作,终于把这个问题弄得稍微明白一点了。

首先我给出一个具体的场景来说明这个事情:

定义一个Cat类,里面有各种属性,包括8大基本数据类型和String类型,我们把String类视为复杂数据类型。Cat类里面有一个setAge方法。我们在main方法里面给tom这个Cat赋值年龄,结果发现,如果给定的年龄没有赋初始值,编译器会报错:

那我们来看下未给Cat里面的各种属性初始化,各项属性的初始值究竟是怎样的:

重写一下toString方法:

然后输出结果为:

我们能够看到,对于8大基本类型的初始化已经实现了,分别是如图所示的值。对于复杂的类,会赋予null作为默认值。(这里char的默认值为'/u0000'也就是null)

那么问题来了,为什么Java会有这样的操作呢,为什么不能将方法内的局部变量也自动赋值一个默认值呢?

首先,我在网上找到了这样的一个答案如下,如果不想看原文,可以直接跳过至引用答案的结尾处直接看我的总结:

这位作者在读《深入理解Java虚拟机》的时候记录了一个相关知识点。

类的成员变量有默认初始值,而方法内的局部变量却没有初始值。这个问题涉及到JVM类加载和字节码执行两个阶段,这两个阶段是依次执行的。

JVM类加载是JVM利用类加载器将class文件加载到JVM的过程,涉及“加载”、“验证”、“”准备“、“”解析“和”初始化“。

一、类的成员变量初始化   ---在JVM类加载阶段完成

类的成员变量又分为静态成员变量和非静态成员变量。

静态成员变量

静态成员变量会被初始化两次,第一次在“准备”阶段,先进行一次初始化,系统附上默认值;第二次在“初始化”阶段,根据代码中的赋值情况再进行一次初始化。

例如:

public static int i =3 ;

第一次初始化后i的值为0,第二次初始化后,值才为3.

数据最终存放在方法区中。

非静态成员变量

仅“初始化”阶段赋值。根据代码中的赋值情况,代码不赋值直接赋默认值,有赋值则等于代码中的赋值。对象实例化后,该变量随java对象分配到java堆中。

二、方法区的局部变量没有初始化

而方法中的局部变量没有初始化步骤,如下图:

需要在代码中进行初始化。

————————————————

原因就是类方法中的代码,实在字节码执行的时候,才会被运行到,此时局部变量是存储在虚拟机栈-栈帧中的局部变量表中。局部变量定义了但是没有赋值是不能使用的。

版权声明:本文为CSDN博主「一步一台阶」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/liufang...

这篇帖子主要是说明了两种变量在JVM编译代码的时候把他们放在了哪里。

JVM加载类的时候,不管是静态类还是非静态类,都会给每个类分配内存,存在堆里面,都有初始化的这一步操作。

对于方法内的局部变量,由于方法要放到堆栈中(堆栈这个词,其实意义就是栈,习惯称为堆栈,其实和堆没关系),只有字节码执行的时候才会被运行到,所以没有赋值是不能使用的。

………………??? 这是什么意思?也就是说,两种变量的存储位置不一样,会对是否初始化有影响,但是没有说明为什么成员变量在堆里就有初始化,方法内局部变量为啥放在堆栈里面,只有执行方法的时候才会被运行到就不能初始化呢?

然后我就找到另一篇文章如下:

为什么 Java 中全局变量不一定初始化,局部变量必须初始化?

作者:Intopass

链接:https://www.zhihu.com/questio...

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先 Java 语言就是这么规定的。

然后为什么 Java 语言要这么规定呢?有什么内部机理吗?

可能的原因如下,当我们新建一个对象时,Java会在Heap中申请一块内存区域用以存放类的数据。而成员变量就是类的数据,也是放在这块内存区域中的。只需要JVM在申请内存的时候顺便把整块区域都置为零即可完成初始化,方便快捷。

而对于方法的局部变量,是在线程的Stack中,当然Stack他也可以帮我们初始化,不过有一个问题。对于有些局部变量,在方法的一开始是没有的,有些在循环中的局部变量是要反复的声明多次的。有些局部变量作用域结束后,另一个局部变量又会占用这个局部变量的位置。

那么初始化要放在何时呢?当然JVM可以帮我们初始化多次,不过那样或许会带来性能问题。

for (int i = 0; i < 10; i++) {

int n;

if (i % 2 == 0) {

n = 10;

} else {

n = 20;

}

}

像是这个n,我们完全不用JVM帮我们初始化,如果每次循环他都帮我们初始化一次,那么是没有必要的。综上所述,对于局部变量,可能不帮我们初始化是一个不错的选择。(而且JVM实现起来也更容易!!!)

通过看这位作者的讲解,我们就能够理解得更清楚一些了。为什么堆内的成员变量可以初始化?因为容易,申请内存的时候顺便就实现了初始化。为什么栈内的局部变量不能初始化?因为麻烦,而且没有必要。

最后,我又看到了一个内容,同知乎页面另一个匿名作者的回答:

套用《Thinking in Java》作者Bruce Eckel的话

编译器当然可以为局部变量附一个默认值,但是未初始化的局部变量更有可能是程序员的疏忽,所以采用默认值范围会掩盖这种失误。因此强制程序员提供一个初始值,往往能够帮助找出程序里的缺陷。

其实我觉得这句话应该是对于为什么局部变量不能够初始化的最合理的解释了吧。

总结一下,为什么局部变量需要手动初始化?从技术上来讲,局部变量一般来说总量大,生命周期短,JVM进行初始话开销较大;从业务上讲,局部变量一般用于实际问题下的运算,很少会用到默认值,赋值意义不大;从编程思想上讲,局部变量不初始化,而是报错提醒,更有助于程序员减少开发过程中出现缺陷的可能。一举三得,何乐而不为?

回到开头,所以说大佬就是大佬,随随便便问一个问题,看似是一个小问题,但是深究下去竟然牵扯到这么多深层次的知识点,甚至有点哲学的意义在里面,佩服佩服!

java全局变量初始化_为什么 Java 中全局变量不一定初始化,局部变量必须初始化?...相关推荐

  1. java类成员变量初始化_探讨Java类中成员变量的初始化方式

    在 Java 里定义一个类的时候,很多时候我们需要提供成员变量,成员变量专业叫法是 Memeber Variable 或者干脆的叫作 Field. 根据是否使用 static 关键字修饰,可以将 Fi ...

  2. java final 类_在Java中,final修饰的类有什么特点

    展开全部 关于Java中的32313133353236313431303231363533e4b893e5b19e31333264663736final(2010-09-09 14:19:48)转载▼ ...

  3. java编程思想 初始化_《java编程思想》_第五章_初始化与清理

    初始化和清理是涉及安全的两个问题,java中采用了构造器,并额外提供了"垃圾回收器",对于不再使用的内存资源,垃圾回收器能自动将其释放. 一.用构造器确保初始化 java中,通过提 ...

  4. java coin介绍_代码示例中的Java 7:Project Coin

    java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...

  5. java 异常对象_在java中的异常处理中的异常对象是什么

    展开全部 Exception类以及他的子类 的一个实例对象 比如32313133353236313431303231363533e58685e5aeb931333264633563 常见异常 1. j ...

  6. 类加载器 java委托机制_解析Java虚拟机中类的初始化及加载器的父委托机制

    类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有 ...

  7. java单例模式构造器初始化_秒懂java单例模式,java私有构造器与一夫一妻制

    在<秒懂java,对于创建一个java对象,你真的会吗?>一文中,讲述了java如何创建一个对象以及如何更优雅的创建对象.此外,java里还有一种比较特殊的创建对象的方式:私有构造器创建对 ...

  8. java logging包_用JDK中提供的java.util.logging.*包创建Logger对象----原创

    由于项目中用到了Applet与Servlet之间(客户端用Applet.Server端用Servlet)的通信,要求: 1:>客户端与服务端必须出Log. 2:>浏览器在加载Applet时 ...

  9. java jar 目录_将Java类路径中的所有jar包括在一个目录中

    有没有一种方法可以将所有的jar文件包含在类路径的目录中? 我正在尝试java -classpath lib / *.jar :. my.package.Program,它无法找到当然在这些罐子里的类 ...

最新文章

  1. The Shortest Statement CodeForces - 1051F LCA+最短路
  2. 交换机无法ping通之谜
  3. java list 删除 遍历_Java list利用遍历进行删除操作3种方法解析
  4. 音频处理八:(MFCC 的计算)
  5. java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseSelectProvider.<init>()的问题解决
  6. extjs5(05--主界面上加入顶部和底部区域)
  7. LeetCode 427. 建立四叉树(递归)
  8. gdb学习(一)[第二版]
  9. 昇腾AI处理器软件栈--张量加速引擎(TBE)
  10. Odoo链接magento纪实
  11. FR多sheet的内置检验和JS校验, 数据集范围校验;填报存在时不提交并提示已存在
  12. org_chart.js 使用方法
  13. 东莞理工学院计算机学院论文,东莞理工学院本科生毕业设计(论文)重复率检测实施办法(试行)...
  14. 分布式智能微电网的体系结构操作系统
  15. html中车牌号省份简称输入键盘
  16. Unity自学虚拟摇杆
  17. LapSRN 超分辨率
  18. 太阳系行星运转示意图
  19. 为你解说加密Pdf如何导出图片
  20. 一枚中级网络工程师的工作日常,能引起多少同行的共鸣啊。

热门文章

  1. 火狐主页被hao123劫持
  2. 怎么让WORD中多行(常带下划线)头和尾都完全对齐
  3. 苹果手机系统计算机删除怎么恢复出厂设置密码,苹果如何恢复出厂设置?恢复出厂设置教程...
  4. ABP框架-1.1 ABP总体介绍 - 入门介绍
  5. 高端专业运动品牌迪桑特与日本著名潮流设计师正式发布联名系列;安踏打造互动数字空间助力冬奥发声 | 知消...
  6. B+树相比B树的优势
  7. [DappReview]2019 Dapp市场报告
  8. node+vue实现支付宝沙箱测试教程
  9. 01 IO流 RandomAccessFile File
  10. acadres.dll文件丢失怎么办?怎么去修复?