深入探究Java中的对象类型变量声明操作——在声明对象时,系统究竟做了什么?
深入探究Java中的对象类型变量声明操作——在声明对象时,系统究竟做了什么?
摘要:本文主要对Java中的对象类型变量的声明的底层原理做了探究。
我们但凡是学过Java的,一定都知道Java中的对象类型变量的声明方式,那就是:类名 变量名 = new 类名()。不管这样说对不对,我们在这样写的时候,一定都是这样写的。比如我们写了一个Person类,在声明变量的时候,就要这样写:
Person liMing = new Person();
我们并不会深入的去思考为什么这么写,这个语句中的主角是什么,这些问题我们都没有仔细去想过,因此在这里,我详细探讨这个问题,解决你心中的疑惑。
1.句柄
在之前的学习中,我们实际上已经探究了句柄的原理,在这里我们再巩固一下。句柄就是我们常说的变量的变量名,一个变量是由变量名和值构成的,对于我们来说,变量的名字就是变量名,对于计算机来说,变量的变量名部分被称为句柄。我们在声明变量之后,变量就会在被声明的位置存储起来,如类的属性变量,就会被存储到位于堆内存中的对象实例中去,而方法中的变量,会在方法被调用的时候,运行到变量声明的地方在相应的栈空间上创建,变量被创建之后,虚拟机就可以根据句柄进行值的寻找了,当我们在变量创建之后调用变量,虚拟机就可以根据变量名来寻找句柄,并找到句柄后边的值进行取值,进而进行运算,正因如此,Java中的句柄和值是相邻的,而相对应的,在进行一个变量声明赋值的时候,等号左边的变量名就是句柄,右边的则是值。
对于这个概念,我们在使用基本类型变量时非常好理解,对于基本类型变量的声明方式我们也很容易理解了,如下:
int a = 10;
首先是声明类型为整形,句柄为a,这就引起了一个操作:先在栈空间上开辟了一个空间存放句柄,然后句柄的后边就是一块连续的32位大小的空间,这个空间就是变量a的值空间。而等号操作就会导致等号右边的值:10被放到值空间中。这样一个基本类型变量就声明好了,那么一个对象类型的变量是如何声明的呢?
2.对象类型变量的声明
在对象类型变量的声明中,主角实际上是new,new关键字是这之中最为关键的东西。new是一个关键词,但是它实际上代表着一系列操作的执行,它属于一个操作开关,虚拟机一旦检测到new,就会执行一系列的操作。
Person liMing = new Person();
在这个声明赋值之中,最前边的Person实际上是变量类型声明,它在整个操作的过程中,起到的作用是类型声明,但它实际上是new总体操作的一个参数,new会根据这个类型声明,使用路径定位的方式,寻找这个类,想要能创建这个类型的变量,就得让new能通过Person这个字符串,顺着路径能够找到它的类信息,我们如何让new通过路径找到它呢?实际上我们在Java中书写的import导入路径,就是在帮助new寻址,new的寻址能力并不特别行,它只能在当前程序所在的包下直接寻找,如果要是想寻找更多的东西,就要为程序加地址索引,也就是最上边的import,new会遍历它们并按照它们的路径寻找。
当new寻找到相应的类信息后,就会检测这个类是否被初始化过,简而言之,就是检查这个类是否生成过对象,如果没有,就会对它进行forname()方法,这个方法是反射中的方法,使用这个方法可以获取这个类的所有信息,拥有类的所有信息之后,就可以通过它们来生成实例了。
在初始化或者类被初始化过之后,就可以拿到类信息在堆空间中创建这个类的实例了,new会创建好这个实例,至此,对象实体的创建就完成了,然而对我们程序员来说,它没有真正的完成,因为它只是存在了,我们还没拿到它,因此new操作在最后会返回一个地址,这个地址通过等号的赋值功能被放在liMing句柄的后边,然而事情没那么简单,它还有一个操作。new的最后一个参数,便是神奇的构造器,在new后边书写,构造器会在new的所有操作完成前执行,构造器的作用并不是构造,构造是new的操作,我们更喜欢将构造器称之为init()方法,即初始化方法,在Java中也有类似的方法。构造器干的事情是在new返回地址之前对对象进行一些初始化操作,具体怎么初始化其实是我们自己定的,我们会在构造器中写自己想要进行的操作,比如给哪个属性赋值什么的,构造器就会在返回地址之前进行这些操作,在构造器完成之后,地址被返回给句柄,至此,我们就可以使用这个变量了。
3.重点
构造器并不是构造对象的,new才是,构造器只是在初始化对象,最重要的操作是new关键字引起的操作,new实际上是一种简写机制,使用了封装思想,就是使用new关键字来代表一系列的操作执行,这个操作由虚拟机执行,我们只要写一个简单的new就行了,这是一种人性化的设计方式,最前边的类名是类型声明,也是一个参数,new中的操作会拿着这个参数进行类信息的寻找,如果找不到就会报错,在new内部还涉及了部分反射的知识,关于这里的研究我认为非常重要,以后还需继续深入学习。
本文参考了两篇不错的博文,在此给出链接:
Java中new一个对象是一个怎样的过程?JVM中发生了什么? - 额是无名小卒儿 - 博客园 (cnblogs.com)
Java new关键字的对象内存分配原理 - naray - 博客园 (cnblogs.com)
深入探究Java中的对象类型变量声明操作——在声明对象时,系统究竟做了什么?的更多相关文章
- 初步探究java中程序退出、GC垃圾回收时,socket tcp连接的行为
初步探究java中程序退出.GC垃圾回收时,socket tcp连接的行为 今天在项目开发中需要用到socket tcp连接相关(作为tcp客户端),在思考中发觉需要理清socket主动.被动关闭时发 ...
- 探究Java中的引用
探究Java中的四种引用 从JDK1.2版本开始,Java把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用.本篇就来详细探究 ...
- java中,方法可以访问他的类对象的任何私有特性
java中,方法可以访问他的类对象的任何私有特性 读一本书(Core Java for the Impatient)时,发现这个注意,以前的时候没有在意,今天仔细想想发现记忆不深刻.记录一下 下面代码 ...
- Java从入门到精通——数据库篇之JAVA中的对Oracle数据库操作
在Java中对Oracle数据库的操作分为两种:一.查询.二.非查询. 下面是我对其进行总结: 一.查询数据 /** * 根据用户代码查询 * @param userId * @return 如果存在 ...
- Java 中是如何支持正则表达式操作的?
Java 中的 String 类提供了支持正则表达式操作的方法,包括:matches(). replaceAll().replaceFirst().split().此外,Java 中可以用 Patte ...
- 第69节:Java中数据库的多表操作
第69节:Java中数据库的多表操作 前言 学习数据库的多表操作,去电商行业做项目吧!!! 达叔,理工男,简书作者&全栈工程师,感性理性兼备的写作者,个人独立开发者,我相信你也可以!阅读他的文 ...
- 探究Java中的锁
一.锁的作用和比较 1.Lock接口及其类图 Lock接口:是Java提供的用来控制多个线程访问共享资源的方式. ReentrantLock:Lock的实现类,提供了可重入的加锁语义 ReadWrit ...
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
一.Java的反射机制 每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图: 其中
- 探究Java中Map类
Map以按键/数值对的形式存储数据,和数组非常相似,在数组中存在的索引,它们本身也是对象. Map的接口 Map---实现Map Map.Entry--Map的内部 ...
随机推荐
- 【多线程那些事儿】如何使用C++写一个线程安全的单例模式?
如何写一个线程安全的单例模式? 单例模式的简单实现 单例模式大概是流传最为广泛的设计模式之一了.一份简单的实现代码大概是下面这个样子的: class singleton { public: stati ...
- 通过刷题HTML遇到的问题
通过刷题HTML遇到的问题 1.有关选择器的权重问题 1.通配符选择器和继承:权重为0, 2.标签选择器:权重为0001 3.类选择器:权重为0010 4.id选择器:权重为0100 5.行内样式:权 ...
- win10桌面右键卡顿卡死解决方法
win+R,打开命令行 输入services.msc 找到NADIA Display Container LS,将其由自动改为禁用,解决问题. PS:网上有些改注册表的方法,确实可以治标,但是大家都应 ...
- 第二阶段:高级核心基础知识·第1章Linux三剑客·1
1.用vmware添加一块10G的硬盘,且永久挂载到/data01中,写出详细的步骤 2.用自己语言描述raid0和raid1的区别 RAID 0: 将两个或以上相同信号,容量的硬盘组合,磁盘阵列的总 ...
- 【单元测试】Junit 4(二)--eclipse配置Junit+Junit基础注解
1.0 前言 前面我们介绍了白盒测试方法,后面我们来介绍一下Junit 4,使用的是eclipse(用IDEA的小伙伴可以撤了) 1.1 配置Junit 4 1.1.1 安装包 我们需要三个jar ...
- Nginx负载均衡策略的介绍与调优
工作中经常会用到nginx负载均衡这一块,下面对nginx负载均衡策略做个总结.本人在工作中最常用到的负载均衡策略是轮询策略. 在一般情况下,Web中间件最大的作用就是负责对请求进行分发,也就是我们常 ...
- Linux 挂载Windows共享文件夹和NAS存储
summary: [Linux 挂载共享存储] 概述 将Windows共享文件夹和NAS存储挂载至Linux. Linux系统环境:CentOS 挂载共享存储 查看外部主机共享了哪些目录 smbcli ...
- kotlin的suspend对比csharp的async&await
协程的出现大大降低了异步编程的复杂度,可以让我们像写同步代码一样去写异步代码,如果没有它,那么很多异步的代码都是需要靠回调函数来一层层嵌套,这个在我之前的一篇有介绍 rxjava回调地狱-kotlin ...
- C ++:树
C++:树 树的概念: 所谓"树"是输就结构的一种,树大概可以分为两大类: 有根树 和 无根树 有根树使有一个确定的根节点,反之为无根树 · 子节点:从树根开始,通过树边向下扩展的 ...
- DRF认证流程及源码分析
认证 前言 用户验证用户是否合法登陆. 部分内容在DRF视图的使用及源码流程分析讲解,建议先看讲解视图的这篇文章. 使用流程 认证使用的方法流程如下: 自定义认证类,继承BaseAuthenticat ...