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:nulla:0b:falsec: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 Javaclass 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 Javaclass 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
- 构造函数能够重载但不能被笼罩
本文参加了思否技术征文,欢送正在浏览的你也退出。