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

引言

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

构造器简介

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

构造器定义方式:

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

构造器有以下几个特点:

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

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

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

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

构造器重载

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

测试代码:

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引用 来调用相应的构造器;

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

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用法差不多,使用它就可以实现子类构造器调用父类的构造器;

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

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不会同时出现;

构造器的调用顺序

这里先看一个代码:

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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java构造器方法深入理解

    目录 重载 1.构造器的重载 2.方法的重载(overload) 重写 重载 1.构造器的重载 因为构造器的名字必须与类名相同,所以同一个类的所有构造器名肯定相同,构成重载:为了让系统能区分不同的构造器,多个构造器的参数列表必须不同. class Person{ int age; String name; public Person(){ } public Person(int age){ this.age = age; } public Person(int age,String name){

  • java构造器的重载实现实例讲解

    说到重载的问题,已经提过很多次了.我们可以把名称一致,但是内在参数不同的对象看成重载,可以说这些类的名称相同是很有迷惑性的.同时,构造器中装有许多的方法,那么构造器也是可以实现重载的功能.下面我们就构造方法格式.注意事项进行简单介绍,然后带来构造起的重载实例. 1.构造方法格式 public class 类名(){ 类名(String name); 类名 对象=new 类名(String name): } 2.注意事项 构造器必须与主类同名 构造器可以有参数 构造器可以重载 没有返回值 不添加构

  • Java继承构造器使用过程解析

    这篇文章主要介绍了Java继承构造器使用过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Java>中提到下面一段话: 当创建一个导出类的对象时,该对象包含了一个基类的子对象.这个子对象与你用基类直接创建的对象是一样的.二者区别在于,后者来自于外部,而基类的子对象被包装在导出类的对象内部. 我们在创建子类对象时,调用了父类的构造器,甚至父类的父类构造器.我们知道,构

  • Java构造器(构造方法)与方法区别说明

    构造器,又称为构造方法.构造器用于构造该类的实例,也就是对象. 格式如下:[修饰符] 类名 (形参列表){//n条语句} 构造方法是一种特殊的方法,与一般的方法区别: 1.构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有. 2.构造方法的调用是在创建一个对象时使用new操作进行的.构造方法的作用是初始化对象. 3.不能被static.final.synchronized.abstract和native修饰.构造方法不能被子类继承. 构造方法可以被重载.没有参数的构造方

  • java中构造器内部调用构造器实例详解

    可能为一个类写了多个构造器,有时可能想在一个构造器里面调用另外一个构造器,为了减少代码的重复,可用this关键字做到这一点. public class Flower { private String string; private int age; public Flower() { // 先调用public Flower(String string, int age) this("leon", 120); // 先调用public Flower(String string, int

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

    引言 相信大家对于java里的构造器应该都是有了解的,这次我们来了解一些构造器的不同使用方式,了解构造器的调用顺序,最后可以灵活的在各种情况下定义使用构造器,进一步优化我们的代码: 构造器简介 还是简单介绍一下构造器到底是什么吧, 构造器是类中一种特殊的方法,通过调用构造器来完成对象的创建,以及对象属性的初始化操作. 构造器定义方式: [修饰符列表] 构造器名(形式参数列表){ 构造方法体; } 构造器有以下几个特点: 构造器名和类名一致: 构造器用来创建对象,以及完成属性初始化操作: 构造器返

  • java中使用try-catch-finally一些值得注意的事(必看)

    我们知道,try负责圈定可能会出异常的代码:catch负责处理try中可能异常的处理,如记录错误日志,使业务能够正常运行:finally负责资源释放等善后工作,无论有无异常都必须要执行的代码,一般都是放在finally中的.如果catch和finally也会出现异常,那么会是什么效果呢? try { // java.lang.ArithmeticException int a = 1 / 0; } catch (Exception e) { System.out.println("catch&q

  • 深入理解Linux shell中2>&1的含义(全网最全,看完就懂)

    A.首先了解下1和2在Linux中代表什么 在Linux系统中0 1 2是一个文件描述符 名称 代码 操作符 Java中表示 Linux 下文件描述符(Debian 为例) 标准输入(stdin) 0 < 或 << System.in /dev/stdin -> /proc/self/fd/0 -> /dev/pts/0 标准输出(stdout) 1 >, >>, 1> 或 1>> System.out /dev/stdout ->

  • 看完这篇文章获得一些java if优化技巧

    目录 1.if 合并 2.将正常的流程放在函数的主干执行 3.减少if 1. 使用三元运算符表达式 2.使用java8 中流过滤filter ,不使用if 3.使用枚举 4.使用manager 5.使用Consumer 总结: 1.if 合并 使用逻辑运算符进行合并if.简单的if 嵌套可以使用&& 进行合并.简单的if else 并且操作相同可以使用 || 进行合并,优化代码逻辑,增加可读性. 注意:逻辑运算符的截断性,if(a >= 10 || b >= 20) 当a>

  • Java中的三种标准注解和四种元注解说明

    目录 Java的三种标准注解和四种元注解 先来说说什么是注解 Java内置了三种注解,定义在java.lang中的注解 Java除了内置了三种标准注解,还有四种元注解 元注解和自己写一个注解 一.元注解 二.自己写注解 Java的三种标准注解和四种元注解 先来说说什么是注解 注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据. 注解的语法比较简单,除了@符号的使用之外,它基本与Java固有的语法一致. Java内置了三种注解,定义在

  • 快速入门Java中的Lambda表达式

    Lambda简介 Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块). Lambda表达式还增强了集合库. Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及 java.util.stream 包. 流(stream)就如同迭代器(iterator),但附加了许多

  • JAVA中static方法的用法实例详解

    本文实例讲述了JAVA中static方法的用法.分享给大家供大家参考,具体如下: static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享.只要这个类被加载,Java虚拟机就能根据类名在运行时数据区或者方法区内找到他们.因此,static对象可以在它的任何对象创建之前访

  • Java 中的io模型详解

    1. BIO 我们先看一个 Java 例子: package cn.bridgeli.demo;   import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket;   /**  * @author bridgel

  • Java中几种常用数据库连接池的使用

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出.拓机.如下图所示: 二.使用数据库连接池优化程序性能 2.1.数据库连接池的基本概念 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性

  • Java中的接口多继承机制

    目录 问题原因 一个接口可以同时继承多个接口 接口不能实现任何接口 一个类可以实现多个接口 一个类只能继承一个父类 总结: 问题原因 今天在看集合源码的时候,突然看到接口继承接口,觉得有点差异,以前写代码也就是类继承一个类,实现接口.这样写的多了,突然看到接口继承接口就有点诧异了,以为哪里不对.就测试,查阅了一些资料 一个接口可以同时继承多个接口 书写接口测试 public interface Jiekou extends Jiekou1,Jiekou2{ void jiekou(); } pu

随机推荐