Java中的Set,Get和Constructors

时间:2012-04-14 17:53:25

标签: java constructor

尽管有Java教程,维基百科搜索,stackoverflow拖钓以及数小时阅读代码示例,但构造函数仍然混淆了我的废话。我有三个相关的问题,我一直试图回答,以帮助我更好地理解构造函数。

首先,我一直认为构造函数需要与它们的类相同。考虑:

public class Money {
    public Money(long l) {
        this.value = l;
    }

    public Money(String s) {
        this.value = toLong(s);
    }

    public long getLong() {
        return this.value;
    }

    public String getString() {
        return toString(this.value);
    }
} 

我认为这是四个构造函数......对吗?所以出现,构造函数的名称与包含它们的类相同。有人可以证实吗?

其次,我似乎阻止了解set和get方法。考虑:

 public class GetSetSample {
     public int getFoo()  {
 return int Foo;
 }
 public void setFoo(int fooValue) {
 int Foo = fooValue;
 } 
} 

为什么我不能这样做:

public class getFoo(int fooValue){
     foo=fooValue;
}

并使用其他类/方法中的foo = getFoo(12)

第三个问题有点深奥,但会帮助我设想更大的画面......这是我的学习风格,有利于我在调试时跟踪程序流程的能力。 getset方法提示我与“to”和“from”的关系。例如,将值“传递给”构造函数,从get方法接收结果。在我看来,“to”和“from”会根据你的观点而改变。我认为任何setMethod都是为对象设置参数,即使变量来自另一个类或方法,GetMethodget生成的对象(比如{{1}使用适当的this.foo参数。无论使用set还是get,在主方法或具有单个构造函数的独立类中,'set'始终与发送参数相关联,set始终关联接收具有该参数的对象。那是一个很好的理解吗?还是我错过了重要的一部分?

6 个答案:

答案 0 :(得分:8)

问题1:

  

我认为这是四个构造函数......正确吗?

不,该类有两个构造函数和两个方法。 (getLonggetString是方法。)

问题2:

  

为什么我不能这样做:

public class getFoo(int fooValue){
    foo=fooValue;
}

嗯,那是尝试使用参数声明,并且设置 get 方法中的值非常奇怪。目前还不清楚你在这里想要达到的目标,但该代码完全无效。

问题3:

  

get和set方法表明我与“to”和“from”的关系。

嗯,这不是一个真正的关系 IMO。关系建议比这些方法中的任何一种都更长远。 setter通常以某种方式改变对象的状态,而getter通常只返回对象状态的某些方面。你的解释其余部分的意思并不是很清楚,因为你的术语有点快而且松散。例如:“get始终与接收具有该参数的对象相关联”对我来说真的没有意义。对象没有参数,方法/构造函数可以 - 并且getter可以获取原始值或引用...

我怀疑你会从阅读有关构造函数和方法的"Classes" part of the Java tutorial中受益。

答案 1 :(得分:3)

您已经显示了2个构造函数,它们需要与该类具有相同的名称。

您还展示了两个“getter”方法,它们以用户请求的形式返回类变量的值。您还可以创建“setter”方法,用于将值传输到类变量中。

使用构造函数创建特定类的对象,并可选择设置其部分或全部内部状态(即其成员变量)。

使用setter和getter将类变量与外部世界隔离开来,因此您不需要允许其他代码直接访问它们。为什么?因为,在setter更新变量之前,它可以验证新值是否有效,以及该操作是否违反了该类正常工作所需的任何规则(“业务逻辑”)。

所以你可以添加一个setter并更新构造函数来使用它:

public Money(long l) {
    setValue(l);
}

public Money(String s) {
    setValue(toLong(s));
}

// Example setter that validates `l` by prohibiting negative values
public Money setValue(long l) {
  if (l < 0) {
    // Warn about negative values
  }
  this.value = l;
  return this;  // Return the current object to allow chaining; see below.
}

请注意,setter通常不需要返回值(也就是说,它可以是void类型),但返回对象本身通常很有帮助。这允许你编写这样的代码:

Money earnings = new Money().setValue(4).setOtherField("foo");

这会创建一个Money类型的对象,设置各种属性,并将其存储在变量earnings中。显然,这对于像这样的简单类来说并不是非常有用,但它对于更复杂的类非常有用:

Paycheck check = new Paycheck("MyCompany")
  .setEmployee("YourName")
  .setSalary(50,000)
  .setPaySchedule(Schedule.BIWEEKLY)
  .setAccountNumber("1234567")
  .setDefaultTaxRate();

答案 2 :(得分:3)

关于第一个答案,只有2个构造函数。区别在于它们将如何被调用(使用字符串调用将使用具有字符串的构造具有参数并且使用long来调用将使用另一个)。所以要回答,是的,构造函数与类具有相同的名称。

两个构造函数:

public Money(long l) {
        this.value = l;
    }

    public Money(String s) {
        this.value = toLong(s);
    }

关于第二个答案,getters和setter并不是一个类。他们应该属于班级本身。

考虑这个使用getter和setter获取打印机类的设置值的示例:

public class Printer {

    @Inject @Informal Greeting greeting;

    private String name;
    private String salutation;

    public void createSalutation() {
        this.salutation = greeting.greet(name);
    }

    public String getSalutation() {
        return salutation;
    }

    public void setName(String name) {
       this.name = name;
    }

    public String getName() {
       return name;
    }
}

很好地阅读此链接可以帮助您! Java oriented-object principles

答案 3 :(得分:0)

我想尝试回答你隐含的概念问题 - 你已经有很多这方面的例子,所以我只是想解释一下。我毫不怀疑你之前已经听过大部分内容 - 也许所有这些 - 但是我不确定并且不确定哪些部分。

面向对象的编程主要围绕对象;对象是代码和数据的融合。您可以通过编写类来定义对象,并使用类构造函数(称为实例化类)创建该类定义的对象的一个​​或多个副本。

与其他语言并行:您可以拥有相关项的数据结构和一组对该数据结构进行操作的子例程。将类视为一种收集数据结构中的项目以及对其进行操作的子程序的方法。

调用构造函数后,您将获得该类中定义的数据的副本以及引用该副本的方法。通过在调用类方法时引用该实例,可以使用该类中定义的方法对该数据副本进行操作。

如果您要使用非OO语言执行此操作,则可以使用例程在内存中创建数据结构的副本,然后仅使用在该数据结构上为其规定的方法。你可以在内存中找到一个指向副本的指针,并将该指针作为参数传递给在其上运行的每个子程序,事实上这就是一些预OO系统的编程方式。

构造函数类似于返回值的方法调用;它涉及(或可能涉及)语句的执行,它总是返回该类的对象。构造函数和方法之间也存在差异;例如,在构造函数完成之前,该对象未完全创建,并且不应该在其上调用某些方法。

所以我希望有所帮助;如果有概念性的事情你仍然有疑问,也许这里的某些内容可以帮助你形成一个特定的问题,这样我们就可以进一步解释。

答案 4 :(得分:0)

许多人发现,如果他们花了数年时间学习COBOL和FORTRAN等语言,那么改用OO编程就需要学习旧语言。 20年前,当我第一次使用C ++时,我确实找到了这个。从你的描述来看,你显然正在努力解决这些概念,我很同情。

我认为没有一个简单的配方。练习简单的例子,不要灰心。不要害怕问这个问题 - 如果问题清楚明白,你会得到一个有用的答案。

获得一个好的IDE(Eclipse,Netbeans等),它允许您使用调试器“查看”对象。希望在某些阶段,事情会点击!

答案 5 :(得分:0)

问题1 - 基本Java类:

在Java类中,您只能找到3件事

  • 字段/属性(取决于您的原始语言)
  • 方法
  • 构造函数(看起来像一种特殊的方法)

每个类都有一个类名,该名称共享它所在文件的名称。所以要稍微扩展Money:

Money.java
----------
public class Money {
   // This is a field/attribute
   Long value;

   // This is a constructor
   public Money() {
      this.value = Long(0L);
   }

   // This is a method
   public Long getValue() {
      return value;
   }

   // Another method
   public void makeMoney(Long moreMoney) {
      this.value = this.value + moreMoney;
   }
} // Everything in here is part of the Money class

构造函数和方法之间的唯一区别是构造函数没有指定的返回值,它在潜在方法的名称之前声明为类型。构造函数的名称必须与它们包含的类相同,但为什么隐含在它们的编写方式中。

另一种看待它的方法是,从你正在查看的方法的前面删除所有与非类型相关的Java关键字(公共,私有等,但不包括float和int之类的东西)(A您可以找到here)的列表,方法前面还有什么内容吗?

凭借我们目前拥有的资金,它看起来像这样:

  • 奖金()
  • Long getValue()
  • void makeMoney()

构造函数是没有返回值类型的构造函数,因为它隐含在声明中。

问题2/3 - 获取/设置方法:

我会说一些可能引起争议的事情,但不要担心这些。获取/设置本质上是面向对象开发的模式,通常是良好的Java风格,但它们不是必需的(最后我检查过,Android开发实际上阻止了它们的使用,出于优化原因)。此外,并非对象中的所有字段都是可访问的或可变的,因此编写它们不是必需的。

如果您将所有字段声明为公共字段(就像现在暗示的那样“值”字段),您可以这样做:

Money myMoney = new Money(new Long(40L));
System.out.println(myMoney.value) // 40
myMoney.value = new Long(20L);
System.out.println(myMoney.value) // 20

除此之外,get()和set()的概念只是方法。他们根本没什么特别的。它们存在的主要原因是因为对于一般的面向对象编程,您不必直接修改对象的内部工作(这是the principle of Encapsulation)。应该通过一种方法来处理你需要影响状态或从中获取某些东西的所有东西。

在简洁的单行中:如果您需要知道要使用它的对象的字段,那么您的设计是错误的。

大图片 那么get()和set()实际上是一对常见的方法碰巧以极其简单的方式影响对象中的字段(get()是对字段的简单访问,set()是赋值给那个领域)。只是你写的其他方法会发生比这更复杂的事情。