“生而有值”—教你使用构造函数 | 带你学《Java面向对象编程》之五

简介: 本节结合多组实例从多个方面介绍了重写构造函数的意义以及构造函数与setter函数的异同,指出了一些编写构造函数相关的注意事项。

上一篇:保守VS开放?看清封装对象属性 | 带你学《Java面向对象编程》之四
【本节目标】
通过阅读本节,你将了解到为对象属性赋值的其他方法,学会通过对构造函数的多样化运用实现对象的快速实例化,使代码显得更加简洁、优雅。

5.1 构造方法

现在的程序在使用类的时候一般都按照如下的步骤进行:
(1)声明并实例化对象,这时实例化对象中的属性并没有任何的数据存在,都是其对应数据类型的默认值。
(2)需要通过一系列的setter方法为类中的属性设置内容。
也就是说现在要想真正获得一个可以正常使用的实例化对象,必须经过两个步骤才可以完成。
范例:传统调用

class Person{    //定义一个类
    private String name ;  //人员的姓名
    private int age ;       //人员的年龄
    public void tell() {
        System.out.println(“姓名:”+ name +”、年龄:”+age) ;
    } 
    public void setName(String n){
        name = n ;
    }
    public void setAge(int a){
        age = a ;
    }
    public String getName(){
        return name ;
    } 
    public int getAge (){
        return age;
    } 
}
public class JavaDemo {      //主类
    public static void main(String args[]) {
   //1、对象的初始化准备
        Person per = new Person() ;     //声明并实例化对象
        per.setName = (“张三”) ;           //在类外部修改属性
        per.setAge = (-18) ;                //在类外部修改属性
  //2、对象的使用
        per.tell() ;            //进行方法的调用
    }
}

但是如果按照这样的方式来进行思考的话就会发现一个问题:假设类中的属性有多个,这样一来,按照之前的做法,此时需要调用多次的setter方法进行内容设置,这样的调用比较麻烦,所以在Java中为了考虑对象初始化的问题,专门提供有构造方法,即:可以通过构造方法实现实例化对象中的属性初始化处理。只有在关键字new的时候使用构造方法,在Java程序中构造定义要求如下:

  • 构造方法名称必须与类名称保持一致
  • 构造方法不允许设置任何的返回值类型,即:没有返回值定义
  • 构造方法是在使用关键字new实例化对象的时候自动调用的

范例:构造定义方法

class Person{    //定义一个类
    private String name ;  //人员的姓名
    private int age ;       //人员的年龄
//方法名称与类名称相同,并且无返回值定义
    public Person (String n, int a) {   //定义有参构造
        name = n ;           //为类中的属性赋值(初始化)
        age = a ;            //为类中的属性赋值(初始化)
    }
    public void tell() {
        System.out.println(“姓名:”+ name +”、年龄:”+age) ;
    } 
}
public class JavaDemo {      //主类
    public static void main(String args[]) {
   //1、对象的初始化准备
        Person per = new Person(“张三”, 18) ;     //声明并实例化对象
  //2、对象的使用
        per.tell() ;            //进行方法的调用
    }
}

image.png
图一 执行结果一

下面针对于当前的对象实例化格式与之前的对象实例化格式做一个比较:
之前的对象实例化格式:①Person ②per = ③new ④Person() ;
当前的对象实例化格式:①Person ②per = ③new ④Person(“张三”, 18) ;

  • “①Person”:主要是定义对象的所属类型,类型决定了你可以调用的方法;
  • “②per”:实例化对象的名称,所有的操作通过对象来进行访问;
  • “③new”:开辟一块新的堆内存空间;
  • “④Person(“张三”, 18)”:调用有参构造、“④Person()”:调用无参构造

在Java的程序中考虑到程序结构的完整性,所以所有的类都会提供有构造方法,也就是说如果现在类中没有定义任何构造方法,那么一定会默认提供一个无参的,什么都不做的构造方法,这个构造方法是在程序编译的时候自动创建的。如果现在已经在类中明确定义有一个构造方法的时候,那么这个默认的构造方法将不会被自动创建。

