`
yeluowuhen
  • 浏览: 155902 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

构造器

JVM 
阅读更多
构造器的调用过程:
首先要注意的是Java的构造器并不是函数,所以他并不能被继承,这在我们extends的时候写子类的构造器时比较的常见,即使子类构造器参数和父类的完全一样,我们也要写super就是因为这个原因。
  构造器的修饰符比较的有限,仅仅只有public private protected这三个,其他的例如任何修饰符都不能对其使用,也就是说构造器不允许被成名成抽象、同步、静态等等访问限制以外的形式。
  因为构造器不是函数,所以它是没有返回值的,也不允许有返回值。但是这里要说明一下,构造器中允许存在return语句,但是return什么都不返回,如果你指定了返回值,虽然编译器不会报出任何错误,但是JVM会认为他是一个与构造器同名的函数罢了,这样就会出现一些莫名其妙的无法找到构造器的错误,这里是要加倍注意的。
  在我们extends一个子类的时候经常会出现一些意想不到的问题,我在这里说一些和构造器有关的。
  首先说一下Java在构造实例时的顺序(不讨论装载类的过程)
  构造的粗略过程如下
  1、分配对象空间,并将对象中成员初始化为0或者空,java不允许用户操纵一个不定值的对象。
  2、执行属性值的显式初始化(这里有一点变化,一会解释,但大体是这样的)
  3、执行构造器
  4、将变量关联到堆中的对象上
  介绍一下准备知识,以备一会来详细说明这个的流程
  this()super()是你如果想用传入当前构造器中的参数或者构造器中的数据调用其他构造器或者控制父类构造器时使用的,在一个构造器中你只能使用this()或者super()之中的一个,而且调用的位置只能在构造器的第一行,在子类中如果你希望调用父类的构造器来初始化父类的部分,那就用合适的参数来调用super(),如果你用没有参数的super()来调用父类的构造器(同时也没有使用this()来调用其他构造器),父类缺省的构造器会被调用,如果父类没有缺省的构造器,那编译器就会报一个错误,注意此处,我们经常在继承父类的时候构造器中并不写和父类有关的内容,此时如果父类没有缺省构造器,就会出现编译器添加的缺省构造器给你添麻烦的问题了哦。例如:Classbextendsa{publicb(){}}就没有任何有关父类构造器的信息,这时父类的缺省构造器就会被调用。你必须在构造器的第一行放置super或者this构造器,否则编译器会自动地放一个空参数的super构造器的,其他的构造器也可以调用super或者this,调用成一个递归构造链,最后的结果是父类的构造器(可能有多级父类构造器)始终在子类的构造器之前执行,递归的调用父类构造器
  在具体构造类实例的过程中,上边过程的第二步和第三步是有一些变化的,这里的顺序是这样的,分配了对象空间及对象成员初始化为默认值之后,构造器就递归的从继承树由根部向下调用,每个构造器的执行过程是这样的:
  1、Bind构造器的参数
  2、如果显式的调用了this,那就递归调用this构造器然后跳到步骤5
  3、递归调用显式或者隐式的父类构造器,除了Object以外,因为它没有父类
  4、执行显式的实例变量初始化(也就是上边的流程中的第二步,调用返回以后执行,这个步骤相当于在父构造器执行后隐含执行的,看样子像一个特殊处理)
  5、执行构造器的其它部分
 
  从这个步骤中可以很明显的发现这个实例初始化时的递归调用过程,估计看过这个你应该能够理解这个递归构造链是怎么样回事了。

public class Object {
...
public Object() {}
...
}
public class Employee extends Object {
private String name;
private double salary = 15000.00;
private Date birthDate;
public Employee(String n, Date DoB) {
// implicit super();
name = n;
birthDate = DoB;
}
public Employee(String n) {
this(n, null);
}
}

public class Manager extends Employee {
private String department;
public Manager(String n, String d) {
super(n);
department = d;
}
}


在创建Manager("Joe 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("Joe Smith", "Sales")

1.1 bind constructor parameters: n="Joe Smith", d="Sales"

1.2 no explicit this() call

1.3 call super(n) for Employee(String)

1.3.1 bind constructor parameters: n="Joe Smith"

1.3.2 call this(n, null) for Employee(String, Date)

1.3.2.1 bind constructor parameters: n="Joe 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="Joe 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方法时,多态就不会出现,也就不会出现父类构造器调用子类方法的情况,这样可以保证父类始终调用自己的方法,即使这个方法中调用了父类中的实例变量也不会出现变量未初始化的情况(变量初始化总是在当前类构造器主体执行之前进行)。

构造器与方法的不同:

功能和作用的不同
构造器是为了创建一个类的实例。这个过程也可以在创建一个对象的时候用到:Platypus p1 = new Platypus();
相反,方法的作用是为了执行java代码。
修饰符,返回值和命名的不同
构造器和方法在下面三个方便的区别:修饰符,返回值,命名。和方法一样,构造器可以有任何访问的修饰: public, protected, private或者没有修饰(通常被package 和 friendly调用). 不同于方法的是,构造器不能有以下非访问性质的修饰: abstract, final, native, static, 或者 synchronized。
返回类型也是非常重要的。方法能返回任何类型的值或者无返回值(void),构造器没有返回值,也不需要void。
  最后,谈谈两者的命名。构造器使用和类相同的名字,而方法则不同。按照习惯,方法通常用小写字母开始,而构造器通常用大写字母开始。构造器通常是一个名词,因为它和类名相同;而方法通常更接近动词,因为它说明一个操作。
"this"的用法
构造器和方法使用关键字this有很大的区别。方法引用this指向正在执行方法的类的实例。静态方法不能使用this关键字,因为静态方法不属于类的实例,所以this也就没有什么东西去指向。构造器的this指向同一个类中,不同参数列表的另外一个构造器。在构造器中,如果要使用关键字this,那么,必须放在第一行,如果不这样,将导致一个编译错误。
"super"的用法
构造器和方法,都用关键字super指向超类,但是用的方法不一样。方法用这个关键字去执行被重载的超类中的方法。构造器使用super去调用超类中的构造器。同this一样,这行代码必须放在第一行,否则编译将出错。

编译器自动加入代码
编译器自动加入代码到构造器,对于这个,java程序员新手可能比较混淆。当我们写一个没有构造器的类,编译的时候,编译器会自动加上一个不带参数的构造器,例如:public class Example {}
编译后将如下代码:
public class Example {
Example() {}
}
   在构造器的第一行,没有使用super,那么编译器也会自动加上,例如:
public class TestConstructors {
   TestConstructors() {}
}
   编译器会加上代码,如下:
public class TestConstructors {
   TestConstructors() {
   super;
   }
}
继承
  构造器是不能被继承的。子类可以继承超类的任何方法。

总结


主题 构造器 方法
功能 建立一个类的实例 java功能语句
修饰 不能用bstract, final, native, static, or synchronized 能
返回类型 没有返回值,没有void 有返回值,或者void
命名 和类名相同;通常为名词,大写开头 通常代表一个动词的意思,小写开头
this 指向同一个类中另外一个构造器,在第一行 指向当前类的一个实例,不能用于静态方法
super 调用父类的构造器,在第一行 调用父类中一个重载的方法
继承 构造器不能被继承 方法可以被继承
编译器自动加入一个缺省的构造器 自动加入(如果没有)
编译器自动加入一个缺省的调用到超类的构造器 自动加入(如果没有) 不支持
分享到:
评论

相关推荐

    深入理解java构造器机理

    “深入理解Java构造器机理” 在 Java 编程语言中,构造器是一种特殊的方法,用于初始化对象的创建。它是 Java 类中最重要的一个概念。下面将深入讨论构造器的机理、执行顺序、作用及与其他概念的区别。 一、构造器...

    java 构造器的调用

    在Java编程语言中,构造器(Constructor)是一个特殊的方法,主要负责对象的初始化工作。当创建一个新的类实例时,构造器会被自动调用。构造器的名称必须与类名完全相同,且没有返回类型,包括void。理解并熟练运用...

    NX10.0后处理构造器

    "NX10.0后处理构造器"是一个用于创建、编辑和定制数控(NC)代码后处理程序的强大工具。在数控编程中,后处理是将高级的几何模型或刀具路径转换为特定机床语言(如G代码)的过程,使得机床能够理解和执行。此工具主要...

    对象和构造器

    "对象和构造器" 在 Java 程序设计中,对象和构造器是两个基本概念。对象是类的实例,构造器是创建对象的特殊方法。 类和对象 在 Java 中,每个对象都是一个类的实例。类是对对象的抽象,定义了对象的属性和行为。...

    NX10.0后处理构造器.rar

    《NX10.0后处理构造器:深入解析与应用》 NX10.0,作为UGS(Unigraphics Solutions)系列软件的版本之一,是Siemens PLM Software公司推出的高级三维计算机辅助设计、制造和工程分析(CAD/CAM/CAE)系统。其强大的...

    理解构造器--构造器和方法的区别

    【理解构造器与方法的区别】 在Java编程语言中,构造器和方法是两个核心概念,它们在类的定义和对象的创建中起着至关重要的作用。然而,它们之间存在着显著的差异,这些差异是理解面向对象编程的关键。 首先,构造...

    HYPERMILL五轴后处理构造器

    【标题】:“HYPERMILL五轴后处理构造器”是一种高级 CAM(计算机辅助制造)技术,用于定制和优化五轴机床的NC(数值控制)代码。它在制造流程中扮演着至关重要的角色,确保从设计到生产的无缝转换,提高加工效率和...

    JPA构造器的使用样例

    总的来说,JPA构造器的使用样例展示了如何通过自定义构造器将多表查询的结果映射到自定义的Java对象上,从而更方便地处理数据库查询结果。这种方法不仅可以减少手动转换数据的工作,还可以使代码更清晰、更易于理解...

    NX12.0.2.9 后处理构造器

    【NX12.0.2.9 后处理构造器】是UGS(Unigraphics Solutions)NX软件中的一个重要组成部分,主要用于创建自定义的数控(NC)代码,以适应各种机床和控制器的需求。UGS NX是一款强大的计算机辅助设计、制造和工程分析...

    构造器和方法的区别

    构造器和方法是Java编程语言中的两个核心概念,它们各自承担着不同的角色和功能,但初学者往往容易混淆。为了更好地理解和区分构造器与方法,本文将深入探讨这两个概念的关键差异,包括它们的功能、语法特性以及如何...

    NX9.0加工后处理构造器

    标题中的“NX9.0加工后处理构造器”是指UGS(Unigraphics Solutions)的NX9.0版本中的一个特定功能,它涉及到CAD/CAM/CAE一体化软件的后处理部分。在数控编程(NC Programming)中,后处理是将经过 CAM(计算机辅助...

    Java入门理解构造器

    ### Java入门理解构造器 #### 一、构造器的基本概念 在Java中,构造器(Constructor)是一种特殊的方法,主要用于初始化对象。构造器的名字必须与类名相同,并且没有返回类型,甚至连`void`也不可以有。构造器的...

    基于SpringBoot构造器注入循环依赖及解决方式

    在Spring Boot应用中,构造器注入是一种常见的依赖注入方式,但它可能会引发循环依赖的问题。循环依赖是指两个或多个Bean之间形成一个闭环,彼此依赖对方,导致Spring容器在初始化Bean时无法确定创建顺序,从而抛出...

    JS+HTML版表单构造器(Fom Builder)适合Web系统使用

    **Bootstrap表单构造器_files**可能是一个文件夹,包含了与Bootstrap表单构造器相关的资源文件,如CSS样式表、JavaScript库、图片和其他必要的Web资产。这些文件是构建和运行表单构造器所必需的,它们确保了表单构造...

    代码生成器,SQL构造器

    代码生成器和SQL构造器是两个紧密相关的工具,它们在软件开发过程中扮演着重要的角色,尤其是在提高效率和减少错误方面。下面将详细解释这两个概念及其相关知识点。 代码生成器是一种自动化工具,它能够根据预定义...

    bootstrap表单构造器

    5. **响应式设计**:由于基于Bootstrap,表单构造器创建的表单通常具有良好的响应式布局,能在不同设备上正常显示。 6. **数据处理**:可以集成后端代码,如PHP的CodeIgniter框架,用于处理表单提交的数据,实现...

    MyBatisPlus条件构造器带条件更新update使用示例代码

    在实际开发中,我们经常会遇到需要根据特定条件对数据进行更新的情况,MyBatisPlus的条件构造器就是为了解决这个问题而设计的。本文将详细介绍如何使用MyBatisPlus的条件构造器进行带条件的更新操作。 首先,我们...

    MyBatisPlus条件构造器 -Wrapper详解.ziw

    MyBatisPlus条件构造器 -Wrapper详解(为知笔记版,可用网页打开),详解wrapper条件构造器的各种使用方法及其扩展类的使用方法。

    spring介绍(set和构造器注入)

    标题中的“spring介绍(set和构造器注入)”是指在Spring框架中两种主要的依赖注入(Dependency Injection,简称DI)方式:setter注入和构造器注入。在Spring框架中,DI是一种核心特性,它允许我们解耦组件之间的关系...

    应用UG后处理构造器定制 海德汉iTNC530五轴加工中心后置程序

    【UG后处理构造器】是UG软件中用于创建和修改后处理程序的工具,它允许用户通过图形界面自定义NC程序的格式、输出内容及各个事件的处理方式。在【海德汉iTNC530五轴加工中心】的编程中,后处理构造器起到了关键作用...

Global site tag (gtag.js) - Google Analytics