一文了解 Java 中的构造器
摘要:Java 也采用了构造器,并且还提供了一个垃圾收集器(garbage collector),当不再使用内存资源的时候,垃圾收集器会自动将其释放。
本文分享自华为云社区《一文带你了解 Java 中的构造器》,作者: 宇宙之一粟 。
C ++ 引入了构造器(constructor,也叫构造函数)的概念,它是在创建对象时被自动调用的特殊方法。
Java 也采用了构造器,并且还提供了一个垃圾收集器(garbage collector),当不再使用内存资源的时候,垃圾收集器会自动将其释放。
构造器定义
在 Java 中,可以通过编写构造器来确保每个对象的初始化。但是这里有两个问题:
- 这个构造器使用的任何名字都有可能与类里某个成员相冲突;
- 编译器负责调用构造器,所以它必须始终知道应该调用哪个方法。
C++ 语言采用的方案就是将构造器和类的名字定义相同,Java 也采用了这个方案。
构造器的作用是用来建立一个新的类的实例,当一个对象被创建时,JVM 使用一个构造函数,并为其分配内存空间。
语法结构
class ClassName {
ClassName() {
}
}
例如,在下面的示例中,我们创建了一个名为 ReLearnConstructor 的构造函数。在构造函数内部,我们正在初始化 hello 变量的值。:
public class ReLearnConstructor {
String hello; // 属性
// 构造器
public ReLearnConstructor() {
hello = "Hello, Constructor!";
}
public static void main(String[] args) {
ReLearnConstructor rc = new ReLearnConstructor();
System.out.println(rc.hello);
}
}
注意创建 ReLearnConstructor 类的对象的语句:ReLearnConstructor rc = new ReLearnConstructor();
在这里,当创建对象时,调用 ReLearnConstructor 构造函数。并且,hello 变量的值被初始化。
因此打印的 hello 的值为:

构造器目的
构造函数的目的是初始化对象的状态,为所有声明的属性赋值。如果我们没有自定义构造函数,JVM 就会为这些属性分配默认值。
原始类型的默认值:
- 整数类型是 0
- 浮点类型是 0.0
- 布尔类型是 false
对于其他 Java 引用类型,默认值是null,这意味着引用类型的属性没有被分配任何值。

后面可以用代码查看这些默认值。
构造器分类

在 Java 中,有三种类型的构造器:
- 无参构造器
- 有参构造器
- 默认构造器
无参构造器
与方法类似,Java 构造函数可能有参数,也可能没有任何参数。如果构造函数不接受任何参数,则称为无参数构造器。例如上述代码中 ReLearnConstructor 构造器就是:
// 无参构造器
public ReLearnConstructor() {
hello = "Hello, Constructor!";
}
有参构造器
字面理解,具有参数的构造函数称为有参数构造器。那为什么需要使用有参构造器?
有参构造器可用于为不同对象提供不同初始化的值。 例如:
public class ReLearnConstructor {
String languages;
// 接受单个参数的构造器
public ReLearnConstructor(String lang) {
languages = lang;
System.out.println("我在学习 " + languages + " 语言!");
}
public static void main(String[] args) {
// 向构造器中传入不同的值
ReLearnConstructor rc1 = new ReLearnConstructor("Java");
ReLearnConstructor rc2 = new ReLearnConstructor("Go");
ReLearnConstructor rc3 = new ReLearnConstructor("Python");
}
}
运行结果:

