当前位置: 首页 > 科技观察

深入解析Java构造函数调用和类初始化顺序

时间:2023-03-18 23:24:01 科技观察

Java中的构造函数,或者说构造函数,其实就是在创建类对象的实例并为该对象分配内存时调用的一段代码。它是一种用于初始化对象的特殊方法。也允许在声明构造函数时使用访问修饰符。掌握构造函数是有效学习Java的重要组成部分。因此,本文将讲述Java构造函数的创建规则、应用和初始化,以全面了解和掌握Java构造函数及相关情况。1.构造函数规则编写Java构造函数必须遵循的规则是:Java构造函数不能有显式的返回类型;它不能是抽象的、最终的、静态的或同步的);构造函数名称必须与其所属类的名称相同;构造函数的第一行原理调用构造函数。2.构造函数类型Java中有两种构造函数:1)默认构造函数或无参数构造函数Java默认构造函数没有参数。这就是为什么它也被称为无参数构造函数。Java默认构造函数的一般语法是:(){//必要的初始化代码}你需要知道的是,如果Java类中没有定义显式构造函数,Java编译器会自动为类创建一个类默认构造函数。根据对象的类型,默认构造函数为对象提供默认值或默认初始化。使用由javac(java编译器)自动创建的默认构造函数的缺点是程序员无法在事后设置或更改对象属性的初始值。例如:packagecom.learning;/****@authorSoloCui*/publicclassConstructorDemo{ConstructorDemo(){//无参构造函数System.out.println("成功执行构造函数,完成对象的创建。");}publicstaticvoidmain(String[]args){ConstructorDemocd=newConstructorDemo();}}运行输出结果如下:构造函数执行成功,对象创建完成。2)参数化构造函数任何带有参数(一个或多个)的Java构造函数都称为参数化构造函数。虽然参数化构造函数经常被用来为不同的Java对象提供不同的值,但它也可以为不同的Java对象提供相同的值,比如0或null。示例如下:packagecom.learning;/***参数化构造函数示例**@authorSoloCui*/publicclassParametersConstructor{intid;Stringname;ParametersConstructor(Stringn,inti){name=n;id=i;}voiddisplay(){System.out.println(""+id+""+name);}publicstaticvoidmain(Stringargs[]){ParametersConstructors1=newParametersConstructor("Solo",666);ParametersConstructors2=newParametersConstructor("崔",999);s1.display();s2.display();}}运行输出如下:666Solo999Cui3。构造函数调用构造函数除了创建对象时的常规调用外,构造函数还可以调用同一个类中的其他构造函数。这里有两种情况,即调用父类构造函数和调用当前子类构造函数。示例如下:1)这种形式调用packagecom.learning;/***一个有多个构造函数的类,这种形式调用其他构造函数*@authorAdministrator*/publicclassMyParent{MyParent(){System.out.println("无参构造设备已初始化...");}MyParent(Stringhello){this();System.out.println("Sayhello:"+hello);}publicstaticvoidmain(String[]args){newMyParent("你'reGreat!");}}这里必须注意,调用同一个类中其他构造函数的this()必须在构造函数的第一行,是否有参数取决于被调用的构造函数的实际情况。2)超形式调用这种调用是类继承关系的子类对父类的调用。代码示例如下:packagecom.learning;/***继承MyParent类,调用父类*@authorAdministrator*/publicclassMyChildextendsMyParent{Stringname="default";MyChild(){//super():编译器会隐式调用父类无参构造函数System.out.println("MyNameis"+name);}MyChild(Stringn){super("大秦帝国");//显式调用父类构造函数name=n;}voidshowName(){System.out.println("Nameis"+name);}publicstaticvoidmain(String[]args){MyChildchild=newMyChild();child.showName();MyChildchild2=newMyChild("Solo");child2.showName();}}请注意:当子类不调用父类构造函数时,编译器会隐式调用父类无参构造函数,即super();如果子类显式调用父类的构造函数,则必须在构造函数的第一行,super中的参数可以根据需要传入。还有一点要注意,this类构造函数的调用和super父子类的调用不能同时出现在同一个构造函数中。4.构造函数重载和方法一样,Java类中的构造函数也是可以重载的。构造函数重载是使用相同的构造函数名称但使用不同的参数列表。所有这些构造函数各自执行不同的任务。Java编译器通过列表中的参数总数及其类型来区分重载的构造函数。以下代码片段演示了Java中的构造函数重载:packagecom.learning;/***构造函数重载示例**@authorSoloCui*/publicclassOverloadConstructor{intid;Stringname;intage;OverloadConstructor(inti,Stringn){id=i;name=n;}OverloadConstructor(inti,Stringn,inta){id=i;name=n;age=a;}voiddisplay(){System.out.println("id="+id+";name="+name+";age="+age);}publicstaticvoidmain(Stringargs[]){OverloadConstructors1=newOverloadConstructor(333,"Solo");OverloadConstructors2=newOverloadConstructor(666,"Cui",25);s1.display();s2。display();}}运行输出如下:id=333;name=Solo;age=0id=666;name=Cui;age=255。构造函数和方法简单地说,Java方法就是一段具有特定名称的代码。在可访问的范围内,只需使用方法名称即可在程序中的任何位置调用它。您也可以将其理解为对数据进行操作并返回值(特定或无效)的子程序。Java构造函数是一种特殊类型的方法。两者在很多方面相似,但并不完全相同。以下是Java构造函数和Java方法之间最重要的一些区别:调用——子类通过super()隐式调用超类构造函数,而方法必须显式调用;当同一个类中有多个构造函数时,某个构造函数调用另一个构造函数时,使用this()的形式。this后面括号内的参数根据被调用的构造函数的参数确定;而方法调用是通过this+点(.)+方法名;编译器——Java编译器从不提供Java的默认方法。但是,如果Java类中没有定义构造函数,则Java编译器会提供默认构造函数;命名约定-Java构造函数的名称必须与类的名称相同。但是方法的名称可能与包含它的类的名称相同,也可能不同。调用次数-Java构造函数在对象创建期间仅被调用一次。Java方法可以根据需要多次调用;返回类型——Java方法必须有返回类型,但对于构??造函数则不需要;用法-方法用于公开Java对象的行为,而构造函数用于初始化同一对象的状态。6、拷贝构造函数虽然Java中没有提供拷贝构造函数,但是你可以将值从一个Java对象拷贝到另一个对象中,就像在C++中使用拷贝构造函数一样。除了使用构造函数将值从一个对象复制到另一个对象外,还可以通过:将一个对象的值赋值给另一个对象;或者使用Object类的clone()方法。以下程序演示了使用Java构造函数将值从一个Java对象复制到另一个:packagecom.learning;/***复制当前类的对象**@authorSoloCui*/publicclassSimpleCopy{intid;Stringname;SimpleCopy(inti,Stringn){id=i;name=n;}SimpleCopy(SimpleCopys){id=s.id;name=s.name;}voidshow(){System.out.println("id="+id+";name="+name);}publicstaticvoidmain(String[]args){Si??mpleCopys1=newSimpleCopy(138,"Solo");SimpleCopys2=newSimpleCopy(s1);s1.show();s2.show();}}7.类初始化Java中的类初始化分为两大类,即静态初始化和非静态初始化。在创建java对象时,程序总是依次调用各个父类的非静态初始化块,父类构造函数(总是以Object开头——Java中的祖先类)进行初始化,最后调用当前(子类))class非静态初始化块,构造函数执行初始化。例子如下,我们看一下它的初始化顺序:1)父类XParent:packagecom.learning;/***类初始化:父类**@authorAdministrator*/publicclassXParent{static{System.out.println("XParent:父类[静态]初始化块");}{System.out.println("XParent:父类[非静态]初始化块");}publicXParent(){System.out.println("XParent:父类无参数构造函数");}publicXParent(Stringname){System.out.println("XParent:父类参数化构造函数:name="+name);}}2)子类XChild:packagecom.learning;/***子类XChild初始化**@authorSolocui*/publicclassXChildextendsXParent{static{System.out.println("XChild:子类静态初始化块");}{System.out.println("XChild:子类非静态初始化块");}publicXChild(){this("Solo");System.out.println("XChild:没有参数的子类构造器");}publicXChild(Stringname){super(name);System.out.println("XChild:带参数的子类构造函数:name="+name);}publicstaticvoidmain(String[]args){XChildc1=newXChild("Tomy");XChildc2=newXChild();}}运行子类的输出是:XParent:parentclass[static]初始化块XChild:子类静态初始化块XParent:父类[non-static]初始化块XParent:parentclasswithparameterconstructor:name=TomyXChild:subclassnon-staticinitializationblockXChild:带参数的子类构造函数:name=TomyXParent:父类[非静态]初始化块XParent:带参数的父类构造函数:name=SoloXChild:子类非静态初始化块XChild:带参数的子类构造函数:name=SoloXChild:子类no-argumentconstructor所以,无论新实例化多少个对象,该类的所有父类及其自身的静态初始化块都只执行一次,而且是最先执行的初始化,在类的初始化之后调用class的初始化会依次执行父类的非静态初始化块、父类的构造函数、子类的非静态初始化块、子类的构造函数来完成初始化,称为object初始化;在子类的构造函数中,可以使用super显式调用父类的构造函数,也可以通过this调用本类的其他重载构造函数,调用哪个构造函数取决于调用时的参数类型。8.关于构造函数的常见问题以下是一些关于Java中构造函数的最常见问题。Q:构造函数有返回值吗?答:虽然您不能在Java构造函数中使用返回类型,但它确实会返回一个值。Java构造函数返回对当前类实例的引用。问:什么是Java中的构造函数链接?答:构造函数链接是Java编程语言中从其他构造函数调用构造函数的技术。this()方法用于调用同一个类的构造函数,super()方法用于调用父类的构造函数。Q:说说构造函数调用构造函数时this和super的区别。答:super和this只能在构造函数中调用,而且都必须在构造函数的第一行,所以super和this不会同时出现在同一个构造函数中。问:我可以在Java中从超类构造函数调用子类构造函数吗?答:没有。问:Java有析构函数吗?答:Java没有析构函数,因为它是一种垃圾收集语言。在Java中,无法预测对象何时会被销毁。问:除了初始化之外,Java构造函数还可以执行哪些任务?答:Java构造函数可以执行任何可以使用方法执行的操作。使用Java构造函数执行的一些最流行的任务是:调用方法;对象创建;启动线程等。问:Java中什么时候需要构造函数重载?答:当需要以多种不同方式初始化Java对象时,在Java中通常使用构造函数重载。问:如果我向Java构造函数添加返回类型会怎样?答:具有返回类型的Java构造函数将被视为典型的Java方法。最后,这就是Java构造函数的全部意义所在。掌握如何有效地使用构造函数是Java编程必备的核心技能之一。多练习,根据具体学习情况酌情使用。