一文了解 Java 中的构造器

3A网络
• 阅读 460

一文了解 Java 中的构造器

C ++ 引入了构造器(constructor,也叫构造函数)的概念,它是在创建对象时被自动调用的特殊方法

Java 也采用了构造器,并且还提供了一个垃圾收集器(garbage collector),当不再使用内存资源的时候,垃圾收集器会自动将其释放。

构造器定义

在 Java 中,可以通过编写构造器来确保每个对象的初始化。但是这里有两个问题:

  1. 这个构造器使用的任何名字都有可能与类里某个成员相冲突;
  2. 编译器负责调用构造器,所以它必须始终知道应该调用哪个方法。

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 的值为:

一文了解 Java 中的构造器

构造器目的

构造函数的目的是初始化对象的状态,为所有声明的属性赋值。如果我们没有自定义构造函数,JVM 就会为这些属性分配默认值。

原始类型的默认值:

  • 整数类型是 0
  • 浮点类型是 0.0
  • 布尔类型是 false

对于其他 Java 引用类型,默认值是 null,这意味着引用类型的属性没有被分配任何值。

一文了解 Java 中的构造器

后面可以用代码查看这些默认值。

构造器分类

一文了解 Java 中的构造器

在 Java 中,有三种类型的构造器:

  1. 无参构造器
  2. 有参构造器
  3. 默认构造器

无参构造器

与方法类似,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 中的构造器

默认构造器

如果我们不创建任何构造函数,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 中的构造器

编程语言: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);
 }
}

总结

以上环境博主都是部署在cnaaa云服务器上,感兴趣的伙伴可以自己也部署一套相同的环境进行测试。

  • 实例化对象时会隐式调用构造函数。
  • 创建构造函数的两条规则是:构造函数的名称应与类相同。Java 构造函数不能有返回类型。
  • 如果一个类没有构造函数,Java 编译器会在运行时自动创建一个默认构造函数。默认构造函数使用默认值初始化实例变量。例如 int 变量将被初始化为 0
  • 构造函数类型:
  • 无参构造器 - 不接受任何参数的构造函数参数化构造函数
  • 接受参数的构造器 - 接受参数的构造函数
  • 默认构造器 - 如果没有明确定义,Java 编译器会自动创建一个构造函数。
  • 构造函数不能被 abstract、static 或 final 修饰

编译器会报如下错误:

Illegal modifier for the constructor in type ReLearnConstructor; only public, protected & private are permitted
  • 构造函数可以重载但不能被覆盖
点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java成员变量的初始化
类变量(static变量,不需要实例化对象也可以引用)实例变量(非static变量,需要实例化对象)局部变量(类的成员函数中的变量)初始化方式:构造函数初始化变量声明时初始化代码块初始化java自动初始化(在构造函数执行之前执行) java保证所有变量被使用之前都是经过初始化的(声明并且定义过,被赋值
Wesley13 Wesley13
3年前
JAVA面试考点解析(11)
9、解释内存中的栈(stack)、堆(heap)和方法区(methodarea)的用法。答:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,
Wesley13 Wesley13
3年前
Java构造方法与析构方法实例剖析
Java构造方法类有一个特殊的成员方法叫作构造方法,它的作用是创建对象并初始化成员变量。在创建对象时,会自动调用类的构造方法。构造方法定义规则:Java中的构造方法必须与该类具有相同的名字,并且没有方法的返回类型(包括没有void)。另外,构造方法一般都应用public类型来说明,这样才能在程序任意的位置创建类的实例-
Wesley13 Wesley13
3年前
Java构造器就是这么简单!
前言理解构造器之前,首先我们需要了解Java中为什么要引入构造器,以及构造器的作用。在很久之前,程序员们编写C程序总会忘记初始化变量(这真的是一件琐碎但必须的事),C引入了构造器(constructor)的概念,这是一个在创建对象时被自动调用的特殊方法。Java也采用了构造器。一、构造器的引入引入构造器帮助我们解决了哪
Wesley13 Wesley13
3年前
Java面向对象之构造器
\toc\Java面向对象之构造器利用构造器确保初始化初始化问题是关系编程方式是否安全的一个重要的问题。功能:在创建对象时执行初始化。在Java中,每个类至少有一个构造器。格式如下:修饰符构造器名(参数列表){...执行体
Wesley13 Wesley13
3年前
C++ 类与结构体 构造函数 详细相关理解整理
说到构造函数,通常是将讲对象创建时编译器自动调用构造函数为对象初始化,也可以说是分配内存空间。 学习了构造函数相对其中牵涉到的一些点作下大概的了解和学习,整理一下只是点。这里主要说下 类与结构体的差异/类与结构体包含继承关系时的构造调用/类的初始化列表/默认构造函数/拷贝构造函数以及牵涉到的相关内容结构体和类的区别
Wesley13 Wesley13
3年前
Java构造器的实质作用
Java构造器的实质作用构造器的本质作用就是为对象初始化,即为实例变量初始化,赋初值;而不是创建对象,创建对象时通过new关键字来完成的,当使用new关键字时就会为该对象在堆内存中开辟一块内存,只等构造器来初始化这块内存,为实例变量赋初始值。在未赋初始值之前是默认值。看代码中的构造器和编译后构造器是不一样的,编译后的构造器包含了更多的内容。
小万哥 小万哥
11个月前
C# 面向对象编程进阶:构造函数详解与访问修饰符应用
C构造函数构造函数是一种特殊的方法,用于初始化对象。构造函数的优势在于,在创建类的对象时调用它。它可以用于为字段设置初始值:示例获取您自己的C服务器创建一个构造函数:csharp//创建一个Car类classCarpublicstringmodel;//创
小万哥 小万哥
10个月前
Java 构造函数与修饰符详解:初始化对象与控制权限
Java构造函数Java构造函数是一种特殊的类方法,用于在创建对象时初始化对象的属性。它与类名相同,并且没有返回值类型。构造函数的作用:为对象的属性设置初始值执行必要的初始化操作提供创建对象的多种方式构造函数的类型:默认构造函数:无参数的构造函数,如果用户
小万哥 小万哥
8个月前
C++ 构造函数实战指南:默认构造、带参数构造、拷贝构造与移动构造
C构造函数构造函数是C中一种特殊的成员函数,当创建类对象时自动调用。它用于初始化对象的状态,例如为属性分配初始值。构造函数与类同名,且没有返回值类型。构造函数类型C支持多种类型的构造函数,用于满足不同的初始化需求:默认构造函数:不带参数的构造函