class Person{    //定义一个类
    private String name ;  //人员的姓名
    private int age ;       //人员的年龄
//方法名称与类名称相同,并且无返回值定义
    public Person (String n, int a) {   //定义有参构造
        name = n ;           //为类中的属性赋值(初始化)
        age = a ;            //为类中的属性赋值(初始化)
    }
    public void tell() {
        System.out.println(“姓名:”+ name +”、年龄:”+age) ;
    } 
    public void setName(String n){
        name = n ;
    }
    public void setAge(int a){
        age = a ;
    }
    public String getName(){
        return name ;
    } 
    public int getAge (){
        return age;
    } 
}
public class JavaDemo {      //主类
    public static void main(String args[]) {
   //1、对象的初始化准备
        Person per = new Person() ;     //声明并实例化对象
  //2、对象的使用
        per.tell() ;            //进行方法的调用
    }
}

image.png
图二 执行结果二

结论:一个类至少存在有一个构造方法,永恒存在。
疑问:为什么构造方法上不允许设置返回值类型?
既然构造方法是一个方法,那么为什么不让它定义返回值类型呢?
既然构造方法不会返回数据,那么为什么不使用viod定义呢?
public Person (String n, int a) ;
public void Person (String n, int a) ;
分析:程序编译器是根据代码结构来进行编译处理的,执行的时候也是根据代码结构来处理的。
如果在构造方法上使用了void,那么此结构就与普通方法的结构完全相同,这样我们编译器会认为此方法是普通方法。而普通方法与构造方法最大的区别:构造方法是在类对象实例化的时候调用的,而普通方法是在类对象实例化产生后调用的。
既然构造方法本身是一个方法,那么方法就具有重载的特点,而构造方法重载的时候只需要考虑参数的类型及个数即可。
范例:构造方法重载

class Person{    //定义一个类
    private String name ;  //人员的姓名
    private int age ;       //人员的年龄
    public Person() {}
    public Person(String n) {
        name = n ;
    }
//方法名称与类名称相同,并且无返回值定义
    public Person (String n, int a) {   //定义有参构造
        name = n ;           //为类中的属性赋值(初始化)
        age = a ;            //为类中的属性赋值(初始化)
    }
    public void tell() {
        System.out.println(“姓名:”+ name +”、年龄:”+age) ;
    } 
}
public class JavaDemo {      //主类
    public static void main(String args[]) {
   //1、对象的初始化准备
        Person per = new Person(“张三”, 18) ;     //声明并实例化对象
  //2、对象的使用
        per.tell() ;            //进行方法的调用
    }
}

image.png
图三 执行结果三

class Person{    //定义一个类
    private String name ;  //人员的姓名
    private int age ;       //人员的年龄
    public Person() {
        name = “无名氏” ;
        age = -1 ;
    }
    public Person(String n) {
        name = n ;
    }
//方法名称与类名称相同,并且无返回值定义
    public Person (String n, int a) {   //定义有参构造
        name = n ;           //为类中的属性赋值(初始化)
        age = a ;            //为类中的属性赋值(初始化)
    }
    public void tell() {
        System.out.println(“姓名:”+ name +”、年龄:”+age) ;
    } 
}
public class JavaDemo {      //主类
    public static void main(String args[]) {
   //1、对象的初始化准备
       Person per = new Person() ;     //声明并实例化对象
  //2、对象的使用
       per.tell() ;            //进行方法的调用
    }
}

image.png
图四 执行结果四

在进行多个构造方法定义的时候强烈建议大家有一些定义的顺序,例如:可以按照参数的个数降序或升序排序。
经过分析可以发现,构造方法的确是可以进行数据的设置,而对于setter也可以进行数据的设置。构造方法是在对象实例化的时候为属性设置初始化内容,而setter除了拥有设置数据的功能之外,还具有修改数据的功能。
范例:使用setter修改数据

class Person{    //定义一个类
    private String name ;  //人员的姓名
    private int age ;       //人员的年龄
//方法名称与类名称相同,并且无返回值定义
    public Person (String n, int a) {   //定义有参构造
         name = n ;           //为类中的属性赋值(初始化)
         age = a ;            //为类中的属性赋值(初始化)
    }
    public void tell() {
        System.out.println(“姓名:”+ name +”、年龄:”+age) ;
    } 
    public void setName(String n){
        name = n ;
    }
    public void setAge(int a){
        age = a ;
    }
    public String getName(){
        return name ;
    } 
    public int getAge (){
        return age;
    } 
}
public class JavaDemo {      //主类
    public static void main(String args[]) {
   //1、对象的初始化准备
        Person per = new Person(“张三”, 10) ;     //声明并实例化对象
  //2、对象的使用
        per.setAge(18);        //修改属性内容
        per.tell() ;            //进行方法的调用
    }
}

