构造函数和方法之间的区别

时间:2014-11-09 02:14:54

标签: java methods constructor

Bellow是我在Tutorials Points上发现的一个例子,它是一个构造函数的例子。我得到了大部分,但我不知道为什么你需要一个构造函数一个方法。

public Puppy(String name){
    System.out.println("Passed Name is :" + name ); 
}

我的问题是,是什么阻止你这样做呢?

public static void Puppy(String name){
    System.out.println("Passed Name is: "+name);
}

这两个人做过同样的事情吗?

以下是完整的参考程序:

public class Puppy {
    int puppyAge;

    public Puppy(String name) {
        System.out.println("Passed Name is :" + name); 
    }

    public void setAge(int age) {
        puppyAge = age;
    }

    public int getAge() {
        System.out.println("Puppy's age is :" + puppyAge); 
        //what does this return do? since the puppyAge is already printed above.
        return puppyAge;
    }

    public static void main(String []args){
        Puppy myPuppy = new Puppy("tommy");

        myPuppy.setAge(2);
        myPuppy.getAge();

        System.out.println("Variable Value :" + myPuppy.puppyAge); 
    }
}

14 个答案:

答案 0 :(得分:22)

您没有获得实例的基本概念,这是OOP的基础。如果你想要一个比喻,让我们谈谈汽车。

我很确定你知道汽车是什么;你知道它可以让你从一个地方移动到另一个地方,它有4个轮子,依此类推。这是一个概念,你车库中的实际车辆是这个概念的实例< => class )。

构造函数的目标是创建一个实例,而不是打印一些文本。如果没有构造函数,您将永远无法调用类的非静态方法。你将无法驾驶汽车的概念,你需要先建造一辆汽车。

回顾这些概念;没有它,你将无处可去。

答案 1 :(得分:10)

我猜你的问题是为什么构造函数是用...创建的

public Puppy(String name)

......而不是......

public static void Puppy(String name)

......,对吧?

如果是,首先你应该建立一个构造函数是特殊方法,只要你创建该类的新实例,就会调用该类。所以,例如,如果你有这个类......

public class Clazz {
    public Clazz (String s) {
         System.out.println(s);
    }
}

...,然后每当你创建这个类的新实例时......

Clazz c = new Clazz("Hello World");

...,将调用构造函数并执行该方法。 (在此示例中,它将在屏幕上打印“Hello World”。)

也就是说,您可以看到构造函数是一个方法,但它是一个在实例化类时调用的特殊方法。所以,关于你的问题,构造函数是正确的而不是常规方法头的原因是向编译器指示它是构造函数不是是常规的方法。如果你写public void Clazz ()而不是public Clazz (),那么编译器将无法识别你的构造函数,并认为它只是一个常规方法。

请注意,构造函数永远不会返回任何内容,因此没有必要使用 void 关键字。此外,将构造函数设置为静态是没有意义的,因为在实例化新对象时会调用构造函数。

答案 2 :(得分:5)

构造函数ARE方法,但它们是特殊类型的方法。构造函数是没有返回类型的方法,必须以它们的封闭类命名。那么为什么我们需要构造函数呢?好吧,那就是我们如何创建类的实例。如果要创建某个类的实例,可以通过调用其构造函数来实现。构造函数为对象保留内存并返回对新创建的对象的引用。

答案 3 :(得分:5)

陈述于Java Spec for Constructors

  • 构造函数不返回任何内容,因此它们没有返回类型。

      

    在所有其他方面,构造函数声明看起来就像没有结果的方法声明(§8.4.5)。

  • 您无法覆盖构造函数。

      

    构造函数声明不是成员。它们永远不会被继承,因此不会被隐藏或覆盖。

  • 他们无法直接访问实例变量,而是必须使用thissuper委托给类'变量

      

    构造函数体中的显式构造函数调用语句可能不引用此类或任何超类中声明的任何实例变量或实例方法或内部类,或者在任何表达式中使用this或super;否则,发生编译时错误。

答案 4 :(得分:3)

构造函数和方法之间存在很大差异。当你实例化一个像在程序中完成的对象时

Puppy myPuppy = new Puppy( "tommy" );

使用 new 关键字,JVM调用构造函数来创建对象。因此构造函数会创建不存在的对象,但方法与存在的对象相关联。您可以在此链接阅读更多内容 http://www.javaworld.com/article/2076204/core-java/understanding-constructors.html

答案 5 :(得分:3)

关于构造函数的几个好答案。

一个小问题;您不能拥有与您的类同名的静态方法。该名称是构造函数的保留

答案 6 :(得分:2)

构造函数应该用于设置对象,其中方法只是对对象执行某些操作。 Java是面向对象的,因此整个语言围绕着对象。构造函数也不能返回任何内容,必须与new一起使用才能返回创建对象的实例,因为方法可以返回任何内容或根本不返回任何内容。

答案 7 :(得分:2)

一个Constructor就是这样,它“构造”你正在创建它的对象技术上是一种特定类型的MethodMethod用于修改对象,主要用于执行单个逻辑。请参阅:single responsibility principle

类/方法应该很简单并且处理确切的信息片段,例如,如果你想要它的属性是长度,宽度,高度,体积,面积等等,你需要使用Shape对象......你的构造函数会必须是:

public Shape (double length, double width, double height, double volume, double area, ect...) {
    //code here
} 

(注意这个方法的名称应该与类的名称相同,表示'构造函数')

这就是所谓的code smell,特别是:参数太多了。它很难阅读,不是很有组织,只是编写代码的坏方法。因此,方法用于设置这些变量:

public void setLength(double length) {
    //code here
} 

然后你的构造函数只会是:

public Shape() {
    //code here
}

