23

构造函数的目的是什么?我在学校一直在学习 Java,在我看来,在我们迄今为止所做的事情中,构造函数在很大程度上是多余的。是否有目的还有待观察,但到目前为止,这对我来说似乎毫无意义。例如,以下两段代码有什么区别?

public class Program {    
    public constructor () {
        function();
    }        
    private void function () {
        //do stuff
    }    
    public static void main(String[] args) { 
        constructor a = new constructor(); 
    }
}

这就是我们被教导如何做作业的方式,但下面的人不会做同样的事情吗?

public class Program {    
    public static void main(String[] args) {
        function();
    }        
    private void function() {
        //do stuff
    }
}

构造函数的目的使我无法理解,但是到目前为止,我们所做的一切都非常初级。

4

13 回答 13

49

构造函数用于初始化类的实例。您通常使用构造函数来创建新对象,参数指定初始状态或有关对象的其他重要信息

来自官方 Java 教程

一个类包含被调用以从类蓝图创建对象的构造函数。构造函数声明看起来像方法声明——除了它们使用类的名称并且没有返回类型。例如, Bicycle 有一个构造函数:

public Bicycle(int startCadence, int startSpeed, int startGear) {
    gear = startGear;
    cadence = startCadence;
    speed = startSpeed;
}

为了创建一个名为 的新 Bicycle 对象myBike,new 运算符调用了一个构造函数:

自行车 myBike = new Bicycle(30, 0, 8);

new Bicycle(30, 0, 8)在内存中为对象创建空间并初始化其字段。

虽然 Bicycle 只有一个构造函数,但它可以有其他构造函数,包括无参数构造函数:

公共自行车(){齿轮= 1;节奏= 10;速度 = 0; }

Bicycle yourBike = new Bicycle();调用无参数构造函数来创建一个名为 yourBike 的新 Bicycle 对象。

于 2013-11-12T23:08:02.610 回答
31

构造函数基本上是一种方法,您可以使用它来确保您的类的对象天生有效。这是构造函数的主要动机。

假设您希望您的类有一个整数字段,该字段应始终大于零。您如何以可靠的方式做到这一点?

public class C {
     private int number;

     public C(int number) {
        setNumber(number);
     }

     public void setNumber(int number) {
        if (number < 1) {
            throws IllegalArgumentException("C cannot store anything smaller than 1");
        }
        this.number = number;
     }
}

在上面的代码中,您可能看起来像是在做一些多余的事情,但实际上您要确保无论如何该数字始终有效。

“初始化类的实例”是构造函数的作用,但不是我们拥有构造函数的原因。问题是关于构造函数的目的。您还可以使用c.setNumber(10)上面的示例在外部初始化类的实例。所以构造函数不是初始化实例的唯一方法。

构造函数这样做,但以一种安全的方式。换句话说,一个类单独解决了确保其对象始终处于有效状态的整个问题。不使用构造函数会将这种验证留给外界,这是一个糟糕的设计。

这是另一个例子:

public class Interval {
    private long start;
    private long end;

    public Interval(long start, long end) {
        changeInterval(start, end);
    }

    public void changeInterval(long start, long end) {
        if (start >= end) {
            throw new IllegalArgumentException("Invalid interval.");
        }
        this.start = start;
        this.end = end;
    }
    public long duration() {
        return end - start;
    }
}

Interval 类表示时间间隔。时间使用 long 存储。在开始之前结束的间隔没有任何意义。通过使用像上面这样的构造函数,不可能在任何给定时刻在系统中的任何地方都有一个 Interval 实例,该实例存储了一个没有意义的间隔。

于 2013-11-12T23:15:07.017 回答
10

正如 LotusUNSW 回答中提到的,构造函数用于初始化类的实例。

例子:

假设你有一个Animal类似的课程

class Animal{
   private String name;
   private String type;
}

让我们看看当您尝试创建 Animal 类的实例时会发生什么,比如Dog命名的Puppy。现在你必须初始化name = Puppytype = Dog. 那么,你怎么能做到这一点。一种方法是拥有一个像这样的构造函数

    Animal(String nameProvided, String typeProvided){
         this.name = nameProvided;
         this.type = typeProvided;
     }

现在,当您创建 class 的对象时Animal,会调用类似于Animal dog = new Animal("Puppy", "Dog");构造函数的东西并将 name 和 type 初始化为您提供的值,即分别为 Puppy 和 Dog。

