构造方法
在创建对象实例时就把内部字段全部初始化为合适的值需要构造方法
- 构造方法必须与其类名相同,不必写方法的返回类型;
- 构造方法没有返回值,但可以有参数,并且可以重载。
- 构造方法只能在创建对象时用new命令调用。
先定义一个构造方法,能在创建Person
实例的时候,一次性传入name
和age
,完成初始化
public class Main {
public static void main(String[] args) {
Person p = new Person("Xiao Ming", 15);
System.out.println(p.getName());
System.out.println(p.getAge());
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) { //方法名就是类名
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
构造方法的名称就是类名。构造方法的参数没有限制,
在方法内部,也可以编写任意语句。但是,和普通方法相比,构造方法没有返回值(也没有void
),调用构造方法,必须用new
操作符。
默认构造方法
任何class都有构造方法
上篇文章中没有为Person类编写构造方法却可以调用new Person()是因为如果一个类没有定义构造方法,编译器会自动生成一个默认构造方法,它没有参数,也没有执行语句 如
class Person {
public Person() {
}
}
但是,如果自定义了一个构造方法,那么,编译器就不再自动创建默认构造方法:
public class Main {
public static void main(String[] args) {
Person p = new Person(); // 编译错误:找不到这个构造方法
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
如果既要能使用带参数的构造方法,又想保留不带参数的构造方法,那么只能把两个构造方法都定义出来:
public class Main {
public static void main(String[] args) {
Person p1 = new Person("Xiao Ming", 15); // 既可以调用带参数的构造方法
Person p2 = new Person(); // 也可以调用无参数构造方法
}
}
class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
没有在构造方法中初始化字段时,引用类型的字段默认是null
,数值类型的字段用默认值,int
类型默认值是0
,布尔类型默认值是false
:
class Person {
private String name; // 默认初始化为null
private int age; // 默认初始化为0
public Person() {
}
}
也可以对字段直接进行初始化:
class Person {
private String name = "Unamed";
private int age = 10;
}
在Java中,创建对象实例的时候,按照如下顺序进行初始化:
- 先初始化字段,例如,
int age = 10;
表示字段初始化为10
,double salary;
表示字段默认初始化为0
,String name;
表示引用类型字段默认初始化为null
; - 执行构造方法的代码进行初始化。
因此,构造方法的代码由于后运行,所以,如果既对字段进行初始化,又在构造方法中对字段进行初始化如
class Person {
private String name = "Unamed";
private int age = 10;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
new Person("Xiao Ming", 12)
的字段值最终由构造方法的代码确定。
多构造方法
可以定义多个构造方法,在通过new操作符调用的时候,编译器通过构造方法的参数数量、位置和类型自动区分:
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name) {
this.name = name;
this.age = 12;
}
public Person() {
}
}
如果调用new Person("Xiao Ming", 20);
,会自动匹配到构造方法public Person(String, int)
。
如果调用new Person("Xiao Ming");
,会自动匹配到构造方法public Person(String)
。
如果调用new Person();
,会自动匹配到构造方法public Person()
。
一个构造方法可以调用其他构造方法,这样做的目的是便于代码复用。调用其他构造方法的语法是this(…)
:
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name) {
this(name, 18); // 调用另一个构造方法Person(String, int)
}
public Person() {
this("Unnamed"); // 调用另一个构造方法Person(String)
}
}
this()
this
定义为被调用的方法的当前对象的引用。this
引用仅能出现在类中的方法中。
可以使用this
来显式地引用屏蔽的域。
通过this
不但可以引用成员变量
,也可通过this
引用方法
,包括构造函数
。
例
import java.text.DecimalFormat;
public class Time3 {
private int hour; // 0 - 23
private int minute; // 0 - 59
private int second; // 0 - 59
public void setTime( int h, int m, int s ){
this.setHour( h );
this.setMinute( m );
setSecond( s );
}
//构造函数只有在创建对象时可以使用,以下为5个重载的构造函数
public Time3(){ //改为public void Time3()是否可以?? 继承
setTime( 0, 0, 0 );
}
public Time3( int h ) {
setTime( h, 0, 0 );
}
public Time3( int h, int m ){
setTime( h, m, 0 );
}
public Time3( int h, int m, int s ) {
this(h,m);
this.setMinute(s);
}
public Time3( Time3 time ){
setTime( time.hour, time.minute, time.second );
}
public void setHour( int hour ){ //setHour方法 形参改为hour,如何处理?
this.hour = ( ( hour >= 0 && hour < 24 ) ? hour : 0 );
}
public void setMinute( int m ){ //setMinute方法
minute = ( ( m >= 0 && m < 60 ) ? m : 0 );
}
public void setSecond( int s ){ //setSecond方法
second = ( ( s >= 0 && s < 60 ) ? s : 0 );
}
public int getHour(){ //getHour方法
return hour;
}
public int getMinute(){ //getMinute方法
return minute;
}
public int getSecond(){ // getSecond方法
return second;
}
public String toUniversalString(){
DecimalFormat twoDigits = new DecimalFormat( "00" );
return twoDigits.format( hour ) + ":" +
twoDigits.format( minute ) + ":" + twoDigits.format( second );
}
public String toStandardString(){
DecimalFormat twoDigits = new DecimalFormat( "00" );
return ( (hour == 12 || hour == 0) ? 12 : hour % 12 ) + ":" +
twoDigits.format( minute ) + ":" + twoDigits.format( second ) +
( hour < 12 ? " AM" : " PM" );
}
}
public class TimeTest3 {
public static void main( String args[] ){
Time3 t1 = new Time3(); // 00:00:00
Time3 t2 = new Time3( 2 ); // 02:00:00
Time3 t3 = new Time3( 21, 34 ); // 21:34:00
Time3 t4 = new Time3( 12, 8, 42 ); // 12:08:42
Time3 t5 = new Time3( t4 ); // 12:08:42
String output = "Constructed with: " +
"\nt1: all arguments defaulted" +
"\n " + t1.toUniversalString() +
"\n " + t1.toStandardString();
output += "\nt2: hour specified; minute and second defaulted" +
"\n " + t2.toUniversalString() +
"\n " + t2.toStandardString();
output += "\nt3: hour and minute specified; second defaulted" +
"\n " + t3.toUniversalString() +
"\n " + t3.toStandardString();
output += "\nt4: hour, minute and second specified" +
"\n " + t4.toUniversalString() +
"\n " + t4.toStandardString();
output += "\nt5: Time3 object t4 specified" +
"\n " + t5.toUniversalString() +
"\n " + t5.toStandardString();
System.out.println(output);
}
}
简单例
public class Main {
public static void main(String[] args) {
Person ming = new Person("小明", 12);
System.out.println(ming.getName());
System.out.println(ming.getAge());
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name) {
this(name, 18);
}
public Person() {
this("Unnamed");
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}