这只是一个简单的例子。在许多情况下,您可能希望根据具体情况将参数(或一些参数)传递给构造函数。

答案 8 :(得分:2)

对于该示例,您不需要构造函数。这是一个非常糟糕的例子。一种方法也可以。

(如果你没有添加一个,所有Java类都有一个默认的构造函数,所以你仍然可以调用new Puppy()来获取一个实例。)

答案 9 :(得分:2)

当您创建对象的新实例(Puppy doggy = new Puppy("Bobby");)时,会立即调用构造函数。它构造了新对象。它用“Bobby”这个名称构造它。 (小狗出生时的名字叫“鲍比”)。假设我们的小狗对其名称不满意,您想将其更改为“Snoopy”。然后你会调用方法:doggy.setName("Snoopy");

答案 10 :(得分:2)

构造函数是方法的类型。特别是在实例化该类的对象时调用它。所以在你的例子中,如果你写:

Puppy pup = new Puppy("Rover");

创建一个名为pup的对象并实例化该对象,允许您使用它。通过实例化它,你可以调用指定的构造函数,在这种情况下:public Puppy(String name)将打印设置为"Rover",但这并不是一个很好的构造函数。更有意义的是将String puppyName;作为字段变量,并使this.puppyName = name设置p.puppyName等于构造函数中传递的内容。

答案 11 :(得分:2)

我真的宁愿读一本关于OOP概念的书,在本例中是java,而不是阅读所有(好的)答案。你可能会得到很多答案,因为这个问题相当受欢迎,但答案不会涉及所有必要的细节。

但有一点我想简单提一下:

public int getAge() {
    System.out.println("Puppy's age is :" + puppyAge); 
    //what does this return do? since the puppyAge is already printed above.
    return puppyAge;
}

方法可以返回某种答案。 那么这种方法有什么用呢?它返回保存在名为puppyAge的变量中的值, 这是一个整数。 因此,如果您调用方法myPuppy.getAge(),此方法中的所有内容(实际上也是打印输出), 将被处理,然后它返回。在您的情况下,您不会将返回值保存在任何地方。 但你想做的“正常”事情是通过这种方法来获取小狗的年龄 并实际上做了一些事情,比如计算所有puppys和东西的平均年龄。 当然,您可以从类外部访问变量,因为您没有设置可见性修饰符,如public,private,protected。

public class Puppy {
    int puppyAge;

实际上没有公共修饰符也有意义,但这与现在不相关。 所以你想要做的就是把它设置为私有:

private int age;

并通过类似getAge()的方法访问它,并执行以下操作:

int allAgesummed = puppy1.getAge() + puppy2.getAge() +
puppy3.getAge();

最后,如果您只是想在控制台上打印出年龄,那么您的方法应该只完成那一件事并且应该相应地命名,例如:

public void printAgeToConsole(){
    System.out.println("Age: " + age);
}

void表示此方法有效,但不返回任何内容。

答案 12 :(得分:2)

构造函数是 public Class(){ 定义需要在整个类中使用的变量 方法是在构造函数下进行的 public void methodName(){} 你可以将void改为你希望方法返回特定类型的变量类型。

答案 13 :(得分:2)

您的第一个示例是在实际创建Puppy时调用的公共构造函数。通常,构造函数会保存名称而不是显示它并将其丢弃,因此您可以稍后再参考它,例如:

public class Puppy{
    private String puppyName;

    public Puppy(String name){
        puppyName = name;
    }
    public void bark(){
        System.out.println(puppyName + ": woof!");
    }
    ...
}
...
public static void main(){
    Puppy Spot = new Puppy("Spot"); // here, the constructor is called, which saves the name
                                    // "Spot" into the variable Spot.puppyName.

    Puppy Fido = new Puppy("Fido"); // on this line, the constructor is called again, but this time, the string
                                    // "Fido" is saved into Fido.puppyName.

    Spot.bark();                    // output: "Spot: woof!"
}

我认为构造函数是一个“返回”Puppy对象的方法,这就是为什么它没有返回类型。与小狗的名字不同,声明为静态的方法和变量并不特别“属于”任何对象,而是在该类的所有成员之间共享。

public class Puppy{
    ...
    private static String latinName;
    public static void setLatinName(String newLatinName){
        latinName = newLatinName;
    }
    public static void printLatinName(){
        System.out.println("I am a " + latinName + ".");
    }
};
...
static void main(){
    Puppy Spot("Spot");
    Puppy Fido("Spot");
    Spot.setLatinName("Canis Lupus");
    Fido.setLatinName("Canis Lupus Familiaris");

    Spot.printLatinName();    // output: "I am a Canus Lupus Familiaris."
    // even though we used the Fido object to change the latinName string,
    // the output of Spot's non-static method still reflects the change because
    // latinName is a static field: there is only one String latinName 
    // shared among all members of the class.
}

虽然你可以使用Puppy对象来调用静态方法(如果Puppy是一个多态Canine,这可能特别有用),反之亦然![/ p>

public class Puppy{
    ...
    public static void bark(){
        System.out.println( puppyName + ": woof!"); // this will not compile!
    }
}

在静态函数的上下文中引用非静态数据成员是无效的(并且没有意义)!静态函数类似于静态变量:在所有成员对象之间只共享一个函数副本。这意味着您可以调用Puppy.setLatinName()(而不是Spot.setLatinName())。您不需要使用特定的Puppy对象来调用静态函数:保证静态函数不依赖于任何非静态成员变量(因为它没有任何变量)。调用Puppy.bark()没有意义,因为类“Puppy”没有puppyName;每个Puppy都有自己的puppyName。

我希望这会有所帮助。面向对象编程非常强大,了解基础知识非常重要!祝你好运。