在我们创建实例时,我们经常需要同时初始化这个实例,例如:
Person ming =new Person();
ming.setName("卫什么");
ming.setAge("18");
这样需要三行代码,实际上,在我们创建实例时,是通过构造方法来初始化实例的,我们可以自己定义一个构造方法,使在创建Person实例时,一次性传入name和age,完成初始化:
public class Main{ public static void main(String[] args){Person p=new Person("卫什么",18);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 关键字
④在类中如果没有定义构造方法,会存一个默认无参的构造方法
默认的构造方法
任何类都有构造方法,在上一篇文章中,我们并没有为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;}
}
此时会发生编译错误,因为没有Person()这个构造方法。
多个构造方法
在一个类中,可以定义多个构造方法,在通过new关键字调用时,编译器会自动通过构造方法的:参数数量、类型、顺序来匹配不同的构造方法,例如:
public class Order_test{public static void main(String [] args){//创建一个订单对象//通过无参构造方法创建Order o1=new Order();o1.setPay(187.9);//保存金额//通过有参构造方法创建Order o2=new Order(157.92);//打印订单System.out.println("订单1:"+o1);System.out.println("订单2:"+o2);}
class Order {//成员变量private String orderNo;private double pay;//无参构造方法public Order(){//获取当前日期String now=LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));//流水号String trace=UUID.randmUUID().toString.subtring(0,5);//订单编号this.orderNo=now+trace;}//有参构造方法public Order(double pay){//调用无参构造方法,自动生成订单编号//构造方法的调用应当是当前构造方法的第一句this();//存入金额this.pay=pay;}//set和get方法public void setordreNo(String ordreNo) {this.orderNo=ordreNo;}public String getordreNo() {return orderNo;}public double getPay() {return pay;}public void setPay(double pay) {this.pay = pay;}}
此时,运行出的结果为:
为什么打印出的是订单的地址呢?因为Order对象是我们自己创建的,它没有自己的toString()方法,所以会默认使用父类Object的toString方法,如下:
所以我们要自己重写toString()方法,使其按照我们想输出的格式输出:
public class Order_test{public static void main(String [] args){//创建一个订单对象//通过无参构造方法创建Order o1=new Order();o1.setPay(187.9);//保存金额//通过有参构造方法创建Order o2=new Order(157.92);//打印订单System.out.println("订单1:"+o1);System.out.println("订单2:"+o2);}
class Order {//成员变量private String orderNo;private double pay;//无参构造方法public Order(){//获取当前日期String now=LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));//流水号String trace=UUID.randmUUID().toString.subtring(0,5);//订单编号this.orderNo=now+trace;}//有参构造方法public Order(double pay){//调用无参构造方法,自动生成订单编号//构造方法的调用应当是当前构造方法的第一句this();//存入金额this.pay=pay;}//toString()方法public String toString(){return String.format("订单编号:%s,订单金额:%f",this.getOrderNo(),this.getPay());//set和get方法public void setordreNo(String ordreNo) {this.orderNo=ordreNo;}public String getordreNo() {return orderNo;}public double getPay() {return pay;}public void setPay(double pay) {this.pay = pay;}}
输出结果:
构造代码块
语法特征:在每个构造方法执行前,自动调用,每次创建对象都会调用构造代码块一次,但是优先于构造方法,但是,如果不实例化对象,构造代码块是不会执行的,例如:
public class Employee_text{public static void main(String[] args){//调用无参的构造方法 Employee emp1=new Employee ();System.out.println(emp1); }}
class Employee{//成员变量(按照数据类型自动初始化)private String name;//nullprivate String job;//nullprivate double salary;//0.0private int level;//0//构造代码块{this.name="匿名";this.job="暂未分配岗位";this.salary=0.1;this.level=1; } //构造方法(无参)public Employee(){}public String toString() {return String.format("姓名:%s,岗位:%s,薪资:%f,等级:%d" ,this.getName(),this.getJob(),this.getSalary(),this.getLevel());}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public int getLevel() {return level;}public void setLevel(int level) {this.level = level;}
此时,无参构造方法中并未有任何语句,但是,构造代码块会在调用构造方法时在构造方法前执行,所以输出为:
当构造方法为有参构造方法时,传入的数据会将构造代码块中的数据覆盖:
public class Employee_text{public static void main(String[] args){//调用无参的构造方法 Employee emp1=new Employee ();System.out.println(emp1); //调用有参的构造方法Employee emp3=new Employee("jack");System.out.println(emp3);Employee emp2=new Employee("小佳","女明星",100000,10);System.out.println(emp2);}}
class Employee{//成员变量(按照数据类型自动初始化)private String name;//nullprivate String job;//nullprivate double salary;//0.0private int level;//0//构造代码块{this.name="匿名";this.job="暂未分配岗位";this.salary=0.1;this.level=1; } //构造方法(无参)public Employee(){}//有参构造方法1public Employee(String name) {this.name=name;}public String toString() {return String.format("姓名:%s,岗位:%s,薪资:%f,等级:%d" ,this.getName(),this.getJob(),this.getSalary(),this.getLevel());}//有参构造方法2public Employee(String name,String job,double salary,int level) {this.name=name;this.job=job;this.salary=salary;this.level=level;} public String getName() {return name;}public void setName(String name) {this.name = name;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public int getLevel() {return level;}public void setLevel(int level) {this.level = level;}
输出结果为:
姓名:匿名,岗位:暂未分配岗位,薪资:0.100000,等级:1
姓名:jack,岗位:暂未分配岗位,薪资:0.100000,等级:1
姓名:小佳,岗位:女明星,薪资:100000.000000,等级:10
注意:如果存在多个构造代码块,则按照书写顺序执行