服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java中你真的会用Constructor构造器吗之看完本篇你就真的会了

Java中你真的会用Constructor构造器吗之看完本篇你就真的会了

2022-01-11 10:59YXXYX Java教程

显式初始化要求我们在写程序时就确定初始值,这有时很不方便。我们可以使用构造器(constructor)来初始化对象。构造器可以初始化数据成员,还可以规定特定的操作。这些操作会在创建对象时自动执行。下面文字将对该内容做详细

引言

相信大家对于java里的构造器应该都是有了解的,这次我们来了解一些构造器的不同使用方式,了解构造器的调用顺序,最后可以灵活的在各种情况下定义使用构造器,进一步优化我们的代码;

构造器简介

还是简单介绍一下构造器到底是什么吧,
构造器是类中一种特殊的方法,通过调用构造器来完成对象的创建,以及对象属性的初始化操作。

构造器定义方式:

?
1
2
3
[修饰符列表] 构造器名(形式参数列表){
     构造方法体;
 }

构造器有以下几个特点:

  • 构造器名和类名一致;
  • 构造器用来创建对象,以及完成属性初始化操作;
  • 构造器返回值类型不需要写,包括 void 也不能写
  • 构造器的返回值类型实际上是当前类的类型
  • 一个类中可以定义多个构造器,这些构造器构成方法重载

构造器的使用其实很常见,调用语法为:new 构造器名(实际参数列表) ,假如我们现在有一个Person类,调用默认构造器:

?
1
Person p = new Person(); // 这里的Person()其实就是调用的默认构造器!!

构造器的使用需要注意:
当一个类没有显式的定义任何构造器的时候,系统默认提供无参数构造器,当显式的定义构造器之后,系统不再提供无参数构造器。无参数构造器又叫做缺省构造器,或默认构造器;

构造器重载

虽然系统会给我们提供默认构造器并赋予初始值,我们自己也可以显式的指定初始值,但是可不可以多种构造器同时存在一个类中呢?
这就需要重载构造器,因为构造器也是方法的一种,方法都可以重载,构造器当然也可以;
构造器重载方式和方法重载差不多,只需要构造器名相同,参数列表不同就可以了;

测试代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ConstructorOverloadTest {
    String name;
    int age;
 
    // 默认构造器(无参构造器)
    ConstructorOverloadTest() {}
    // 含参构造器 重载版
    ConstructorOverloadTest(String myName, int myAge) {
        this.name = myName;
        this.age = myAge;
    }
    public static void main(String[] args) {
        // 调用无参构造器
        var p1 = new ConstructorOverloadTest();
        System.out.println("p1的初始化结果为:");
        System.out.println("姓名 :" + p1.name);
        System.out.println("年龄:" + p1.age);
        // 调用有参构造器
        var p2 = new ConstructorOverloadTest("张三", 18);
        System.out.println("p2的初始化结果为:");
        System.out.println("姓名 :" + p2.name);
        System.out.println("年龄:" + p2.age);
    }
}

输出结果为:

p1的初始化结果为:
姓名 :null
年龄:0
p2的初始化结果为:
姓名 :张三
年龄:18

当然这里只写了一个重载版本,还可以定义多个重载版本,这里就不列举了;我们只需要能够根据实际情况使用恰当的重载就可以了,不用都写出来;

构造器间的相互调用

如果系统中有多个构造器,并且我们想要通过一个构造器A调用另一个构造器B,该怎么办?
可能有人会想到调用构造器肯定要创建一个对象啊,所以直接new一个不就可以了嘛; 但是我们通过一个构造器调用另一个构造器的目的就是为了简化代码的,这样反而又多此一举了;
如果不new一个新的对象,那么我们可以通过 this引用 来调用相应的构造器;

还是不太明白?看看下面的代码!
测试代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class ConstructorTest01 {
    public static void main(String[] args) {
        // 调用两个参数的构造器
        Person p1 = new Person("张三", 18);
        System.out.println("两个参数的构造器初始化结果为:");
        System.out.println("姓名:" + p1.name);
        System.out.println("身份证号:" + p1.idNum);
        System.out.println("年龄:" + p1.age);
 
        // 调用三个参数的构造器
        Person p2 = new Person("李四", "6666666", 20);
        System.out.println("三个参数的构造器初始化结果为:");
        System.out.println("姓名:" + p2.name);
        System.out.println("身份证号:" + p2.idNum);
        System.out.println("年龄:" + p2.age);
    }
}
class Person {
    String name;
    String idNum;
    int age;
 