默认构造器
如果我们不创建任何构造函数,Java 编译器会在程序执行期间自动创建一个无参数构造函数。这个构造函数称为默认构造函数。来看一个例子;
public class ReLearnConstructor {
String languages;
int a;
boolean b;
float c;
public static void main(String[] args) {
ReLearnConstructor rc = new ReLearnConstructor();
System.out.println("默认值:");
System.out.println("languages:" + rc.languages);
System.out.println("a:" + rc.a);
System.out.println("b:" + rc.b);
System.out.println("c:" + rc.c);
}
}
运行结果:
默认值:
languages:null
a:0
b:false
c:0.0
可以看到,我们还没有创建任何构造函数。因此,Java 编译器会自动创建默认构造函数。上述表格得以印证。
原生方法和构造器的区别
- 构造函数必须与在 Java 中定义的类具有相同的名称
- 当方法没有返回任何值时,构造函数不会返回任何类型,而方法则具有返回类型或 void
- 在对象创建时,仅调用构造函数一次,而方法可以被调用任何次数
如果我们不用构造器来给属性赋值的话,可以先使用 new 运算符获取类的实例,并使用类的 setter 方法设置值,如下:
import java.util.Arrays;
class Person
{
private String name;
private int age;
@Override
public String toString() {
return Arrays.asList(name, String.valueOf(age)).toString();
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
// getters
}
// Initialize an object in Java
class Main
{
public static void main(String[] args)
{
Person person = new Person();
person.setName("Yuzhou1su");
person.setAge(22);
System.out.println(person);
}
}
通过构造器进行初始化就可以省去我们的 setter 方法。
如下的例子:
import java.util.Arrays;
class Person {
private String name;
private int age;
// 构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return Arrays.asList(name, String.valueOf(age)).toString();
}
}
class SimpleConstructor {
public static void main(String[] args) {
Person person = new Person("Yuzhou1su", 22);
System.out.println(person);
}
}
运行结果:
[Yuzhou1su, 22]
构造器重载
与 Java 方法重载类似,我们也可以创建两个或多个具有不同参数的构造函数。这称为构造函数重载。
public class ReLearnConstructor {
String language;
public ReLearnConstructor() {
this.language = "Java";
}
// 构造器
public ReLearnConstructor(String language) {
this.language = language;
}
public void getName() {
System.out.println("编程语言:" + this.language);
}
public static void main(String[] args) {
ReLearnConstructor rc1 = new ReLearnConstructor();
ReLearnConstructor rc2 = new ReLearnConstructor("Python");
rc1.getName();
rc2.getName();
}
}
在上面的例子中,我们有两个构造函数:ReLearnConstructor() 和 ReLearnConstructor(String language)。在这里,两个构造函数都用不同的值初始化变量语言的值。根据创建对象时传递的参数,调用不同的构造函数,分配不同的值。
运行结果:

编程语言:Java
编程语言:Python
拷贝构造器
Java 中的拷贝构造方法是一种使用该类的一个对象构造另外一个对象的构造方法。
复制构造函数是一种特殊构造函数,用于将新对象创建为现有对象的副本。它只需要一个参数,它将是同一类的另一个实例。我们可以使用 this() 语句从复制构造函数中显式调用另一个构造函数:
public class ReLearnConstructor {
private String language;
// 构造器
public ReLearnConstructor(String language) {
this.language = language;
}
// 拷贝构造器
public ReLearnConstructor(ReLearnConstructor rc) {
this.language = rc.language;
}
public void getName() {
System.out.println("编程语言:" + this.language);
}
public static void main(String[] args) {
ReLearnConstructor rc = new ReLearnConstructor("Python");
ReLearnConstructor copyOfrc = new ReLearnConstructor(rc);
rc.getName();
copyOfrc.getName();
}
}
运行结果:
编程语言:Python
编程语言:Python
当需要拷贝一个带有多个成员变量的复杂对象或者想构造已存在对象的深拷贝对象时非常有用。
匿名内部类
除了上文介绍的使用构造器的方法,另一种初始化对象的方法是使用“双大括号初始化”。这将创建一个匿名内部类,其中只有一个实例初始化程序。建议不要使用这种方法。
import java.util.Arrays;
class Person
{
private String name;
private int age;
@Override
public String toString() {
return Arrays.asList(name, String.valueOf(age)).toString();
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
// getters
}
// Initialize an object in Java
class Main
{
public static void main(String[] args)
{
// Anonymous class
Person person = new Person() {{
// Initializer block
setName("Yuzhou1su");
setAge(22);
}};
System.out.println(person);
}
}
总结
- 实例化对象时会隐式调用构造函数。
- 创建构造函数的两条规则是:构造函数的名称应与类相同。Java 构造函数不能有返回类型。
- 如果一个类没有构造函数,Java 编译器会在运行时自动创建一个默认构造函数。默认构造函数使用默认值初始化实例变量。例如 int 变量将被初始化为 0
- 构造函数类型:
- 无参构造器 - 不接受任何参数的构造函数参数化构造函数
- 接受参数的构造器 - 接受参数的构造函数
- 默认构造器 - 如果没有明确定义,Java 编译器会自动创建一个构造函数。
- 构造函数不能被 abstract、static 或 final 修饰
编译器会报如下错误:
Illegal modifier for the constructor in type ReLearnConstructor; only public, protected & private are permitted
- 构造函数可以重载但不能被覆盖
一文了解 Java 中的构造器的更多相关文章
- Java中的构造器与垃圾回收
构造器 在我们初始化对象时,如果希望设置一些默认值,那么就可以使用构造器,在Java中,构造器使用和类同名的名字且没有返回值,如下 class Test{ private String name; T ...
- Java中是构造器创建对象吗?
首先,这里说明” Java中是构造器创建对象 “这句话是完全错误的. Java中构造器的作用主要是为了初始化变量的值...其实在执行构造器之前,Java对象所需要的内存空间,已经产生了... 一般可以 ...
- java中的构造器
构造器是什么 1.构造器,也称构造方法.构造函数.作用是构造出来一个类的实例,确保对象得到初始化. 2.构造器的格式: 权限修饰符 类名(无参/有参){}. 3.根据有无参数,可分为无参构造 和有参构 ...
- 一文解开java中字符串编码的小秘密
目录 简介 Unicode的发展史 Unicode详解 UTF-8 UTF-16 UTF-32 Null-terminated string 和变种UTF-8 简介 在本文中你将了解到Unicode和 ...
- 【Java基本功】一文了解Java中继承、封装、多态的细节
本节主要介绍Java面向对象三大特性:继承 封装 多态,以及其中的原理. 本文会结合虚拟机对引用和对象的不同处理来介绍三大特性的原理. 继承 Java中的继承只能单继承,但是可以通过内部类继承其他类来 ...
- Java中初始化的相关问题
目录 局部变量的初始化 成员变量的初始化 构造器初始化 静态数据的初始化 总结 已经快半个月没写博客了,这周在看 Thinking in Java 这本书,准备将书中的第五章和第七章的内容整合一下,写 ...
- Java:API文档;文档注释中的javadoc标记;官方API;自己动手给项目建一个API文档
1.什么是API文档 在Java语言中有3种注释 //单行注释 /* 多行注释 */ /** * 文档注释 */ API(应用程序接口)文档就是用javadoc命令提取文档注释生成的,html格式,用 ...
- java中的xpath,读取xml文档。
1,入门 XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言. XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力.起初 X ...
- 关于Java中基类构造器的调用问题
在<Java编程思想>第7章复用类中有这样一段话,值得深思.当子类继承了父类时,就涉及到了基类和导出类(子类)这两个类.从外部来看,导出类就像是一个与基类具有相同接口的新类,或许还会有一些 ...
随机推荐
- Java:如何打印整个字符串数组?
例: public static void main(String[] args) { String prodName = "雇员姓名,雇员唯一号"; String[] prodN ...
- NC50999 表达式计算4
NC50999 表达式计算4 题目 题目描述 给出一个表达式,其中运算符仅包含+,-,*,/,^(加 减 乘 整除 乘方)要求求出表达式的最终值 数据可能会出现括号情况,还有可能出现多余括号情况 数据 ...
- React key究竟有什么作用?深入源码不背概念,五个问题刷新你对于key的认知
壹 ❀ 引 我在[react]什么是fiber?fiber解决了什么问题?从源码角度深入了解fiber运行机制与diff执行一文中介绍了react对于fiber处理的协调与提交两个阶段,而在介绍协调时 ...
- Tapdata 的 2.0 版 ,开源的 Live Data Platform 现已发布
https://www.bilibili.com/video/BV1tT411g7PA/?aid=470724972&cid=766317673&page=1 点击上方链接,一分钟快速 ...
- datax开启hana支持以及dolphinscheduler开启datax任务
datax开启hana支持以及dolphinscheduler开启datax任务 前面(@,@) 前段时间因为要做异构数据导入导出,所以搜了下,发现这类工具收费的居多,使用起来未必趁手~ 于是我找了下 ...
- 聊聊 C++ 中几类特殊成员函数
一:背景 在 C# 中要说类默认给我们定义的特殊成员函数,莫过于 构造函数,但在 C++ 中这样的特殊函数高达 6 种,有必要整合一下聊一聊. 二:特殊成员函数 1. 默认构造函数 和 C# 一样,很 ...
- Python进程管理神器——Supervisor
一.简介 Supervisor 是一款 Python 开发的进程管理系统,允许用户监视和控制 Linux 上的进程,能将一个普通命令行进程变为后台守护进程,异常退出时能自动重启 详细介绍查阅:Supe ...
- centos 7系统安装
1.打开VMware软件,点击创建虚拟机,默认选择,点击下一步 2.选择稍后安装,点击下一步 3.在Linux系统中选择CentOS 7 64位,点击下一步 4.选择好安装位置后,点击下一步 5.选择 ...
- 啥也不是 -「OI 易犯错误整理」
原帖出自 Nefelibata,不过他不想维护,所以就交给 STrAduts 了 awa.因为一些不可抗力,帖主转移至 XSC062.申请置顶! 前言 Nefelibata:因为笔者弱到无法形容,因此 ...
- Template -「网络流 & 二分图」
EK. 很少用到,知道思想即可. 懒得写封装的屑. queue<int> q; int Cap[MAXN][MAXN], Flow[MAXN][MAXN], Aug[MAXN], fa[M ...