当前位置: 首页 > news >正文

Java类与对象初始化的过程(一道经典的面试题)

本文不再以ClassLoader的视角解释这些问题。

首先,Java代码有个特点,就是成员变量可以在前面的方法中使用,在后面定义。这一特性,很多人说Java了不起,可是为什么呢?Java为何能够这样呢?

我们首先来看一道面试题: 

写出上面代码的运行结果。
其实对于Java了解比较深入的人,不屑于解决这道题,因为看代码写运行结果,再常规不过,可是这个题,要是写准了,还真的不容易,因为,我们要以类似C语言的视角审视这道题。
OK,我们首先理解一个基本概念,内存空间一定是先申请,再初始化,再使用的。例如C语言中的malloc分配空间,然后初始化写0,然后使用。其实Java也是如此的。
首先,我们从main方法入手,只有一行new对象(第26行)。
new对象首先要加载类,这是肯定的了,因此“Test”需要加载类,也就是加载Test的字节码文件到方法区(永久代)中。这时需要把类中的“static”部分处理完成。
也就是说,static部分是随着Test的字节码文件进入到永久代的。
它的过程是:先把所有的static部分申请空间,然后再给每一个static成员由上至下分配初始值。初始值有两种,一种是Java对于基本数据类型的默认初始值,这个默认初始值在申请空间之时就给每一个成员赋予了,另一种是Java程序员利用“=”对成员进行赋初始值。
如图所示,五个静态成员在永久代首先被分配内存。
此时,k=0,t1=null,t2=null,i=0,n=0。空间申请完成之后,我们把0赋值给k,虽然k被分配内存之后就是0,但是依然还要把0再赋值给k,因为“=”右边的“0”是程序员对k的赋值。然后是给t1实例一个对象,也就是t1原本是null,现在把new出来的对象赋值给t1,于是就要构建一个Test对象。构建对象时,要把所有的非static部分初始化一份,放入堆内存。
这时,你就理解了Java语法中,为什么静态成员是“类名.成员”,而非静态成员是“对象.成员”了。因为所属关系不同。
那么我们开始找非静态的成员
如图,有j和一个构造块。
因此是先给j申请空间,然后运行print("j")方法,把方法的返回值交给j。
于是,这个程序的第一段打印结果出来了:
打印:
此后,k=1 , n=1 , i=1。
然后是接着找非静态的部分,就只有构造块了,因此是:
此后,k=2 , n=2 , i=2。
这时,我们构造对象的准备工作做完了,也就是非静态的代码都执行完了,因此开始实例化对象,Java实例化对象使用构造方法,因此执行:
打印:
此后,t1不再是null,然后初始化t2,过程和t1一样,因此运行结果是:
再然后初始化静态的i,因此是执行:
输出打印:
然后初始化 n(第6行),直接把n赋值为99。但是什么都不打印。
然后再往下是静态块:
输出打印:
至此,所有的静态部分也都初始化完毕了,可以new Test("init")了:
输出打印:
所以总体打印如下:
总结,其实Java本身也是代码从上往下走的,只不过静态部分和非静态部分在两个次元里。Java的成员有分配空间,赋默认值两个过程,且首先为全体成员申请空间,然后由上至下逐一赋值。

转载于:https://www.cnblogs.com/atom-wangzh/p/8718323.html

相关文章:

  • EF架构~性能高效的批量操作(Insert篇)
  • user-agent 验证移动端请求
  • python用zipfile模块打包文件或是目录、解压zip文件实例
  • 模块化(学习笔记)
  • HDU 4048 Zhuge Liang's Stone Sentinel Maze [组合数学+Burnside]
  • swap file *.swp already exists问题解决!!!
  • [G-CS-MR.PS02] 機巧之形2: Ruler Circle
  • Eclipse开发环境配置,打磨Eclipse,安装插件(适用3.4,3.5,3.6,3.7)
  • 八、Maven下进行单元测试
  • Java反编译利器-Jad, Jode, Java Decompiler等及其IDE插件
  • 在阿里云创建子域名,配置nginx,使用pm2部署node项目到ubuntu服务器
  • 求数组中只出现一次的数字(算法)
  • 黄聪:公众号怎么用微信做出点击此处查看答案
  • 远程调用
  • Kinect+OpenNI学习笔记之12(简单手势所表示的数字的识别)
  • php的引用
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • Java 多线程编程之:notify 和 wait 用法
  • Javascript 原型链
  • java中的hashCode
  • Python语法速览与机器学习开发环境搭建
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 复杂数据处理
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 理解在java “”i=i++;”所发生的事情
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 前嗅ForeSpider采集配置界面介绍
  • 浅谈Golang中select的用法
  • 嵌入式文件系统
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 使用docker-compose进行多节点部署
  • 王永庆:技术创新改变教育未来
  • 无服务器化是企业 IT 架构的未来吗?
  • 译自由幺半群
  • 怎样选择前端框架
  • RDS-Mysql 物理备份恢复到本地数据库上
  • ​2021半年盘点,不想你错过的重磅新书
  • ​MySQL主从复制一致性检测
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (论文阅读30/100)Convolutional Pose Machines
  • (三) diretfbrc详解
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转) 深度模型优化性能 调参
  • (转)mysql使用Navicat 导出和导入数据库
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .net 调用php,php 调用.net com组件 --
  • .NET 设计一套高性能的弱事件机制
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .net项目IIS、VS 附加进程调试
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d
  • @Bean注解详解