一、构造方法的介绍

  开发过程中经常需要在创建对象的同时明确对象的属性,比如员工刚入职公司就要明确他的姓名、年龄等属性信息。

  那么在创建对象就要明确属性值,如何实现呢?也就是在创建对象的时候就要做的事情,当使用new关键字创建对象时,怎么给对象属性初始化值呢?这里就要用到Java的构造方法。

  那么什么是构造方法?从字面理解即为构建创造时用的方法,既对象创建时要执行的方法。既然是对象创建时候要执行的方法,那么只要在new对象时,知道其执行的构造方法是什么,就可以在执行这个方法的时候给对象进行属性赋值。

  构造方法定义语法的格式:

    修饰符  构造方法名(参数列表){}

  构造方法的特点:

    1、构造方法无返回值类型,如:void等。也不需要写返回值,因为它是为构建对象的,对象创建完,方法就执行结束。

    2、构造方法名称必须和本类的名称保持一致。

  构造方法的代码体现:



1 public class Person {
 2     private String name;
 3     private int age;
 4     
 5     /*
 6      *     定义出Person类无参的构造方法
 7      */
 8     public Person() {
 9         
10     }
11     
12     /*
13      *     定义出Person类含有参数的构造方法
14      */
15     public Person(String name,int age) {
16         //System.out.println("我是一个空参数的构造方法");
17         this.name = name;
18         this.age = age;
19     }



二、构造方法的调用和图解说明

首先看构造方法是如何执行的呢?在创建对象的时候是如何初始化的呢?

  构造方法是专门用来创建对象,也就是在new对象的时要调用构造方法,如下面的代码体现:



1 public class Person {
 2     // Person的成员属性age和name
 3     private int age;
 4     private String name;
 5 
 6     // Person的构造方法,拥有参数列表
 7     Person(int a, String nm) {
 8         // 接受到创建对象时传递进来的值,将值赋给成员属性
 9         this.age = a;
10         this.name = nm;
11     }
12 
13     public void speak() {
14         System.out.println("name=" + name + ",age=" + age);
15     }
16 }
17 /*
18  *     测试类PersonDemo
19  * */
20 class PersonDemo {
21     public static void main(String[] args) {
22         // 创建Person对象,并明确对象的年龄和姓名
23         Person p = new Person(23, "张三");
24         p.speak();
25 }



 

  上述代码对创建对象时,对构造方法的调用。既在创建对象时,会调用与参数列表对应的构造方法。

  上述代码的构造方法原理图:

JAVA的构造方法会返回对象吗 java构造方法能有返回值吗_java

  上述原理图说明:

    内存加载的过程:

    有一个Person类, 创建Person 对象new Person()
    1、首先会将main方法压入栈中,执行main方法中的 new Person(23,"张三");
    2、在堆内存中分配一片区域,用来存放创建的Person对象,这片内存区域会有属于自己的内存地址(0x001)。然后给成员变量进行默认初始化(name=null,age=0)。
    3、执行构造方法中的代码(age = a ; name = name;),将变量a对应的23赋值给age,将变量name对应的”张三赋值给name,这段代码执行结束后,成员变量age和name的值已经改变。执行结束之后构造方法弹栈,Person对象创建完成。将Person对象的内存地址0x001赋值给p。

三、默认构造方法和细节描述

  在描述事物的场景下,并没有显示指定构造方法,当在Java编译的时候,编译器会自动给class文件中添加默认的构造方法。如果描述类时,指定了构造方法,那么在编译器在编译Java源文件时,编译器就不会再给class文件中添加默认的构造方法。

  代码显示如下:



1 public class  Person {
 2     //如果没有显示指定构造方法,编译会在编译时自动添加默认的构造方法
 3     //空参数的默认构造方法
 4     public Person(){}  
 5     // 有参构造方法
 6     public Person(String name,int age){
 7         this.name = name;
 8         this.age = age;
 9     }
10 }



  什么样的场景下,需要用到构造方法?

    这种情况下根据事物的描述特点来定,当描述的对象在创建的同时必须要明确其属性值,这个时候就要在定义类的时候写上带参数的构造方法,若创建对象不需要明确的具体数据,这时不需要书写构造方法。

  构造方法的细节有哪些呢?

    1、一个类中可以有多个构造方法,构造方法都是以重载的形式存在

    2、构造方法是可以被private修饰的,作用:其它程序无法创建该类的对象



1 class Person {
 2     private int age;
 3     private String name;
 4 
 5     // 私有无参数的构造方法,即外界不能通过new Person();语句创建本类对象
 6     private Person() {
 7     }
 8 
 9     // 多个构造方法是以重载的形式存在
10     Person(int a) {
11         age = a;
12     }
13 
14     Person(String nm, int a) {
15         name = nm;
16         age = a;
17     }
18 }



四、构造方法和一般方法的区别

  构造方法和一般方法有什么异同呢?

    1、构造方法在对象创建时就执行,而且只执行一次

    2、一般方法是在创建对象后,需要使用时候才被调用,并可以被多次调用

     3、格式不同

        构造方法:修饰符  类名  (参数类型  参数){}

        一般方法:修饰符  返回值类型  方法名(参数类型  参数){}

     4、调用方法不同

        构造方法创建对象时候就默认调用,或this()、super()调用

        普通方法需要对象调用或静态方法直接调用静态方法

     5、作用不同

        构造方法一般是用来给成员变量进行初始化

        一般方法根据需要而定

  有了构造方法,还需要一般方法中的set、get方法吗?

    答案是毋庸置疑的需要,因为在创建对象后,当需要对属性值进行修改或访问时,就需要set和get方法来操作。

五、this调用构造方法

  一般方法可以根据方法名调用,而构造方法可以通过this关键字来完成构造方法之间的调用。

  构造方法调用格式:



this(参数列表);



  构造方法之间的调用:



1 public class Person {
 2     // Person的成员属性
 3     private int age;
 4     private String name;
 5 
 6     // 无参数的构造方法
 7     public Person() {
 8     }
 9 
10     // 给姓名初始化的构造方法
11     public Person(String nm) {
12         this.name = nm;
13     }
14 
15     // 给姓名和年龄初始化的构造方法
16     public Person(String nm, int a) {
17         // 由于已经存在给姓名进行初始化的构造方法 name = nm;因此只需要调用即可
18         // 调用其他构造方法,需要通过this关键字来调用
19         this(nm);
20         // 给年龄初始化
21         this.age = a;
22     }
23 }



六、this调用构造方法的原理图

  首先来上一段代码:

  



1 public class Person {
 2     private String name;
 3     private int age;
 4     
 5     // 无参构造方法
 6     public Person() {
 7         // 调用了有参的构造方法
 8         // 参数李斯,20传递给了变量name,age
 9         this("李四", 20);
10     }
11     // 有参构造方法
12     /*
13      *     构造方法,传递String,int
14      *     在创建对象的同时为成员变量赋值
15      * */
16     public Person(String name,int age) {
17         this.name = name;
18         this.age = age;
19     }
20 }
21 
22 // 测试代码
23 public class Test {
24     public static void main(String[] args) {
25         // 创建Person的对象,调用空参数的构造方法
26         // 运行的结果是默认的null和0
27         Person p = new Person();
28         
29         System.out.println(p.getAge());
30         System.out.println(p.getName());
31     }
32 }



  原理图:

JAVA的构造方法会返回对象吗 java构造方法能有返回值吗_JAVA的构造方法会返回对象吗_02

  分析:  

    1、先执行main方法,main方法压栈,执行其中的new Person(“李四”,20);
    2、堆内存中开辟空间,并为其分配内存地址0x01,,紧接着成员变量默认初始化(name=null age = 0);
    3、拥有两个参数的构造方法(Person(String nm , int a))压栈,在这个构造方法中有一个隐式的this,因为构造方法是给对象初始化的,那个对象调用到这个构造方法,this就指向堆中的那个对象。
    4、由于Person(String nm , int a)构造方法中使用了this(nm);构造方法Person(String nm)就会压栈,并将“张三”传递给nm。在Person(String nm , int a)构造方法中同样也有隐式的this,this的值同样也为0x33,这时会执行其中name = nm,即把“张三”赋值给成员的name。当赋值结束后Person(String nm , int a)构造方法弹栈。
    5、程序继续执行构造方法(Person(String nm , int a)中的age = a;这时会将23赋值给成员属性age。赋值结束构造方法(Person(String nm , int a)弹栈。
    6、当构造方法(Person(String nm , int a)弹栈结束后,Person对象在内存中创建完成,并将0x33赋值给main方法中的p引用变量

七、成员变量和局部变量的同名问题

  在平时的场景中,当方法中出现局部变量和成员变量同名的时候,那么在方法中怎么区分?

    可以在成员变量前面加上this来区分和局部变量



1 public class Person {
 2     private int age;
 3     private String name;
 4 
 5     // 给姓名和年龄初始化的构造方法
 6     public Person(String name, int age) {
 7         // 当需要访问成员变量是,只需要在成员变量前面加上this.即可
 8         this.name = name;
 9         this.age = age;
10     }
11 
12     public void speak() {
13         System.out.println("name=" + this.name + ",age=" + this.age);
14     }
15 }
16 
17 class PersonDemo {
18     public static void main(String[] args) {
19         Person p = new Person("张三", 23);
20         p.speak();
21     }
22 }



八、this的应用

  需求:在Person类中定义功能,判断两个人是否是同龄人

  



1 public class Person {
 2     private int age;
 3     private String name;
 4 
 5     // 给姓名和年龄初始化的构造方法
 6     public Person(String name, int age) {
 7         // 当需要访问成员变量是,只需要在成员变量前面加上this.即可
 8         this.name = name;
 9         this.age = age;
10     }
11 
12     public void speak() {
13         System.out.println("name=" + this.name + ",age=" + this.age);
14     }
15 
16     // 判断是否为同龄人
17     public boolean equalsAge(Person p) {
18         // 使用当前调用该equalsAge方法对象的age和传递进来p的age进行比较
19         // 由于无法确定具体是哪一个对象调用equalsAge方法,这里就可以使用this来代替
20         /*
21          * if(this.age == p.age) { return true; } return false;
22          */
23         return this.age = p.age;
24     }
25 }