本文分享自华为云社区《一文带你了解 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
- 结构函数能够重载但不能被掩盖
点击关注,第一时间了解华为云新鲜技能~