Java中构造函数的用途?

时间:2013-11-12 23:06:23

标签: java function methods constructor

构造函数的目的是什么?我一直在学习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
    }
}

构造函数的目的让我感到惊讶,但到目前为止我们所做的一切都非常简陋。

13 个答案:

答案 0 :(得分:45)

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

来自official Java tutorial

  

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

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

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

     

自行车myBike =新自​​行车(30,0,8);

     

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

     

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

     

public Bicycle(){           gear = 1;           cadence = 10;           速度= 0;       }

     

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

答案 1 :(得分:29)

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

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

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实例来存储一个没有意义的区间。

答案 2 :(得分:9)

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

示例:

假设你有一个类似<{p>}的Animal

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

让我们看看当你尝试创建一个Animal类的实例时会发生什么,比如名为Dog的{​​{1}}。现在,您必须初始化Puppyname = Puppy。那么,你怎么能这样做。一种方法是使用像

这样的构造函数
type = Dog

现在,当您创建类 Animal(String nameProvided, String typeProvided){ this.name = nameProvided; this.type = typeProvided; } 的对象时,会调用类似Animal的构造函数,并将名称和类型初始化为您提供的值,即Puppy和Dog。

现在你可能会问,如果我没有为我的构造函数提供类似

的参数
Animal dog = new Animal("Puppy", "Dog");

这是Animal xyz = new Animal(); ,它使用默认值初始化对象,即在我们的default ConstructorAnimalname对应type对象的值将为{ {1}}和xyz

答案 3 :(得分:4)

构造函数在创建对象时初始化对象。它与其类具有相同的名称,并且在语法上与方法类似,但构造函数没有expicit返回类型。通常,我们使用构造函数为类定义的实例变量赋予初始值,或执行任何其他操作制作完整形成的物体所需的启动程序。

以下是构造函数的示例:

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);

    }
} 

输出是:

98 98

这里的建设是:

queen(){
beauty =98;
}

现在转向参数化构造函数。

  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);

    }
} 

输出是:

100 98

答案 4 :(得分:3)

  • 通过构造函数(带参数),您可以“询问”该类的用户是否存在必需的依赖项。
  • 用于初始化实例变量
  • 并将参数传递给超类(super(...))的构造函数,它基本上是相同的
  • 它可以使用代码初始化(最终)实例变量,这可能会抛出异常,而不是instance initializer范围
  • 应该盲目地从构造函数中调用方法,因为在本地或派生类中初始化可能没有完成/足够。

答案 5 :(得分:1)

它用于设置班级的内容和状态。 虽然这是真的,你可以使用main方法制作更简单的例子,每个应用程序只有1个主要方法,所以它不是一个明智的方法。

考虑简单启动程序的主要方法,应该只知道如何做到这一点。另请注意,main()是静态的,因此无法调用需要类实例和关联状态的函数。 main方法应该调用new Program()。function(),并且Program构造函数不应该调用function(),除非它是设置类所必需的。

答案 6 :(得分:1)

类定义定义了类的API。换句话说,它是一个蓝图,用于定义类及其客户端之间存在的合同 - 使用此类的所有其他代码。合同表明哪些方法可用,如何调用它们以及期望什么方式。

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

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

从构造函数返回的此对象现在将遵循类定义中指定的契约,并且您可以使用此对象进行实际工作。

这样想。如果你看过保时捷的网站,你就会看到它能做什么 - 马力,扭矩等等。但是在你有一辆真正的保时捷驾驶之前它并不好玩。

希望有所帮助。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

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

答案 9 :(得分:1)

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

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

远不如我想的定义。

答案 10 :(得分:1)

构造函数将有助于防止实例获取不真实的值。例如,设置一个具有高度,重量的Person类。不能有0m和0kg的人

答案 11 :(得分:0)

好吧,首先我会告诉两个代码段中的错误。

第一个代码段

[ngClass]

正如您可以看到上面的代码,构造函数名称与类名称不同。在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 } } 创建对非静态方法函数()的静态引用,这是不可能的。

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

第一个代码段

Program

第二段代码

public class Program
{
    public Program()
    {
        function();
    }        
    private void function()
    {
        //do stuff
    }   

    public static void main(String[] args)
    {
        Program a = new Program();
        a.function();
    }
}

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

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

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

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

http://www.flowerbrackets.com/learn-constructor-in-java/

http://www.flowerbrackets.com/java-constructor-example/

答案 12 :(得分: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
  学生姓名是:约翰   学生部门是:CSE
  student2的详细信息是
  学生号码是:102
  学生年龄为:99岁   学生姓名是:彼得
  学生部门是:CSE
  student2的详细信息是
  学生号码是:102
  学生年龄为:99岁   学生姓名是:彼得
  学生部门是:CSE