用来进行构建创造的方法,在 Java 中构造方法是专门用来构建创造实例对象 并给创建出来的实例对象的成员变量进行初始化。
示例:
Person person = new Person()
这句话的本质上是方法的调用过程,只不过调用的是 Person 类的无参构造方法。
构造方法的格式:
修饰符 构造方法名(参数列表){//方法体
}
(1)构造方法没有返回值类型,因为它不需要写返回值类型,因为构造方法的作用就是用来构建构造方法所在类类型的实例对象,因此当构建完实例对象之后并对实例对象中的成员变量进行初始化后该方法就已经结束了。
(2)构造方法名必须和类名保持一致,如果当构造方法名和类名不一致的时候,此时方法就会被当成类中的普通成员方法,而普通的成员方法应该有返回值类型,这个时候就跟该方法没有返回值类型冲突了,因此编译出错。
(3)构造方法的方法体中可以有单独的 return 语句表示构造方法的结束,但是 return 关键字后面不能跟任何内容,因为构造方法是用来创建实例对象的,不需要返回值。
示例:
public class Person {private String name;/*** get方法* @return*/public String getName() {return name;}/*** set方法* @return*/public void setName(String name) {this.name = name;}/*** 无参构造器*/public Person (){}/*** 有参构造器* @param name*/public Person(String name){this.name = name;}/*** 把 Person 类型的实例对象以字符串的形式输出*/@Overridepublic String toString() {return name + "闪亮登场!";}}
public class Test {public static void main(String[] args) {//使用无参构造器创建对象并赋值Person person1 = new Person();person1.setName("person1");System.out.println(person1.toString());//使用有参构造器构建对象Person person2 = new Person("person2");System.out.println(person2.toString());}
}
打印结果:
构造器的注意事项
(1)当一个类中没有显式的定义任意一个构造器时,那么该类中就会默认有一个使用 public 关键字修饰的无参构造器。
(2)如果我们在一个类中显式的定义了有参构造器,那么该类中就不再有默认的使用 public 关键字修饰的无参构造器,如果想要使用无参构造器,只能够在当前类在显式的去声明一个无参构造器。
(3)使用构造器创建实例对象的时候,在构造器的方法体执行之前,该实例对象就已经存在了并进行了默认初始化的操作,构造器的方法体其实是对已经创建出来并进行了默认初始化的实例对象再次进行初始化的操作。
(4)同一个类中的多个构造器是以重载的形式存在的。
(5)构造器在实例对象创建的时候就已经开始执行了,因此对应一个实例对象而言,在整个创建的过程中,该构造器只能够执行一次,即创建一个实例对象构造器就执行一次,实例对象一旦创建出来直接就无法再调用构造器了。 对于的一般的成员方法是在实例对象创建出来之后由实例对象去调用的,并且是可以反复调用多 次。
(6)对于构造器而言,除了是以关键字 public 修饰,还可以是以其它的权限修饰符(private、 protected、不写),只不过不同的权限修饰符决定了构造器的使用权限,如果使用关键字 private 修饰,那么我们在其它类中就无法直接使用构造器创建该类的实例对象了,如果想要创建实例对象,只能通过其它方式了。
(7)一个类中至少存在一个构造器,有可能是显式声明的,也有可能是类中默认的 public 关键字修饰的无参构造器。
(8)构造器之间可以相互调用。
有了构造器之后,我们可以通过构造器在创建对象的时候对对象进行初始化的操作,即为成员变量 指定值,这个时候是不是说成员变量对应的 getter 和 setter 方法就不需要了?
需要,因为通过构造器我们只能对刚创建出来的实例对象进行初始化操作,但是对于一个实例对象而言,在使用的过程中成员变量的值并不是一成不变的,如果想要改变成员变量的值,此时通过构造器就无法完成了,这个时候就需要通过 setter 方法,同样的想要获取成员变量的值就得通过 getter 方法。
this 关键字
1、区分成员变量和局部变量
这个之前说过了。
2、调用构造器
通风关键字 this 可以在构造器中调用当前类中的其它构造器,即构造器之间的相互调用不能够通过构造器名的形式。
this(参数列表); //表示调用当前类中的其它构造器
具体调用哪一个构造器,由参数列表自己匹配。
使用 this 关键字在构造器中调用当前类的其它构造器时,this 语句必须放在构造器的方法体的第一行,否则编译出错。
示例:
public class Person {private String name;private String sex;/*** get方法* @return*/public String getName() {return name;}public String getSex() {return sex;}/*** set方法* @return*/public void setName(String name) {this.name = name;}public void setSex(String sex) {this.sex = sex;}/*** 无参构造器*/public Person (){}/*** 有1个参数的构造器* @param name*/public Person(String name){this.name = name;}/*** 有2个参数的构造器** @param name* @param sex*/public Person(String name,String sex) {this(name);this.sex = sex;}/*** 把 Person 类型的实例对象以字符串的形式输出*/@Overridepublic String toString() {return name + "是" + sex +"的!";}}
public class Test {public static void main(String[] args) {//使用无参构造器创建对象并赋值Person person1 = new Person();person1.setName("person1");person1.setSex("男");System.out.println(person1.toString());//使用1个有参构造器构建对象Person person2 = new Person("person2");person2.setSex("女");System.out.println(person2.toString());//使用2个有参构造器构建对象Person person3 = new Person("person3","男");person3.setSex("女");System.out.println(person3.toString());}
}
打印结果:
super 关键字
1、调用父类中的成员变量
这个之前也说过了。
2、调用父类中的成员方法
这个之前也说过了。
3、调用父类的构造器
当我们使用构造器去创建实例对象的时候,要创建的实例对象所属类的父类的构造器都会先执行, 如果在某个类的任意一个构造器中都没有显式的对父类构造器的调用,那么构造器的方法体中必然存在一个隐式的 super() 语句,表示调用父类的无参构造器。
当然我们也发现在类的某些构造器中存在使用 this 关键字调用当前类的其它构造器,此时存在用 this 关键字调用当前类的其它构造器的构造器中是不存在使用 super 关键字调用父类构造器的情况,如果存在由于使用 this 关键字调用当前类的其它构造器最终肯定会有使用 super 关键字对父类构造器的调用,也就会导致父类的构造器被调用了至少 2 次,因此编译报错。
同时也可以发现同一个构造器中是不可能同时出现 this 和 super 关键字。
为什么子类对象创建的时候一定要调用访问父类的构造器?
因为子类会继承父类中一切可继承的成员(成员变量以及成员方法),因此创建子类类型的实例对象的时候需要对从父类中继承而来的成员变量进行初始化的操作,而子类中并没有专门对从父类中继承而来的成员变量进行初始化的操作,因此就需要依赖父类的构造器对从父类中继承而来的成员变量进行 初始化的操作。
在类中的任意一个构造器中,如果没有显式的通过 this(参数列表) 的方式去调用当前类中的其它构造器或者通过 super(参数列表) 去调用父类中的其它构造器,那么在该构造器中必然存在一个隐式的 super() 语句,表示对父类无参构造器的调用,换而言之,在类中的任意一个构造器中必然存在对父类构造器的调用。
如果父类中没有声明定义一个无参构造器时该怎么办?
(1)在父类中手动的显式定义声明一个无参构造器。
(2)不再使用默认的 super() 语句对父类无参构造器进行调用,而是使用 super(参数列表) 方式调用父类中的有参构造器。
(3)通过 this(参数列表) 的方式去调用当前类中已经调用了父类中有参构造器的其它构造器,间接的调用父类的有参构造器。