Java 中的 Set、Get 和构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10155925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 23:50:27  来源:igfitidea点击:

Set, Get and Constructors in Java

javaconstructor

提问by dwwilson66

Despite Java tutorials, Wikipedia searches, stackoverflow trolling, and hours of reading code samples, constructors still confuse the crap out of me. I've got three related questions that I've been trying to answer to help ME understand constructors a little better.

尽管有 Java 教程、维基百科搜索、stackoverflow 拖钓和数小时的代码示例,构造函数仍然让我感到困惑。我一直在尝试回答三个相关的问题,以帮助我更好地理解构造函数。

First, I've been under the impression that constructors need to be named the same as their classes. Consider:

首先,我的印象是构造函数需要与它们的类命名相同。考虑:

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

I see this as four constructors...correct? So it appearsthat constructors notnamed the same as the class which contains them allowable. Can someone confirm that?

我认为这是四个构造函数......对吗?因此,它似乎是构造不是命名一样包含它们允许类。有人可以确认吗?

Second, I seem to have a block against understanding the set and get methods. Consider:

其次,我似乎对理解 set 和 get 方法有障碍。考虑:

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

Why can't I just do this:

为什么我不能这样做:

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

and use foo = getFoo(12)from some other class/method?

foo = getFoo(12)从其他一些类/方法中使用?

The third question is a little more esoteric, but will help me conceive of the bigger picture...which is my learning style, and conducive to my ability to trace program flow when debugging. The getand setmethods suggest a "to" and "from" relationship to me. e.g., Passing a value "to" a constructor, receiving the result "from" the get method. It seems to me though that the "to" and "from" will change depending on your perspective. I think that any setMethodis setting parameters for an object, even though the variable comes FROM another class or method, and the GetMethodis getting the resulting object (say, this.foo) with the appropriately setparameter. No matter where the getor setis used, in a main method or a standalone class with a single constructor, 'set' is always associated with sending a parameter and getis always associated with receiving an object with that parameter. Is that a good understanding? or am I missing a vital part?

第三个问题有点深奥,但会帮助我构想更大的图景……这是我的学习风格,有助于我在调试时跟踪程序流程的能力。该getset方法提出了“到”和“从”的关系给我。例如,将值“传递给”构造函数,从 get 方法“接收”结果。在我看来,“to”和“from”会根据您的观点而改变。我认为 anysetMethod正在为对象设置参数,即使变量来自另一个类或方法,并且GetMethod正在使用适当的参数get对结果对象(例如,this.foo)进行调整set。无论在哪里getset在主方法或具有单个构造函数的独立类中使用时,'set' 始终与发送参数get相关联,并且始终与接收具有该参数的对象相关联。这是一个很好的理解吗?还是我错过了一个重要的部分?

回答by Jon Skeet

Question 1:

问题 1:

I see this as four constructors...correct?

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

No, that class has two constructors and two methods. (getLongand getStringare the methods.)

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

Question 2:

问题2:

Why can't I just do this:

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

为什么我不能这样做:

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

Well, that's trying to declare a classwith parameters, and also you're settinga value in a getmethod, which would be extremely weird. It's not clear what you're trying to achieve here, but that code is thoroughly invalid.

好吧,那是试图声明一个带参数的,而且您还在get方法中设置一个值,这将非常奇怪。目前尚不清楚您要在这里实现什么,但该代码完全无效。

Question 3:

问题 3:

The get and set methods suggest a "to" and "from" relationship to me.

get 和 set 方法暗示了我的“to”和“from”关系。

Well it's not really a relationshipIMO. A relationship suggests something longer term than either of these methods. A setter typically changes the state of an object in some way, and a getter typically just returns some aspect of the state of an object. It's not really clear what the rest of your explanation meant, because you're playing somewhat fast and loose with terminology. For example: "getis always associated with receiving an object with that parameter" doesn't really make sense to me. Objects don't have parameters, methods/constructors do - and getters can fetch primitive values or references...

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

