在OOP语言中,都会有构造方法这个概念,它的主要作用就是用于创建一个类的实例,并为这个实例的成员变量赋值。虽然它是一个好像很简单的东西,但是好像还有很多人对它的理解还不是很透彻,往往在面试中就会搞一些比较2B的题目来考大家。
写这个主题主要是因为在自己的代码中出现了问题,在XStream中,它在实例化的时候是不会调用类的默认方法的,后面自己去跟了一下XStream的源码才发现,它是用了Unsafe中的allocateInstance方法来实例化的,而这个方法是不会去调用构造方法的,导致了Map cache = new HashMap();这个cache成员变量没有被赋值,最后用的时候就出现了NullPointerExption。
我猜这XStream是肯定没有调用类的默认构造方法,不然不可能会null的,结果就跟其他两个同事讨论起构造方法的事来,他们都说成员变量的赋值都是在构造方法之前执行的,而我说成员变量的初始化是在构造方法里面执行的。在论证这个之前,我们先来看一个比较误导人的命题:“当一个类没有定义任何构造方法时,编译器会生成一个什么都不做的默认构造方法”,我拿这个问题问了以前的同事,他竟然说这是对的,这段话好像在很多教材里面都会出现。这句话里的一半是对的,至于哪里错了,我们就要用事实来说话了。
先上一段简单的代码:
public class Test { int a = 100; }
这段代码只有简单的三行代码,但是却已经可以证明上面那句话的问题了。首先这个类里面是没有任何构造方法的,为了证明上面那句话是有一半错误的,我们需要看编译器为我们生成了些什么东西。在这里我们需要用到javap命令,这个命令能为我们的class文件转成对应的字节码指令。
在这里我们看到,编译器确实帮我们生成了一个默认的构造方法,但是它是什么都不做的默认构造方法么?明显不是,生成好几行的字节码指令。那么,我们现在来看一下这些生成的字节码指令都做了些什么事,首先会将this压入栈中,接着调用父类的构造方法,最后为成员变量赋值。现在我们就可以得出两个结论了:1、编译器为我们生成的默认构造方法并不是什么都不做的”懒人“;2、类中的成员变量的赋值是放到构造方法中去的,而并不是在构造方法之前执行的。相当于生成了以下的代码:
public class Test { int a; Test() { super(); // 首先去调用父类的构造方法 a = 100; // 为成员变量赋值 } }
再来看一下构造方法里面的代码和成员变量赋值的顺序,再来一段简单的代码:
public class Test { int a = 100; int b = 200; Test() { int e = 300; int f = 400; } int c = 500; int d = 600; }
看了这段简单的代码后,大家先花几秒钟的时间来猜一下它们的执行顺序是怎么样的
国际惯例,我们用javap命令来看一下它生成的字节码指令(javap真是一个好用的东西啊,哈哈)
看了这图之后,相信大家都已经知道答案了吧。相当于生成了以下的代码:
public class Test { int a; int b; Test() { a = 100; b = 200; c = 500; d = 600; int e = 300; int f = 400; } int c; int d; }
哈哈,我就不多费口舌了。希望这篇博客能帮到大家。
相关推荐
下面详细解析Java构造方法的特性和使用方法。 构造方法的特性: 1. 方法名与类名相同:构造方法的名字必须与类名完全相同,这是Java语法规定的一部分,便于编译器识别并自动调用构造方法。 2. 构造方法无返回类型:...
Java 中构造方法的深入研究与探讨 本文探讨了 Java 中构造方法的概念、特点和应用,通过对构造方法的深入研究和探讨,阐述了其在继承和设计模式中的重要作用。 知识点一:构造方法的概念和特点 构造方法是 Java ...
在IT行业中,构造方法是面向对象编程中的一个关键概念,特别是在Java、C#等语言中。这个概念对于理解和实现类的实例化至关重要。"论构造方法的方法论.zip"的文件标题暗示了这是一个深入探讨构造方法设计策略的资源,...
Java语言是一种面向对象的编程语言,在面向对象编程中,对象的创建是通过构造方法来实现的。构造方法是一种特殊的成员方法,它的名称与类名完全相同,并且没有返回值类型,连void都没有。构造方法在对象实例化的过程...
Java编程方法论中,Spring Reactor、Reactor-Netty和Spring Webflux是现代Java开发中用于构建反应式应用程序的关键组件。Spring Reactor是响应式流(Reactive Streams)规范的实现,它提供了用于处理异步事件和数据...
3. 文档中提出了一种基于UML关系的Java代码库构造方法。这种方法的核心在于使用图数据库作为实现平台,并以抽象语法树(AST)为基础来构建图结构。 二、图数据库与抽象语法树 1. 图数据库是一种特殊的数据库,它...
本资源"一种基于UML关系的Java代码库构造方法"探讨了如何利用UML的关系来指导Java代码的生成,从而构建高效、结构化的代码库。以下是对这个主题的详细解释: 1. **UML简介**:UML是面向对象设计的一种标准化语言,...
`AnimateDelete`类提供了几个构造函数,用于根据不同的情况初始化消除路径。例如,`AnimateDelete(int direct, Point a, Point b)`用于处理两个点之间的直线消除,`AnimateDelete(int direct, Point a, Point b, ...
### 论C#与Java之异同 #### 引言 Dare Obasanjo撰写的这篇详尽且精准的文章——《论C#与Java之异同》首次发布于2001年,随着时间的推移,它已经成为了一个比较这两门语言的权威资料。基于C# 2.0和Java SE 6的新...
Java课程设计是一个重要的实践环节,它旨在让学生深入理解Java编程语言的原理,提高编程技能,并锻炼问题解决能力。这份资源包含完整的源代码、源程序和论文,为学习者提供了全面的学习材料,可以从多个角度深入了解...
### 论JAVA继承机制中父类与子类的关系 #### 摘要 本文深入探讨了Java语言中的继承机制,并重点分析了父类与子类之间的关系。文章围绕子类继承父类成员的过程、成员变量及方法的赋值、重写、覆盖等问题展开讨论,...
【语义网、Java、范畴论】在计算机科学中,特别是Java编程语言的面向对象设计中,范畴论的概念被用来理解和构建复杂的抽象概念。范畴论是一种数学理论,它抽象出数学对象之间的关系,形成一种通用的语言,使得不同...
在构造Java Swing组件时,经常使用参数的构造方法来完成。为了实现代码的封装和重用,可以通过继承相关的类来构建组件。例如,下拉列表框(ComboBox)和列表框(ListBox)是Swing中的常见组件,它们都具有多个构造...
通过"Java初学者习题20道.doc",你可以深入实践这些方法的运用。 5. **面向对象编程** Java是面向对象的语言,因此封装、继承和多态是其核心特性。习题中可能包含创建类、对象,理解构造器,以及实现继承和接口的...
Java提供了多种方式来创建字符串,例如使用字符串字面量、使用String类的构造方法等。Java也提供了多种方式来比较字符串,例如使用equals()方法、compareTo()方法等。 Java中的字符串替换可以使用replaceAll()方法...
如果没有在子类中显式地调用super(),Java虚拟机会默认调用父类的无参构造方法。如果父类中没有无参构造方法,子类的构造方法中必须显式调用带参的父类构造方法。 本文档通过分析this与super关键字的基本用法,明确...
开发者可以通过调用`ServerSocket(int port)`构造方法来创建一个监听特定端口的服务器,然后使用`accept()`方法等待并接受客户端的连接。这是一个被动的过程,因为服务器等待客户端的主动连接。 远程端口扫描则涉及...
构造方法重载是重载的一种特殊情况,指的是在一个类中可以有多个构造方法,每个构造方法可以接受不同类型的参数,这样就可以根据不同的需求初始化对象。构造方法重载可以提供更加灵活的实例化机制,满足不同的初始化...
一个常见的构造方法是Window(Frame owner),它允许你创建一个新的窗口,并将一个已存在的Frame对象作为它的所有者。如果当前没有指定所有者,或者所有者已经隐藏或关闭,则此方法会抛出一个IllegalArgumentException...