作者:CHAITANYA SINGH

来源:https://www.koofun.com//pro/kfpostsdetail?kfpostsid=25

构造函数是用来初始化新创建的对象的代码块。构造函数类似于java中的实例方法(Instance Method),但它不是一个方法(Method),因为它没有返回类型。简而言之,构造函数和方法是不同的(在本指南的末尾将有更多的介绍)。人们经常把Java中的构造函数称为特殊类型的方法。

构造函数的名称必须与与类名相同,如下图中的java代码所示:

1
2
3
4
5
6
public class MyClass{
   //This is the constructor
   MyClass(){
   }
   ..
}

注意,构造函数名与类名必须一致,并且没有返回类型。

构造函数是如何工作的?

下面我们通过一个例子来帮助大家理解构造函数的工作原理。我们先创建一个名字叫MyClass的类:

1
MyClass obj = new MyClass();

以上代码的意思就是通过new关键字来创建类MyClass的对象并调用这个类的构造函数来初始化这个新创建的对象,然后把这个对象赋值给对象变量obj。语句new MyClass()表示创建一个新的关于类MyClass的对象并调用构造函数来初始化这个新创建的对象。

下面我们来通过代码实例来解释什么是新创建对象的初始化。

一个简单的java构造函数程序

这里我们基于类Hello创建了一个对象obj,然后我们显示这个对象的实例变量name的值。在构造函数里面,我们给变量name赋值“BeginnersBook.com”,在赋值语句里面的this关键字表示引用当前的对象。我们将在下一个教程中详细介绍this关键字。

1
2
3
4
5
6
7
8
9
10
11
public class Hello {
   String name;
   //Constructor
   Hello(){
      this.name = "BeginnersBook.com";
   }
   public static void main(String[] args) {
      Hello obj = new Hello();
      System.out.println(obj.name);
   }
}

输出:

1
BeginnersBook.com

构造函数的类型

构造函数有三种类型:默认构造函数、无参数构造函数和参数化构造函数。

默认构造函数

如果在类(class)中没有定义代码来实现任何构造函数,Java编译器将会在编译的字节码里面为你插入默认构造函数。不会在源代码(java文件)中找到它,因为默认构造函数是在编译期间由编译器插入到代码中,并且存在于.class文件中,所以你在源代码(java文件)里面是看不到这个默认构造函数的。这个过程如下图所示:

注:如果你在类(class)里面实现了任何构造函数,那么Java编译器将不会在你的代码中插入默认构造函数。

无参数构造函数

不带参数的构造函数称为无参数构造函数,其形式看上去与默认构造函数相同,但是无参数构造函数里面可以有任何代码,而默认构造函数里面则是空的。

注:虽然您可能会看到一些人声称默认构造函数和无参数构造函数是相同的,但实际上它们并不相同,只要是你写的构造函数,就不能称之为默认构造函数。

示例:无参数构造函数

1
2
3
4
5
6
7
8
9
10
class Demo
{
     public Demo()
     {
         System.out.println("This is a no argument constructor");
     }
     public static void main(String args[]) {
         new Demo();
     }
}

输出:

This is a no argument constructor

参数化构造函数

带参数的构造函数称为参数化构造函数。

示例1:参数化构造函数

在这个例子中,我们定义的类Employee里面有一个带有两个参数(id,name)的参数化构造函数。用这个类Employee创建两个对象,obj1和obj2,在创建obj1和obj2时都调用了这个参数化构造函数,分别往里面传了两套不同的参数:10245、"Chaitanya"和92232、"Negan",传进去的参数都赋值给了类的成员变量empId和empName,后面的代码把obj1和obj2的empId和empName分别打印出来,见下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Employee {
 
   int empId;  
   String empName;  
         
   //parameterized constructor with two parameters
   Employee(int id, String name){  
       this.empId = id;  
       this.empName = name;  
   }  
   void info(){
        System.out.println("Id: "+empId+" Name: "+empName);
   }  
        
   public static void main(String args[]){  
    Employee obj1 = new Employee(10245,"Chaitanya");  
    Employee obj2 = new Employee(92232,"Negan");  
    obj1.info();  
    obj2.info();  
   }  
}

输出:

1
2
Id: 10245 Name: Chaitanya
Id: 92232 Name: Negan

例2:参数化构造函数

在这个例子中,我们有两个构造函数,一个默认构造函数和一个参数化构造函数。当我们在使用new关键字创建对象而且不传递任何参数时,系统将调用默认构造函数,但是如果我们在使用new关键字创建对象的时候传递了参数,那么系统将调用与传递的参数列表匹配的参数化构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Example2
{
      private int var;
      //default constructor
      public Example2()
      {
             this.var = 10;
      }
      //parameterized constructor
      public Example2(int num)
      {
             this.var = num;
      }
      public int getValue()
      {
              return var;
      }
      public static void main(String args[])
      {
              Example2 obj = new Example2();
              Example2 obj2 = new Example2(100);
              System.out.println("var is: "+obj.getValue());
              System.out.println("var is: "+obj2.getValue());
      }
}