I suspect you would benefit from reading the "Classes" part of the Java tutorial, which talks about constructors and methods.

我怀疑您会从Java 教程“类”部分中受益,该部分讨论了构造函数和方法。

回答by Erwald

Regarding the first answer, there's only 2 constructors. The difference is on how they are going to be called (called using a string will use the construction having a string has a parameter and called using a long will use the other one). So to answer, yes a constructor has the same name as the class.

关于第一个答案,只有 2 个构造函数。不同之处在于它们将如何被调用(使用字符串调用将使用具有字符串参数的构造,而使用 long 调用将使用另一个)。所以回答,是的,构造函数与类同名。

The two constructors :

两个构造函数:

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

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

Regarding the second answer, getters ans setters are not meant to be classes. They are supposed to be within the class itself.

关于第二个答案,getter 和 setter 并不意味着是类。它们应该在类本身内。

Consider this example which uses getter and setters to get ans set value for the printer class :

考虑这个例子,它使用 getter 和 setter 来获取打印机类的 ans 设置值:

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

A good read of this link could definitly help you out ! Java oriented-object principles

仔细阅读此链接绝对可以帮助您! Java 面向对象原则

回答by Adam Liss

You've shown 2 constructors, which do need to have the same name as the class.

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

You've also shown two "getter" methods, which return the value of the class variable in the form requested by the user. You can also create "setter" methods, which are used to transfer values into class variables.

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

You use a constructor to create an object of a particular class, and optionally to set some or all of its internal state (that is, its member variables).

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

You use setters and getters to isolate the class variables from the outside world, so you don't need to allow other code to access them directly. Why? Because, before a setter updates a variable, it can verify that the new value is valid, and that the operation doesn't violate any or the rules (the "business logic") that are required for the class to work properly.

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

So you could add a setter and update the constructor to use it:

因此,您可以添加一个 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.
}

Note that a setter usually doesn't need to return a value (that is, it can be type void), but it's often helpful to return the object itself. That allows you to write code like this:

请注意,setter 通常不需要返回值(即它可以是 type void),但返回对象本身通常很有帮助。这允许您编写如下代码:

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

This creates an object of type Money, sets various attributes, and stores it in the variable earnings. Clearly, this isn't terribly useful for a simple class like this, but it can be very helpful for more complex classes:

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

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

回答by arcy

I would like to try to answer your implied conceptual questions -- you've already got plenty of examples of this and that, so I'm just going to try to explain. I have no doubt you have heard most of this -- maybe all of this -- before, but am not sure and not sure which parts.

我想尝试回答你隐含的概念性问题——你已经有很多这样和那样的例子,所以我只是想解释一下。毫无疑问,您之前已经听过大部分——也许所有这些——但我不确定也不确定是哪些部分。

Object-oriented programming centers mostly around objects; an object is an amalgamation of code and data. You define objects by writing a class, and you create one or more copies of the object defined by that class with the class constructor (called instantiatingthe class).

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

A parallel in other languages: you can have a data structure of related items and a set of subroutines that operate on that data structure. Think of a class as a way of collecting the items in that data structure and the subroutines that operate on it into one unit.

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

After you have invoked a constructor, you have a copy of the data defined in that class and a way to refer to that copy. By referring to that instance when you invoke a class method, you operate on that copy of the data with the methods defined in that class.

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

If you were to do this in a non-OO language, you could have a routine that created a copy of the data structure in memory and then only use the methods prescribed for it on that data structure. You could have a pointer to the copy in memory and pass that pointer as a parameter to every subroutine that operated on it, and in fact that's the way some pre-OO systems were programmed.

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

A constructor is similar to a method call that returns a value; it involves (or can involve) the execution of statements, and it always returns an object of that class. There are also differences between a constructor and a method; until the constructor completes, for instance, the object is not fully created and shouldn't have some methods invoked on it.

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

So I hope that helped; if there are conceptual things you still have questions about, perhaps something in here will help you form a specific question so we can explain things further.

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

回答by peter.murray.rust