现在你可能会问,如果我没有为我的构造函数提供一个参数,比如

Animal xyz = new Animal();

这是一个default Constructor用默认值初始化对象的方法,即在我们的Animal类中name,与对象type对应的值xyzname = nulltype = null

于 2013-11-12T23:20:22.367 回答
4

A constructor initializes an object when it is created . It has the same name as its class and is syntactically similar to a method , but constructor have no expicit return type.Typically , we use constructor to give initial value to the instance variables defined by the class , or to perform any other startup procedures required to make a fully formed object.

Here is an example of constructor:

class queen(){
   int beauty;

   queen(){ 
     beauty = 98;
   }
 }


class constructor demo{
    public static void main(String[] args){
       queen arth = new queen();
       queen y = new queen();

       System.out.println(arth.beauty+" "+y.beauty);

    }
} 

output is:

98 98

Here the construcor is :

queen(){
beauty =98;
}

Now the turn of parameterized constructor.

  class queen(){
   int beauty;

   queen(int x){ 
     beauty = x;
   }
 }


class constructor demo{
    public static void main(String[] args){
       queen arth = new queen(100);
       queen y = new queen(98);

       System.out.println(arth.beauty+" "+y.beauty);

    }
} 

output is:

100 98
于 2016-01-06T13:46:45.273 回答
3
  • 通过构造函数(带有参数),您可以“询问”该类的用户所需的依赖项。
  • 用于初始化实例变量
  • 并将参数传递给超类 ( super(...)) 的构造函数,它的作用基本相同
  • 它可以使用可能引发异常的代码初始化(最终)实例变量,而不是实例初始化器作用域
  • 不应盲目从构造函数中调用方法,因为在本地或派生类中初始化可能没有完成/不够。
于 2013-11-12T23:11:01.267 回答
2

Java 构造函数的名称与其所属的类的名称相同。

构造函数的语法不包括返回类型,因为构造函数从不返回值。

创建对象时始终调用构造函数。示例:- 默认构造函数

class Student3{  
    int id;  
    String name;  
    void display(){System.out.println(id+" "+name);}  
    public static void main(String args[]){  
        Student3 s1=new Student3();  
        Student3 s2=new Student3();  
        s1.display();  
        s2.display();  
    }  
} 

输出:

0 null
0 null

说明:在上面的类中,您没有创建任何构造函数,因此编译器为您提供了一个默认构造函数。这里默认构造函数提供了 0 和 null 值。

参数化构造函数示例

在此示例中,我们创建了具有两个参数的 Student 类的构造函数。我们可以在构造函数中有任意数量的参数。

class Student4{  
    int id;  
    String name;  
    Student4(int i,String n){  
        id = i;  
        name = n;  
    }  
    void display(){System.out.println(id+" "+name);}  
    public static void main(String args[]){  
        Student4 s1 = new Student4(111,"Karan");  
        Student4 s2 = new Student4(222,"Aryan");  
        s1.display();  
        s2.display();  
    }  
}  

输出:

111 Karan
222 Aryan
于 2015-03-22T12:44:20.427 回答
1

构造函数主要用于在创建对象时初始化变量

于 2015-02-24T08:03:36.353 回答
1

类定义为您的类定义 API。换句话说,它是一个蓝图,定义了类与其客户之间存在的契约——所有其他使用这个类的代码。合约指明了哪些方法可用,如何调用它们,以及期望得到什么回报。

但是类定义是一个规范。在您拥有此类的实际对象之前,合同只是“一张纸”。这就是构造函数的用武之地。

构造函数是通过在内存中创建对象并返回对它的引用来创建类实例的方法。构造函数中应该发生的事情是对象处于适当的初始状态,以便对对象的后续操作有意义。

从构造函数返回的这个对象现在将遵守类定义中指定的约定,您可以使用这个对象来做实际的工作。

这样想吧。如果您查看保时捷网站,您会看到它可以做什么——马力、扭矩等。但是,除非您有一辆真正的保时捷可以驾驶,否则它并不有趣。

希望有帮助。

于 2013-11-12T23:21:45.063 回答
1

它用于设置课程的内容和状态。虽然确实可以使用 main 方法制作更简单的示例,但每个应用程序只有 1 个 main 方法,因此它不是一种明智的方法。

考虑简单地启动程序的主要方法,并且应该只知道如何执行此操作。还要注意 main() 是静态的,因此不能调用需要类实例和相关状态的函数。main 方法应该调用 new Program().function() 并且 Program 构造函数不应该调用 function() ,除非它是设置类所必需的。

