首页 > 编程知识 正文

java定义构造方法,java构造方法格式

时间:2023-05-04 00:29:05 阅读:173058 作者:3461

首先应该注意的是,Java的构造函数不是函数,所以并不是继承他。 这在我们为extends编写子类构造函数时很常见。 因此,我们编写super,即使子类的构造函数的参数与父类完全相同。 构造函数的修饰符比较是有限的,只有三个public private protected,其他例如任何修饰符都不能用于它。 这意味着构造函数不允许以抽象、同步、静态等访问限制以外的形式出名。 构造函数不是函数,所以没有返回值。 另外,也不允许返回值。 但是,在这里说明。 构造函数允许存在return语句,但return不返回任何内容。 如果提供返回值,编译器不会报告任何错误,但会认为JVM是与构造函数同名的函数。 因此,会出现找不到构造函数的莫名其妙的错误。 这里请加倍注意。 当我们是extends的子类时,经常会出现意想不到的问题,但现在我要谈一些与构造函数有关的事情。 首先,介绍了Java构建实例的顺序(不讨论加载类的过程)构建的大致过程: 1、分配对象空间,将空间内存初始化为二进制零,将对象成员初始化为0或空在Java中,用户不能与非定值对象进行操作。 2、执行属性值的显式初始化(这里有点奇怪,后面会介绍,大致是这样的) 3、执行构造函数4,将变量与堆中的对象相关联,介绍准备知识,之后再详细说明这个的过程this 用于对传递给当前构造函数的参数或构造函数中的数据调用其他构造函数或控制父类的构造函数。 构造函数只能使用this (或super )中的一个。 此外,调用方只有构造函数的第一行。 在子类中,如果要通过调用父类的构造函数初始化父类的部分,请使用适当的参数调用super )。 super ) )上调用父类的构造函数时,也不使用this。 调用父类的默认构造函数。 如果父类没有缺省构造函数,编译器将报告错误。 请注意这里。 继承父类时,构造函数通常不会包含有关父类的内容。 如果父类没有缺省构造函数,编译器添加的缺省构造函数将会打扰您。 例如,classbextendsa{publicb{}}没有有关父类的构造函数的信息,而是调用父类的缺省构造函数。

作为示例,SL-275示例1 publicclassmanagerextendsemployee {2privatestring department; 3公共管理器(string name,double salary,String dept )5super ) name,salary ); 6深度=深度; 7 } 8公共管理器(stringn,String dept )9super ) name; 10深度=深度; 11 ) 12公共管理器(字符串深度/此处为super ) )不可用。 编译器会自动添加空参数的默认super构造函数。 此时,如果Employee类没有空参数的默认构造函数,则编译器错误13 department=d。14 } 15 }必须将super或this构造函数放在构造函数的第一行。 否则,编译器将自动放置null参数的super构造函数。 其他构造函数也可以调用super或this作为递归构造函数调用。 最终,父类的构造函数(可能是多个级别的父类的构造函数)始终在子类的构造函数之前执行。 的递归调用父类构造函数在具体构建类实例的过程中,上面过程的第二步和第三步有一些变化。 在此处,当分配并初始化默认值的对象空间和对象成员时,将从继承树的根向下递归调用构造函数。 每个构造函数的执行过程如下: 1、Bind构造函数的参数2、如果显式调用了this,那么递归调用this构造函数并跳到步骤5-3,递归调用显式或隐式父类构造函数。 除了Object之外,没有其他父类4,因此要初始化显式实例变量,即执行上面过程中的第二个步骤,然后在调用返回后再执行。 此步骤看起来像是在执行父构造函数后隐式执行的特殊处理。 5、在构造函数的其他部分执行这里的步骤很重要哦! 此过程清楚地说明了初始化此实例时的递归调用过程。 我想看过这个之后,就能理解这个递归结构链是什么样的了。 这里还是给出SL-275中的一个例子,让我们充分理解这个递归的过程吧。 public class object { . publicobject { } { } . publicclassemployeextendsobject { privatestring name; private double salary=15000.00; private Date birthDate; publicemployee(stringn,Date DoB ) { //implicit super; name=n; birthDate=DoB; }公共元素(stringn ) this,null ); } publicclassmanagerextendsemployee { privatestringdepartmen }

t; public Manager(String n, String d) { super(n); department = d; } } 在创建Manager("高贵的心情 Smith","Sales"):时,步骤如下 0 basic initialization 0.1 allocate memory for the complete Manager object 0.2 initialize all instance variables to their default values (0 or null) 1 call constructor: Manager("高贵的心情 Smith", "Sales") 1.1 bind constructor parameters: n="高贵的心情 Smith", d="Sales" 1.2 no explicit this() call 1.3 call super(n) for Employee(String) 1.3.1 bind constructor parameters: n="高贵的心情 Smith" 1.3.2 call this(n, null) for Employee(String, Date) 1.3.2.1 bind constructor parameters: n="高贵的心情 Smith", DoB=null 1.3.2.2 no explicit this() call 1.3.2.3 call super() for Object() 1.3.2.3.1 no binding necessary 1.3.2.3.2 no this() call 1.3.2.3.3 no super() call (Object is the root) 1.3.2.3.4 no explicit variable initialization for Object 1.3.2.3.5 no method body to call 1.3.2.4 initialize explicit Employee variables: salary=15000.00;注意:在父构造器返回后子类才会初始化实例变量的值。 1.3.2.5 execute body: name="高贵的心情 Smith"; date=null; 1.3.3 - 1.3.4 steps skipped 1.3.5 execute body: no body in Employee(String) 1.4 no explicit initializers for Manager 1.5 execute body: department="Sales" 这个流程就说明了一切,这个步骤是要注意的。一会还有些内容是要涉及到这里的。 写在后边的一些在使用构造器中的注意事项。 一、构造器中一定不要创建自身的实例,否则会造成调用栈溢出错误。这个规则也适用于对象的实例变量,如果对象中有自身的引用,这个引用一定不能在定义中或者构造器中初始化。 class a { a _a = new a(); public a() { _a = new a(); a _b = new a(); } } 以上三种情况都会造成栈溢出,呵呵,这样会造成一个无穷递归的调用栈。 二、如果父类是一个抽象类,那通过调用父类的构造器,也可以将它初始化,并且初始化其中的数据。 三、如果你要在构造器中调用一个方法时,将该方法声明为private。 对于这个规则是需要一些说明的,假使你的父类构造器中要调用一个非静态方法,而这个方法不是private的又被子类所重载,这样在实际创建子类的过程中递归调用到了父类的构造器时,父类构造器对这个方法的调用就会由于多态而实际上调用了子类的方法,当这个子类方法需要用到子类中实例变量的时候,就会由于变量没有初始化而出现异常(至于为什么子类中的实例变量没有初始化可以参考上边的实例初始化过程),这是Java不想看到的情况。而当父类构造器中调用的方法是一个private方法时,多态就不会出现,也就不会出现父类构造器调用子类方法的情况,这样可以保证父类始终调用自己的方法,即使这个方法中调用了父类中的实例变量也不会出现变量未初始化的情况(变量初始化总是在当前类构造器主体执行之前进行)。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。