Many people have found that if they have spent years learning languages such as COBOL and FORTRAN then changing to OO programming involves unlearning the old languages. I certainly found this when I first tackled C++ 20 years ago. From your description you are clearly struggling with the concepts and I sympathize.

许多人发现,如果他们花了数年时间学习 COBOL 和 FORTRAN 等语言,那么转向 OO 编程就涉及忘掉旧语言。当我 20 年前第一次接触 C++ 时,我当然发现了这一点。从您的描述来看,您显然正在为这些概念而苦苦挣扎,我对此表示同情。

I don't think there is a simple recipe. Practice at the simple examples and don't be disheartened. Don't be afraid to ask on SO - if the questions are clearly asked you will get a useful answer.

我不认为有一个简单的食谱。练习简单的例子,不要灰心。不要害怕问 SO - 如果问题被明确提出,您将得到有用的答案。

Get a good IDE (Eclipse, Netbeans, etc.) which allows you to "look inside" objects with the debugger. Hopefully at some stage things will click!

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

回答by PastryExplosion

Question 1 - Basic Java Classes:

问题 1 - 基本 Java 类:

There's pretty much only 3 things you're going to find in a Java class

在 Java 类中几乎只能找到 3 样东西

  • Field/attribute (Depending on your language of origin)
  • Method
  • Constructor (Which looks like a special kind of method)
  • 字段/属性(取决于您的母语)
  • 方法
  • 构造函数(看起来像一种特殊的方法)

Every class is going to have a class name that shares the name of the file it's located in. So to expand Money out a bit:

每个类都将有一个类名,该类名与它所在的文件的名称相同。因此,将 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

The only distinction between a constructor and a method is that a constructor has no specified return value, which is declared as a type right before the name of a potential method. Constructors do have to be named the same as the class they are contained in, but why is implied in how they are written.

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

Another way of looking at it is if you remove all of the non-type related Java keywords (public, private etc., but not things like float and int) from the front of the method you're looking at (A list of which you can find here), is there anything left in front of the method?

另一种看待它的方法是,如果您从您正在查看的方法的前面删除所有与类型无关的 Java 关键字(public、private 等,但不包括 float 和 int 之类的东西)(其中的列表)你可以在这里找到),方法前面还有什么吗?

With the Money we have at the moment, it would look like this:

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

  • Money()
  • Long getValue()
  • void makeMoney()
  • 钱()
  • 长 getValue()
  • void makeMoney()

The constructor is the one that has no type for the return value, because it is implied in the declaration.

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

Question 2/3 - Get/Set methods:

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

I'm going to say something potentially controversial, but don't worry about these yet. Get/Set are essentially patterns for Object Oriented development, and generally good Java style, but they aren't required (Last I checked, Android development actually discourages their use when possible for optimization reasons). Moreover, not all fields in your objects will be accessible or mutable so writing them isn't mandatory.

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

If you declare all of your fields as public (Like the 'value' field is implied to be right now), you simple can do this:

如果您将所有字段声明为公共字段(就像现在隐含的“值”字段一样),您可以简单地执行以下操作:

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

Aside from that, the notion of get() and set() are just methods. There is nothing special about them at all. The main reason they exist is because for general Object-Oriented programming, you shouldn't have to directly modify the internal workings of an object (This is the principle of Encapsulation). Everything you should need to affect state or get something out of it should be handled by a method.

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

In a pithy one-liner: If you need to know the fields of an object to use it, you designed it incorrectly.

简而言之:如果你需要知道一个对象的字段来使用它,你就设计错了。

Big PictureSo what get() and set() really are is a pair of commonly written methods that happen to affect a field in an object in an extremely simple way (get() is a simple access to a field, set() is assignment to that field). It's just that other methods you write will happen to do more complicated stuff than that.

大图所以 get() 和 set() 真正是一对常用的方法,它们碰巧以极其简单的方式影响对象中的字段(get() 是对字段的简单访问,set() 是分配给该字段)。只是你编写的其他方法会碰巧做比这更复杂的事情。