于 2013-11-12T23:14:02.480 回答
1

我认为构造函数可能像数据库一样工作,其中只有它定义变量和控制它们的方法

然后我看到了使用未在其构造函数中定义的变量和方法的对象。因此,对我来说最有意义的讨论是测试变量值的有效性,但是该类可以创建未在构造函数中定义的变量和方法 - 不像数据库,更像是蒸汽上的过压阀机车。它不控制车轮等。

远比我想象的要少。

于 2016-07-27T21:59:11.237 回答
1

构造函数将有助于防止实例获得不真实的值。例如,使用身高、体重设置 Person 类。不可能有 0m 和 0kg 的人

于 2017-09-28T03:21:24.257 回答
0

好吧,首先我将在两个代码片段中告诉错误。

第一个代码片段

public class Program
{
    public constructor() // Error - Return type for the method is missing
    {
        function();
    }        
    private void function()
    {
        //do stuff
    }   
    
    public static void main(String[] args)
    {
        constructor a = new constructor(); // Error - constructor cannot be resolved to a type
    }
}

正如您在上面的代码中看到的,构造函数名称与类名称不同。在main()方法中,您从没有返回类型的方法创建对象。

第二个代码片段

public class Program
{
    public static void main(String[] args)
    {
        function(); // Error - Cannot make a static reference to the non-static method function() from the type Program
    }
    
    private void function()
    {
        //do stuff
    } 
}

现在,在此代码片段中,您尝试从 type 创建对非静态方法 function() 的静态引用Program,这是不可能的。

所以可能的解决方案是这样的,

第一个代码片段

public class Program
{
    public Program()
    {
        function();
    }        
    private void function()
    {
        //do stuff
    }   
    
    public static void main(String[] args)
    {
        Program a = new Program();
        a.function();
    }
}

第二个代码片段

public class Program
{
    public static void main(String[] args)
    {
        Program a = new Program();
        a.function();
    }
    
    private void function()
    {
        //do stuff
    } 
}

最后,代码片段之间的区别在于,在第一个代码片段中,类名与类名不同

而在第二个代码片段中没有定义构造函数。

同时要了解构造函数的目的,请参考以下资源,

https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html

https://www.flowerbrackets.com/constructor-in-java/

于 2017-11-29T13:36:33.273 回答
0

假设我们正在存储 3 个学生的学生详细信息。这 3 名学生的 sno、sname 和 sage 值不同,但所有 3 名学生都属于同一部门的 CSE。因此最好在构造函数中初始化“dept”变量,以便所有 3 个学生对象都可以获取该值。

为了清楚地理解,请看下面的简单示例:

class Student
{
    int sno,sage;
    String sname,dept;
    Student()
    {
        dept="CSE";
    }
    public static void main(String a[])
    {
        Student s1=new Student();
        s1.sno=101;
        s1.sage=33;
        s1.sname="John";

        Student s2=new Student();
        s2.sno=102;
        s2.sage=99;
        s2.sname="Peter";


        Student s3=new Student();
        s3.sno=102;
        s3.sage=99;
        s3.sname="Peter";
        System.out.println("The details of student1 are");
        System.out.println("The student no is:"+s1.sno);
        System.out.println("The student age is:"+s1.sage);
        System.out.println("The student name is:"+s1.sname);
        System.out.println("The student dept is:"+s1.dept);


        System.out.println("The details of student2 are");`enter code here`
        System.out.println("The student no is:"+s2.sno);
        System.out.println("The student age is:"+s2.sage);
        System.out.println("The student name is:"+s2.sname);
        System.out.println("The student dept is:"+s2.dept);

        System.out.println("The details of student2 are");
        System.out.println("The student no is:"+s3.sno);
        System.out.println("The student age is:"+s3.sage);
        System.out.println("The student name is:"+s3.sname);
        System.out.println("The student dept is:"+s3.dept);
    }
}

输出:

student1 的详细信息是
学生编号是:101
学生年龄是:33
学生姓名是:John
学生部门是:CSE
student2 的详细信息是
学生编号是:102
学生年龄是:99
学生姓名是:Peter
学生部门是:CSE
student2 的详细信息是
学生编号是:102
学生年龄是:99
学生姓名是:Peter
学生部门是:CSE

于 2017-12-29T05:12:52.043 回答