输出:

1
2
var is: 10
var is: 100

如果我们类中只实现了参数化构造函数,而没有实现默认构造函数(不带参数的),会发生什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Example3
{
      private int var;
      public Example3(int num)
      {
             var=num;
      }
      public int getValue()
      {
              return var;
      }
      public static void main(String args[])
      {
              Example3 myobj = new Example3();
              System.out.println("value of var is: "+myobj.getValue());
      }
}

输出:编译报错

原因:在代码Example3 myobj = new Example3();中,我们调用了类Example3里面的不含参数的默认构造函数,还记得我们在上面提到的,一旦我们在类里面有实现带参数的构造函数,那么编译器就不会自动在背后给我们插入不含参数的默认构造函数,而代码new Example3();调用了类(class)Example3的不存在的默认构造函数,当然编译就会报错啦!

如果我们从上面的代码中删除参数化构造函数的实现代码,那么程序编译和运行都不会有问题,因为编译器会在编译的过程中将默认构造函数插入到您的代码中。

构造函数链

当构造函数调用同一个类的另一个构造函数时,这称为构造函数链,见下图:

super()

每当我们调用子类构造函数时,它都隐式地调用了父类的构造函数,可以把这理解为编译器在子类构造函数的开头插入了super();语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyParentClass {
   MyParentClass(){
    System.out.println("MyParentClass Constructor");
   }
}
class MyChildClass extends MyParentClass{
   MyChildClass() {
    System.out.println("MyChildClass Constructor");
   }
   public static void main(String args[]) {
    new MyChildClass();
   }
}

输出:

1
2
MyParentClass Constructor
MyChildClass Constructor

构造函数重载

构造函数重载指的是同一个类里面定义实现了多个不同参数列表的构造函数,虽然这些构造函数的名字都是一样的(和类名一样),但在创建这个类的对象的时候,如果传进去的参数不同,调用的构造函数也是不同的。

Java的复制构造函数

复制构造函数用于将一个对象的值复制到另一个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class JavaExample{  
   String web; 
   JavaExample(String w){  
    web = w;
   }  
 
   /* This is the Copy Constructor, it 
    * copies the values of one object
    * to the another object (the object
    * that invokes this constructor)
    */
   JavaExample(JavaExample je){  
    web = je.web; 
   }  
   void disp(){
    System.out.println("Website: "+web);
   }  
 
   public static void main(String args[]){  
    JavaExample obj1 = new JavaExample("BeginnersBook");  
         
    /* Passing the object as an argument to the constructor
     * This will invoke the copy constructor
     */
    JavaExample obj2 = new JavaExample(obj1);  
    obj1.disp();  
    obj2.disp();  
   }  
}

输出:

1
2
Website: BeginnersBook
Website: BeginnersBook

要点回顾:

1. 每个类都有一个构造函数,不管它是普通类还是抽象类。

2. 构造函数不是方法,它们没有任何返回类型。

3. 构造函数名应该与类名匹配。

4. 构造函数可以使用任何访问说明符,它们也可以声明为私有。在java中可以使用私有构造函数,但是私有构造函数的作用域局限在类里面。

5. 我们也可以定义一个和类名相同的方法,但方法必须要定义返回值的数据类型,我们可以据此判断和类名相同的方法和构造函数的区别。

6. 如果我们没有在类中定义和实现任何构造函数,编译器就会在编译的时候自动在后台的代码中插入默认构造函数。

7. this()和super()这两个语句如果放在构造函数代码里面,一定要放在构造函数代码里面的第一行。如果我们的代码里面没有这两个语句,编译器会在后台的代码中自动插入这两个语句。

8. 构造函数可以重载(overload),但不能重写(override)。这意味着我们可以在类中重载(overload)构造函数,但不能重写(override)构造函数。

9. 构造函数不能继承。

10. 如果父类(super class)没有定义无参数构造函数(默认构造函数),那么编译器也不会自动在子类(child class)的后台代码里面自动插入默认构造函数。

11. 接口没有构造函数。

12. 抽象类可以有构造函数,抽象类的构造函数在创建具体类的对象的时候被调用到。

13. 构造函数代码里面还可以调用同一个类的另一个构造函数,使用方法就是通过调用this()方法,例如,在一个构造函数里面要调用另一个带参数的构造函数,可以用这样的写法:this(parameter list),这里parameter list就是传进去的几个参数。

