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

上一篇:保守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() ;            //进行方法的调用
    }
}

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

下面针对于当前的对象实例化格式与之前的对象实例化格式做一个比较:
之前的对象实例化格式:①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() ;            //进行方法的调用
    }
}

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

结论:一个类至少存在有一个构造方法,永恒存在。
疑问:为什么构造方法上不允许设置返回值类型?
既然构造方法是一个方法,那么为什么不让它定义返回值类型呢?
既然构造方法不会返回数据,那么为什么不使用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() ;            //进行方法的调用
    }
}

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

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() ;            //进行方法的调用
    }
}

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

在进行多个构造方法定义的时候强烈建议大家有一些定义的顺序,例如:可以按照参数的个数降序或升序排序。
经过分析可以发现,构造方法的确是可以进行数据的设置,而对于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() ;            //进行方法的调用
    }
}

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

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

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

上一篇:二进制/十六进制转浮点数的编程(互转类似)


下一篇:重新理解响应式编程