Java之构造器

构造器的引入

  假设为编写的每个类都定义一个initialize()方法,这个方法提醒你在使用其对象之前,应首先调用initialize()方法,但这也意味着用户必须记得自己去调用此方法。

  为此,Java通过提供构造器让类的设计者确保每个对象都会得到初始化,在创建对象时,如果其类具有构造器,Java就会在用户操作对象之前自动调用相应的构造器,从而确保初始化的进行

构造器的命名

  命名有两个问题:第一,所取的任何名字都可能与类的某个成员名称相冲突;第二,调用构造器是编译器的责任,所以必须让编译器知道该调用哪个方法

  为此,Java让构造器采用与类相同的名称,这样看来最简单且更符合逻辑

 1 package com.constructor;
 2 
 3 class Rock {
 4     Rock(int i) {
 5         System.out.println("Rock " + i + " ");
 6     }
 7 }
 8 
 9 public class SimpleConstructor {
10     public static void main(String[] args) {
11         for(int i = 0; i < 5; i++)
12         {
13             new Rock(i);
14         }
15     }
16 }

  结果为:

1 Rock 0 
2 Rock 1 
3 Rock 2 
4 Rock 3 
5 Rock 4

构造器的几种方式以及特点

  1. 无参构造器(也叫默认构造器),当类中没有任何构造器时,Java会自动给类提供一个无参构造器,若有构造器,Java就不会为类提供无参构造器,需要用户自己编写
  2. 有参构造器,如上述代码,Rock构造器接收一个int类型的变量,就可以在初始化对象时提供实际参数,如果Rock(int i)是类中唯一的构造器,编译器不允许用户以其他任何方式创建创建Rock对象

 

构造器初始化原理

  代码:Person p = new Person();

  1. 创建一个Person类型的引用变量p
  2. 通过new关键字创建一个Person对象(也可以理解为将Person类实例化)
  3. Person对象里的全局变量赋初值,如int类型的变量初值为0,boolean类型的变量初值为false,String类型的变量初值为null等等
  4. new Person()小括号里若没有实际参数,则初始化结束,直接到第5步;若小括号里有参数,则根据参数的类型,顺序,数量,在类中查找相对应的构造器(方法重载),将实际参数传给形式参数
  5. Person对象的内存地址值复制给P引用变量,此时p指向堆内存的Person对象

 

扩展一

  构造器中最常见的几种运用:

  1. 用this关键字为全局变量赋值
  2. 用this关键字调用构造器
  3. 用super关键字调用父类构造器

  例一:用this关键字为全局变量赋值

 1 package com.constructor;
 2 
 3 class Person {
 4     String name;
 5     static int age;
 6     
 7     Person() {}
 8     
 9     Person(String name, int age) {
10         this.name = name;
11         this.age= age;
12     }
13 }
14 
15 public class HardConstructor {
16     public static void main(String[] args) {
17         Person p1 = new Person();
18         System.out.println("p1:name" + "---" + p1.name + " age" + "---" + p1.age);
19         Person p2 = new Person("Jhin", 21);
20         System.out.println("p2:name" + "---" + p2.name + " age" + "---" + p2.age);
21     }
22 }

  结果为:

1 p1:name---null age---0
2 p2:name---Jhin age---21

  例二:用this关键字调用本类构造器

 1 package com.constructor;
 2 
 3 class Person{
 4     Person() {
 5         this("Jhin", 21);
 6     }
 7     
 8     Person(String name, int age) {
 9         System.out.println("name:" + name + "---" + "age:" + age);
10     }
11 }
12 
13 public class HardConstructor {
14     public static void main(String[] args) {
15         Person s = new Person();
16     }
17 }

  结果为:

name:Jhin---age:21

  例三:用super关键字调用父类构造器

 1 package com.constructor;
 2 
 3 class Father {
 4     String name;
 5     static int age;
 6     
 7     Father() {
 8         System.out.println("这是父类无参构造器");
 9     }
10     
11     Father(String name, int age) {
12         this.name = name;
13         this.age = age;
14         System.out.println("这是父类有参构造器");
15     }
16 }
17 
18 class Son extends Father {
19     Son() {
20         super();
21     }
22     
23     Son(String name, int age) {
24         super(name, age);
25     }
26 }
27 
28 public class HardConstructor {
29     public static void main(String[] args) {
30         Son s1 = new Son();
31         Son s2 = new Son("Jhin", 21);
32     }
33 }

  结果为:

1 这是父类无参构造器
2 这是父类有参构造器

扩展二 

  讨论构造器是否属于静态方法?

  首先,从Java语言规范对“方法”的定义来来说,构造器根本不是方法,它没有返回值。尽管new表达式确实返回了对新建对象的引用,但构造器本身并没有任何返回值

  然后,构造器无法被重写无法被隐藏(若隐藏则无法创建对象,但工具类不同,它会隐藏构造器,方法全用static修饰,让用户通过类名调用方法),不参与多态

  其次,静态方法中不能使用this关键字,但构造器中可以使用this关键字,this是指调用当前方法的对象,而静态方法不属于任何对象

  最后,构造器只能由new关键字(或别的构造器)调用,不能通过方法调用,new表达式作为一个整体保证了对象的创建和初始化时打包在一起的,不能分开。且构造器只负责初始化,从创建对象是由new关键字本身执行的

posted @ 2019-01-18 11:54  漫画小生  阅读(175)  评论(0编辑  收藏  举报