image.png
图五 运行结果五

想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。
本内容视频来源于阿里云大学

下一篇:3分钟速懂匿名对象 | 带你学《Java面向对象编程》之六
更多Java面向对象编程文章查看此处

相关文章
|
24天前
|
Java 开发者
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
33 7
|
24天前
|
Java 开发者
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
39 5
|
27天前
|
Java
【Java基础面试三十四】、接口中可以有构造函数吗?
这篇文章讨论了Java中接口不能包含构造函数的原因,主要解释了接口中的成员变量默认是public static final类型的常量,不需要通过构造函数初始化,且接口本身不能被实例化,因此构造函数在接口中没有意义。
|
25天前
|
Java 程序员
Java中的继承和多态:理解面向对象编程的核心概念
【8月更文挑战第22天】在Java的世界中,继承和多态不仅仅是编程技巧,它们是构建可维护、可扩展软件架构的基石。通过本文,我们将深入探讨这两个概念,并揭示它们如何共同作用于面向对象编程(OOP)的实践之中。你将了解继承如何简化代码重用,以及多态如何为程序提供灵活性和扩展性。让我们启程,探索Java语言中这些强大特性的秘密。
|
3月前
|
Java
Java面向对象编程新篇章:多态,你准备好了吗?
【6月更文挑战第17天】Java的多态性是面向对象编程的核心,它允许通过统一的接口处理不同类型的对象。例如,在一个虚拟宠物游戏中,抽象类`Pet`定义了`speak()`方法,猫、狗和鹦鹉等子类各自重写此方法以实现独特叫声。在`main`方法中,使用`Pet`类型的引用创建子类对象并调用`speak()`,多态机制确保调用实际对象的方法,实现代码的灵活性和可扩展性。通过多态,我们能以更低的耦合度和更高的复用性编写更优雅的代码。
28 3
|
10天前
|
Java 开发者
【Java编程新纪元】JDK 22:超级构造函数来袭,super(...) 前导语句改写编程规则!
【9月更文挑战第6天】JDK 22的超级构造函数特性是Java编程语言发展史上的一个重要里程碑。它不仅简化了代码编写,还提升了代码的可读性和维护性。我们有理由相信,在未来的Java版本中,还将有更多令人兴奋的新特性等待我们去发现和应用。让我们共同期待Java编程新纪元的到来!
|
26天前
|
Java 开发者
什么是 Java 中的构造函数链?
【8月更文挑战第21天】
13 1
|
1月前
|
存储 前端开发 JavaScript
【前端学java】面向对象编程基础-类的使用(4)
【8月更文挑战第9天】面向对象编程基础-类的使用
10 0
【前端学java】面向对象编程基础-类的使用(4)
|
3月前
|
Java
Java 面向对象编程:父类与子类的“传承”与“创新”之路
【6月更文挑战第16天】Java 中的父类与子类展示了面向对象的“传承”与“创新”。子类`Dog`继承`Animal`,获取其属性和方法如`name`和`makeSound`。子类通过`@Override`增强`makeSound`,显示多态性。设计父类时应考虑普遍性,子类创新专注自身特性,遵循继承最佳实践,利用复用提升效率,构建可维护的软件系统。
135 57
|
26天前
|
Java 程序员 开发者
Java的面向对象编程:从基础到深入
【8月更文挑战第21天】在本文中,我们将探讨Java的面向对象编程(OOP)的核心概念,包括类、对象、继承、多态和封装。我们将通过实例和比喻,以通俗易懂的方式,深入理解这些概念的内涵和意义,以及它们如何影响我们的编程思维和实践。无论你是初学者还是有经验的开发者,这篇文章都将帮助你更深入地理解Java的OOP,并启发你思考如何在你的项目中应用这些概念。