哪个是更好的构造函数?空或使用字段?

时间:2014-10-07 14:27:22

标签: java class

我目前正在学习Android课程,当我获得第一个作业成绩时,由于使用了空构造函数而不是使用带有字段的构造函数,我丢失了分数。教授说使用田地更好。他是对的吗?如果是这样,为什么?

这样更好吗?

Photos pic = new Photos(path, title, author, date);

public Photos(String url_path, String title, String author,
        String date_taken) {
    super();

    this.url_path = url_path;
    this.title = title;
    this.author = author;
    this.date_taken = date_taken;
} 

还是这个?或者重要吗?

 Photos pic = new Photos();
 pic.setUrl_path(path);
 pic.setTitle(title);
 pic.setAuthor(author);
 pic.setDate_taken(date);

 public Photos() {
    super();

 }

8 个答案:

答案 0 :(得分:4)

两者都不“更好”,他们只是做不同的事情。哪一个主观上“更好”取决于你想要通过该课程实现什么。请考虑以下代码:

Photos pic = new Photos();
pic.setUrl_path(path);
pic.setTitle(title);
pic.setAuthor(author);
pic.setDate_taken(date);

紧接第一行后,pic对象是否处于有效状态?没有设置值会导致有意义且上下文完整的Photos对象吗?如果答案是“否”,并且如果要设置的字段必需以便拥有有效的Photos对象,则构造函数应该要求它们。

也就是说,构造函数的工作是确保只创建一个有效的实例。永远不要假设消费代码将跟随setter,它可能不会。确保对象的有效状态的工作是应该封装在对象中的责任。

另一方面,如果无参数构造函数可以创建Photos的有效实例,那么拥有无参数构造函数是完全可以接受的。您可以同时使用这两种方式,因此根据要创建的状态,使用代码可以选择使用:

public Photos() {
    // set default values
}

public Photos(String url_path, String title, String author, String date_taken) {
    // set supplied values
}

这一切都取决于Photos对象的有效状态是什么以及为了达到该状态所需要的(或不需要的)。

答案 1 :(得分:2)

当你使用setter时,对象是可变的,并且可以操纵它们的状态,但任何有权访问它的人都可以。

另一种方法使对象处于单一定义状态,并且一旦创建它们通常是只读的,因为它们不能从类外部修改。他们怎么总能在课堂上变异。

示例:

public class Setters {
   private int value;
   public void setValue(int val) {
     value=val;
   }
   public int getValue() {
     return value;
   }
}

public void function(Setter setter){
    setter.setValue(20);
}


// In main 

Setter setter = new Setter();
setter.setValue(10);
function(setter);
System.out.println(setter.getValue());

在这种情况下,它会打印20因为它是可变的

public class Setters {
   private int value;
   public setter(int val) {
     value=val;
   }
   public int getValue() {
     return value;
   }
}

// In main 

Setter setter = new Setter(10);
Setter setter1 = new Setter(20);
System.out.println(setter.getValue());
System.out.println(setter1.getValue());

这将打印10和20你没有设置器,所以这些对象将在创建后被读取。

答案 2 :(得分:2)

正如Dmitry Bychenko in the comments所指出的,参数是通过构造函数传递的,当construction object依赖来强制执行这些必需参数时。

一旦构造了对象,通常会设置其他参数。

File

的构造函数为例
File f = new File("filepath");

此处filepath是一个参数,如果没有该参数,则无法构造File对象,因为它需要引用文件所在的位置。它的属性如readable,可以通过setter设置,只有在成功构造文件引用后才会出现。

f.setReadable(arg0)

由于在您的示例中,Photo类并不依赖于其构造的任何参数值,因此不需要parameterized构造函数。

答案 3 :(得分:1)

取决于你正在写什么课。如果它适用于Immutable对象,则意味着您不能为它提供访问器/更改器。在这种情况下,必须在创建对象时为属性提供初始值。自然的选择是将它们传递给构造函数。

在你的照片的情况下,Title,Date_Taken和Author等属性不应该被改变或者不能为null,并且应该与创作中的“Photos”相关联,所以更好的做法是在构造函数中提供参数。虽然您可以为URL提供getter / setter,因为它的值可能随时间而变化。

答案 4 :(得分:1)

就效率而言,是的。

你可以这样做......

JButton b = new JButton();
b.setText("Hello everybody 1");
b.setIcon(b1);

JButton c = new JButton();
c.setText("Hello everybody 2");
c.setIcon(c2);

JButton d = new JButton();
d.setText("Hello everybody 3");
d.setIcon(d3);

JButton e = new JButton();
e.setText("Hello everybody 4");
e.setIcon(e4);

或者你可以做到

JButton b = new JButton("Hello everybody 1", b1);

JButton c = new JButton("Hello everybody 2", c2);

JButton d = new JButton("Hello everybody 3", d3);

JButton e = new JButton("Hello everybody 4", e4);

更精简,是吗?更不用说像变量这样的东西,其中大多数类都有几个,可以从getgo中给出默认值,而不是在你甚至不打算在你的程序中的任何地方使用这些变量时给它们被动值。

答案 5 :(得分:1)

如果你的对象Photo(在这种情况下)总是将这些属性作为有效照片 我相信你应该在构造函数中包含这些属性的赋值。 (路径,标题,作者,日期);

因为你正在制作一个照片对象。构造函数和类的名称应该是Photo(不是Photos)

public Photo(String urlPath, String title, String author,
    String dateTaken) {
super();

this.urlPath= urlPath;
this.title = title;
this.author = author;
this.dateTaken= dateTaken;

}

更多评论:

如果Photo类是派生类,则只需要调用super()。 使用驼峰套管作为参数名称并尝试保持一致。

答案 6 :(得分:1)

另一个需要考虑的方面是如何将类连接在一起。如果你使用像spring或guice这样的依赖注入容器,那么带有setter和getter的空构造函数允许你将引用连接到你的对象。

我更喜欢将对象构造与执行分开,因此只要您的代码以这种方式考虑,就会模块化,可扩展和干净。

答案 7 :(得分:1)

通常,您应该更喜欢使用给定初始值的构造函数,以便稍后使用setter方法设置这些值。但为什么呢?

可以将一个对象想象成一个用于存放混乱字段的包,理论上它可以具有任何值,包括无效值。在这种情况下,使用no-args构造函数后跟一个setter就可以了。

但是(在20世纪70年代),这种方式的编程在创建大型或复杂的程序时造成了困难。

想象一下,你有一个Person类,其中有一个属性,记录了该人的姓名,为String,你的程序的性质就是你的,并且必须< / strong>,总是知道一个人的名字。由于您必须始终拥有该名称,因此绝不能是null。如果你有一个no-args构造函数,它会将名称初始化为什么值?不允许将名称保留为null。但是将名称设置为任意默认名称是没有意义的,因为人名不具有通常有用的默认值。因此,如果要强制约束Person对象始终具有(非null)名称,则构造函数必须具有一个参数,告诉它新的Person的名称是什么对象将是。

考虑一个对象很有用,不是作为一个混杂的值,而是作为对它们有约束的值。如果该对象的代码以一种使不可能突破这些约束的方式编写,则会非常有用。然后,使用该对象的任何代码都可以安全地假设将满足这些约束,即使您不知道(或记住)代码的其他部分的作用。这使您可以立即专注于一位代码,而无需在别处检查以检查是否会满足重要约束。在大多数情况下,只有给定初始值的构造函数才能构造满足所有约束的对象。