    // 有两个参数的构造器
    Person(String myName, int myAge) {
        this.name = myName;
        this.age = myAge;
    }
    // 有三个参数的构造器
    Person(String myName, String myIdNum, int myAge) {
        // 通过this调用两个参数的构造器
        this(myName, myAge);
        this.idNum = myIdNum;
    }
}

输出结果为:

两个参数的构造器初始化结果为:
姓名:张三
身份证号:null
年龄:18
三个参数的构造器初始化结果为:
姓名:李四
身份证号:6666666
年龄:20

通过this调用有一点需要注意:
使用this调用另一个重载的构造器只能在构造器中使用,且必须作为构造器执行体的第一条语句

可能有人会问:如果在有三个参数的构造器里面不用this指针,而是直接把上一个构造器的代码复制过来不行吗?
当然可以,但是不建议;我们得知道为什么要存在this这个调用构造器的方法,它不是无缘无故存在的;在软件开发时有一个原则:不要把相同代码重复写两次以上;因为一旦一个构造器内的初始代码需要修改,那么很有可能其他的构造器初始代码也要跟着修改,如果构造版本多的话是非常麻烦的;而使用this恰恰可以避免这个问题,只需要修改一个地方,其他几个构造器就随着更改了;这样的代码不仅更加简洁,而且降低了维护成本;

子类构造器调用父类构造器

继承有一个规则是:当继承发生后,子类不会获得父类的构造器;
但是子类的构造器可以通过一定方法区调用父类构造器,类似于通过this引用调用重载的构造器;
而子类构造器调用父类的构造器不用this关键字,这里有一个新的关键字:super

super和this用法差不多,使用它就可以实现子类构造器调用父类的构造器;

看个代码就明白了:
测试代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person {
    String name;
    int age;
    // 父类的构造函数
    Person(String myName, int myAge) {
        this.name = myName;
        this.age = myAge;
    }
}
public class Kids extends Person{
    String school;
    // 子类的构造函数
    Kids(String myName, int myAge, String mySchool) {
        // 通过super来调用父类构造器初始化过程
        super(myName, myAge);
        this.school = mySchool;
    }
    public static void main(String[] args) {
        Kids k = new Kids("张三", 5, "奥特曼小学");
        System.out.println("name:" + k.name);
        System.out.println("age:" + k.age);
        System.out.println("school:" + k.school);
    }
}

输出结果为:

name:张三
age:5
school:奥特曼小学

通过代码可以看出来super确实和this非常像,无非就是super调用父类构造器,this调用同一个类的重载的构造器;
且使用super也需要注意:
super调用父类构造器也必须在子类构造器执行体的第一行,所以this和super不会同时出现;

构造器的调用顺序

这里先看一个代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Creature {
    Creature() {
        System.out.println("Creature的无参构造器的调用");
    }
}
class Person extends Creature {
    Person(String name) {
        System.out.println("Person的一个参数构造器的调用");
    }
    Person(String name, int age) {
        // this调用同一个类中重载的构造器
        this(name);
        System.out.println("Person的两个参数构造器的调用");
    }
}
public class Kids02 extends Person {
    Kids02() {
        // 显式调用父类的两个参数的构造器
        super("张三", 18);
        System.out.println("Kids02的无参构造器的调用");
    }
    public static void main(String[] args) {
        // 创建一个Kids02对象
        new Kids02();
    }
}

这个代码中,Person类继承了Creature类,Kids02类继承了Person类,Perosn类中又通过this调用同一个类中重载的构造器,
Kids02类中用super 显式调用父类的两个参数的构造器;
那么输出是什么呢?到底先调用的是谁的构造器,最后调用的谁的构造器?

输出如下:

Creature的无参构造器的调用
Person的一个参数构造器的调用
Person的两个参数构造器的调用
Kids02的无参构造器的调用

通过这个代码和结果,可以总结出来,父类构造器总在子类构造器之前执行,或者可以说:
创建任何对象总是从该类所在继承树最顶层类的构造器开始执行的,然后依次向下执行;
对于this和super也是一样;

这个代码好好理解一下,就会对构造器间的关系体会更深;

总结

对象的初始化离不开构造器,对构造器的学习真正需要的还是大量的练习,这些内容也是需要熟练掌握的;这关乎着你在实际开发应用过程中对整个代码的影响和对象能否恰到好处的初始化;希望你能够真正学会并应用到这些方法,且通过这篇文章能有所收获!

ps:如果内容有问题欢迎讨论!!

到此这篇关于Java中你真的会用Constructor构造器吗之看完本篇你就真的会了的文章就介绍到这了,更多相关Java 构造器 Constructor内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/YXXXYX/article/details/120164551

延伸 · 阅读

精彩推荐
  • Java教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7482021-02-04
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12