构造函数的深入理解

构造器 :

             也叫构造方法(constructor),用于对象的初始化。构造器是一个创建对象时被自动调用的特殊方法,目的是对象的初始化。构造器的名称应与类的名称一致。Java通过new关键字来调用构造器,从而返回该类的实例,是一种特殊的方法。

放在最前面的图片: 

构造函数的关健特征:会在对象能够被赋值给引用之前就执行!

1.新建Duck状态的初始化

class Duck{
    int size;
    public Duck(){                    //构造函数
        System.out.println("Quack");
    }
    public void setSize(int newSize){
        size = newsize;
    }
}

public class UserADuck{
    public static void main(String[] args){
        Douck d = new Duck();    //Duck在此处已经建立,开始去调用构造函数,但是却没有size的值      

        d.setSize(42);           //我们必须在此处设立size的值
    }
}

2.使用构造函数来初始化Duck状态

class Duck{
    int size;
    public Duck(int duckSize){           //有参构造函数
        System.out.println("Quack");
        size = newsize;

    }
}

public class UserADuck{
    public static void main(String[] args){
        
        Douck d = new Duck(42);    //传值给构造函数  
    }
}

3.关于有参构造器和无参构造器

class Point {
    double x, y; //全局变量

//如果不添加有参构造器,系统默认构造无参构造器
    public Point(double x, double y) {       //局部变量
       this.x = x;   //this表示创建好的对象
       this.y = y;  
    }
    public double getDistance(Point p) {
        return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    }
}
public class TestConstructor {
    public static void main(String[] args) {
        Point p = new Point(3.0, 4.0);       //调用构造器
        Point origin = new Point(0.0, 0.0);
        System.out.println(p.getDistance(origin));
    }
}

4.构造函数的要点:

 1. 通过new关键字调用

 2. 构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return返回某个值。

 3. 如果我们没有定义构造器,则编译器会自动定义一个无参的构造函数。如果已定义则编译器不会自动添加!

 4. 构造器的方法名必须和类名一致!

 5. 构造函数的重载 

(重载的方法,实际是完全不同的方法,只是名称相同而已! )

   构成方法重载的条件:

1.不同的含义:形参类型、形参个数、形参顺序不同

2.只有返回值不同不构成方法的重载

构造方法也是方法,只不过有特殊的作用而已。与普通方法一样,构造方法也可以重载

public class User {
    int id; // id
    String name; // 账户名
    String pwd; // 密码
//无参构造
    public User() {
 
    }
//有参构造
    public User(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
//有参构造
    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public static void main(String[] args) {
        User u1 = new User();
        User u2 = new User(1563231, "小明");
        User u3 = new User(56891, "小红", "123456");     
    }
}

 6.调用父类构造函数

在创建对象时,所有继承下来的构造函数都会被执行!即每个父类的构造函数都会在子类对象创建时期执行。即使是抽象类也有构造函数,虽然我们不能对抽象类执行new操作,但是抽象类也是父类,因此它的构造函数会在子类创建出实例时执行。

在构造函数中,我们用super调用父类的构造函数的部分,这一路会调用到Object的构造函数为止,一路执行,然后逐个弹出。子类可能会根据父类的状态(实例变量)来继承方法,完整的对象需要完整的父类核心,所以必须执行父类的构造函数,来读取父类的实例变量,继而来继承父类的部分方法。

public class Animal {
    public Animal(){
        System.out.println("Making an animal.....");
    }
}
---------------------------------------------------------
public class Hippo extends Animal{
    public Hippo(){
        System.out.println("Making a Hippo.....");
    }
}
----------------------------------------------------------
public class main {
    public static void main(String[] args) {
        System.out.println("Staring....");
        Hippo h =new Hippo();
    }
}
--------------------------------------------------------
输出: Staring....
       Making an animal.....
       Making a Hippo...

内存编译过程:(如果对Java内存不了解的,可参考:内存管理) 

 这里我们为什么没有用到super呢?

1.如果你编写构造函数时,没有调用super,编译器会帮你自动加上super()的调用;

2.如果说你没有编写构造函数,但需要引用父类构造函数时,我们需要自行加入super();来调用父类构造函数。

 7.调用有参数的父类构造函数

这里通过super();来引用父类,把name的值传进去,让Animal把它存到私有的name实例变量中,继而才可以调用getName方法

public class Animal {
    private String name;
    public String getName(){
        return name;
    }
    public Animal(String theName){
        name = theName;
    }
}
---------------------------------------------
public class Hippo extends Animal{
    public Hippo(String name){
        super(name);            //传给Animal的构造函数
    }
}
----------------------------------------------
public class main {
    public static void main(String[] args) {
        System.out.println("Staring....");
        Hippo h =new Hippo("Buffy");         //创建Hippo,传入name
        System.out.println(h.getName());
    }
}
----------------------------------------------
输出:Buffy

8.调用super()和this()

this()的应用场景:如果说我们有某个重载版的构造函数,除了不能处理不同类型的参数之外,可以处理所有的工作,那么我们为了实现代码的易维护性,我们想让所有的构造函数都先去调用这个构造函数,然后由它来执行真正的构造函数。这时候我们就要用到this();

 注意:

super()和this()两者只会出现在第一行,而且同一个构造方法不能同时出现super()和this()

发布了43 篇原创文章 · 获赞 80 · 访问量 8745

猜你喜欢

转载自blog.csdn.net/qq_44717317/article/details/102884239