在我们创建实例时,我们经常需要同时初始化这个实例,例如:
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;//null
private String job;//null
private double salary;//0.0
private 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;//null
private String job;//null
private double salary;//0.0
private int level;//0
//构造代码块
{
this.name="匿名";
this.job="暂未分配岗位";
this.salary=0.1;
this.level=1;
}
//构造方法(无参)
public Employee(){
}
//有参构造方法1
public Employee(String name) {
this.name=name;
}
public String toString() {
return String.format("姓名:%s,岗位:%s,薪资:%f,等级:%d"
,this.getName(),this.getJob(),this.getSalary()
,this.getLevel());
}
//有参构造方法2
public 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
注意:如果存在多个构造代码块,则按照书写顺序执行