面试官:在 Java 中 new 一个对象的流程是怎样的?彻底被问懵了。。(2)

简介: 面试官:在 Java 中 new 一个对象的流程是怎样的?彻底被问懵了。。

首先搞清楚 newInstance 两种方法区别:


Class.newInstance()只能够调用无参的构造函数,即默认的构造函数,我们在Class源码里也看到了其实最终还是调用了无参构造器对象 Constructor 的 newInstance 方法,举个栗子:Dog.class 中是没有无参构造方法,那么会直接抛出 InstantiationException 异常:


//Dog类中只有一个dog_name的有参构造方法
Class c = Class.forName("com.service.ClassAnalysis.Dog");
Dog dog = (Dog) c.newInstance();//直接抛InstantiationException异常


image.png



Constructor.newInstance()可以根据传入的参数,调用任意构造构造函数,也可以反射私有构造器(了解就行)


//Dog类中只有一个dog_name的有参构造方法

Constructor cs = Dog.class.getConstructor(String.class);

Dog dog = (Dog) cs.newInstance("小黑");//执行没有问题



但是这里面的 newInstance跟我们这次要说的 new 方法存在区别,两者创建对象的方式不同,创建条件也不同:


使用 newInstance 时必须要保证这类已经加载并且已经建立连接,就是已经被类记载器加载完毕,而 new 不需要

class对象的 newInstance 方法只能用无参构造,上面已经提到了,而 new 不需要

前者使用的是类加载机制,是一种方法,后者是创建一个新类,一种关键字

这个不能说newInstance 不方便,相反它在反射、工厂设计模式、代理中发挥了重要作用,后续我也会写下代理和反射,因为理解起来确实有点绕。还有一点需要注意,不管以哪种方式创建对象,对应的Class对象都是同一个


Dog dog1 = new Dog("旺财");
Dog dog2 = new Dog("小黑");
Class c = Class.forName("com.service.classload.Dog");//为了测试,加了无参构造
Dog dog3 = (Dog) c.newInstance();
System.out.println(dog1.getClass() == dog2.getClass());
System.out.println(dog1.getClass() == dog3.getClass());

image.png




连接和初始化

在此阶段首先为静态static变量内存中分配存储空间,设立初始值(还未被初始化)比如:


public static int i = 666;//被类加载器加载到内存时会执行,赋予一个初始值

public static Integer ii = new Integer(666);//也被赋值一个初始值


但请注意,实际上i 的初始值是0,不是666,其他基本数据类型比如boolean的初始值就是false,以此类推。如果是引用类型的成员变量 ii 那么初始值就是null。


Dog dog = new Dog("旺财");//在这里打个断点

执行,首先会执行静态成员变量初始化,默认值是0:


image.png


但有例外,如果加上了 final 修饰词那么初始值就是设定的值。


image.png


接着对已经分配存储空间的静态变量真正赋值,比如为上面的dog_max_age 赋值16,还有执行静态代码块,也就是类似下面的代码:


static {

   System.out.println("狗狗的静态代码块");

}



到这为止,类的加载过程才算完成。


创建实例

在加载类完毕后,对象的所需大小根据类信息就可以确认了,具体创建的步骤如下:


先给对象分配内存(包括本类和父类的所有实例变量,不包括上面的静态变量),并设置默认值,如果有引用对象那么会在栈内存中申请一个空间用来指向的实际对象。

执行初始化代码实例化,先初始化父类再初始化子类,赋予给定值(尊重长辈是java的传统美德)

对象实例化完毕后如果存在引用对象的话还需要把第一步的栈对象指向到堆内存中的实际对象,这样一个真正可用的对象才被创建出来。

说了这么多估计很多人都没概念,懵逼状态中,其实很简单,我们只要记住new的创建对象就两步:初始化和实例化,再给你们搞一张图:可以简单理解②③④为初始化⑤实例化(可恶,我这该死的责任感!)


image.png


本文不指望你能使劲弄懂java虚拟机底层加载创建对象的过程(其实有些步骤我都懒得讲了,因为说出来也都非常理论化,没多大意思),是想让你知道对象的诞生过程有哪几个重要概念参与了,弄懂这些概念比起单单知道对象创建的过程有意义的多:


类加载器,可以找找网上的资料,蛮多的,这块内容做个了解就行

Class类和Class对象的概念,请重点掌握,不然理解反射和动态代理很费劲,spring的源码也会难以理解

栈内存和堆内存以及对应的基本类型和引用类型,也很重要,争取能基本理解

来源:blog.csdn.net/qq_16887951/article/details/115872678



相关文章
|
18天前
|
算法 测试技术 持续交付
面试的流程,面试的重点
本文介绍了面试流程及各轮面试的重点。通常面试为1-5轮,首轮关注技术实力与项目经验,次轮深入考察技术细节,第三轮侧重项目协调、创新及价值观等软性问题,如职业规划和沟通能力。面试题分为开放型(如项目经验、解决问题思路)和非开放型(如技术细节、手撕算法),需提前准备。测试类问题涉及自动化测试、持续集成等实际应用。
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
98 2
|
3天前
|
Java
java代码优化:判断内聚到实体对象中和构造上下文对象传递参数
通过两个常见的java后端实例场景探讨代码优化,代码不是优化出来的,而是设计出来的,我们永远不可能有专门的时间去做代码优化,优化和设计在平时
22 15
|
1天前
|
监控 Dubbo Java
Java Dubbo 面试题
Java Dubbo相关基础面试题
|
1天前
|
SQL Java 数据库连接
Java MyBatis 面试题
Java MyBatis相关基础面试题
|
1天前
|
存储 监控 算法
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题
|
1天前
|
安全 架构师 Java
Java大厂面试高频:Collection 和 Collections 到底咋回答?
Java中的`Collection`和`Collections`是两个容易混淆的概念。`Collection`是集合框架的根接口,定义了集合的基本操作方法,如添加、删除等;而`Collections`是一个工具类,提供了操作集合的静态方法,如排序、查找、同步化等。简单来说,`Collection`关注数据结构,`Collections`则提供功能增强。通过小王的面试经历,我们可以更好地理解这两者的区别及其在实际开发中的应用。希望这篇文章能帮助你掌握这个经典面试题。
16 4
|
1天前
|
SQL 监控 druid
Java Druid 面试题
Java Druid 连接池相关基础面试题
|
1天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
22天前
|
Java
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
今日分享的主题是如何区分&和&&的区别,提高自身面试的能力。主要分为以下四部分。 1、自我面试经历 2、&amp和&amp&amp的不同之处 3、&对&&的不同用回答逻辑解释 4、彩蛋