构造函数(constructor)与方法(method)的区别

1. 构造函数的目的是初始化类的对象,而方法的目的是通过执行java代码来执行任务。

2. 构造函数不能是抽象的(abstract)、最终的(final)、静态的(static)和同步的(synchronised),而方法则可以是。

3. 构造函数没有返回类型,而方法有返回类型。

Java中的构造函数——通过示例学习Java编程(14)的更多相关文章

  1. Java中的数据类型——通过示例学习Java编程(5)

    作者:CHAITANYA SINGH 来源:https://www.koofun.com//pro/kfpostsdetail?kfpostsid=15 数据类型用来定义变量可以采用的值,例如,如果变 ...

  2. Java中的变量——通过示例学习Java编程(4)

    作者:CHAITANYA SINGH 来源:https://www.koofun.com/pro/kfpostsdetail?kfpostsid=14&cid= 变量是用来存放可以更改的值的容 ...

  3. java中的构造函数

    在c++中就学习了构造函数,今天学习java又碰到了构造函数,重新写一篇博客来理解一下 其实直接听这个词并不能理解这是什么,但其实看了它的作用,就很好理解了 当创建一个对象时,往往需要做一些初始化工作 ...

  4. Hash Map 在java中的解释及示例

    目录 HashMap在java中的应用及示例 HashMap的内部结构 HashMap的性能 同步HashMap HashMap的构造函数 HashMap的时间复杂度 HashMap的方法 1. vo ...

  5. Java中的构造函数和重载

    一.Java中的构造函数 构造函数是对象被创建时初始化对象的成员方法,它具有和它所在的类完全一样的名字.构造函数只能有入口参数,没有返回类型,因为一个类的构造方法的返回类就是类本身.构造函数定义后,创 ...

  6. Java中有关构造函数的一道笔试题解析

    Java中有关构造函数的一道笔试题解析 1.详细题目例如以下 下列说法正确的有() A. class中的constructor不可省略 B. constructor必须与class同名,但方法不能与c ...

  7. Java中的Swing及AWT又称GUI编程

    Java中的Swing及AWT又称GUI编程. 关于学习Java要不要学Swing及AWT,这个完全取决于个人的开发及发展方向. 如果从事web方向的开发,则可以不用学习Swing及AWT. 如果从事 ...

  8. java中myeclipse连接mysql问题(java.lang.ClassNotFoundException: com.mysql.jdbc.Driver)

    java中myeclipse连接mysql问题(java.lang.ClassNotFoundException: com.mysql.jdbc.Driver) 1.往项目中添加mysql-conne ...

  9. 第九节:详细讲解Java中的泛型,多线程,网络编程

    前言 大家好,给大家带来详细讲解Java中的泛型,多线程,网络编程的概述,希望你们喜欢 泛型 泛型格式:ArrayList list= new ArrayList(); ArrayList list= ...

随机推荐

  1. BZOJ_2064_分裂_状压DP

    BZOJ_2064_分裂_状压DP Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的 ...

  2. POJ(有向图求LCA)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 18013   Accept ...

  3. js中变量声明提前

    demo1: var a=10; function b(){alert(a); var a=20; alert(a)} b()//undefined 20 因为:js编译器在执行b这个函数时,会把函数 ...

  4. Docker入门(一):简介

    这个<Docker入门>系列文档,是我根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家 ...

  5. 最小化安装linux CentOS-6.6后 部署fastdfs +下载地址 很干很干的干货

    参考:http://blog.itpub.net/7734666/viewspace-1292485/ 安装一些必要软件 yum -y install wget gcc perl mkdir ~/zy ...

  6. C#设计模式(5)——建造者模式

    一.概念 建造者模式将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示. 二.模型 三.代码实现 /// <summary> /// 建造者模式的演变 /// 省略了指挥 ...

  7. SQLServer中连接个数及超时问题

    超时时间已到.超时时间已到,但是尚未从池中获取连接.出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小. 解决办法1.在代码里面,把未关闭的连接关闭2.扩大共享池,方法如下:解决方法可以是 ...

  8. linux控制USB的绑定/解绑

    linux控制USB的绑定/解绑 http://www.jianshu.com/p/57293f9be558 今天工作中遇到一个问题, 要用代码实现USB的enable和disable. 谷歌了一番, ...

  9. John 尼姆博弈

    John Little John is playing very funny game with his younger brother. There is one big box filled wi ...

  10. sqlserver2012——逻辑运算符

    ALL 如果一组的比较都为TRUE,则结果为true ANY如果玉足比较中任何一个为true,则结果为true AND 两个boll都为TRUE,则结果为TRUE OR 两个BOLL任何一个TRUE, ...