如何使用set和get方法,为什么要使用它们?他们真的很有帮助吗?你也可以给我一些set和get方法的例子吗?
答案 0 :(得分:54)
Set和Get方法是数据封装的模式。您可以定义get
方法来访问这些变量,而不是直接访问类成员变量,并使用set
方法来修改它们。通过以这种方式封装它们,您可以控制公共接口,如果您将来需要更改类的内部工作方式。
例如,对于成员变量:
Integer x;
你可能有方法:
Integer getX(){ return x; }
void setX(Integer x){ this.x = x; }
chiccodoro 也提到了重点。如果您只想允许对任何外国类的字段进行读取访问,则只需提供公共get
方法并保持set
私有或不提供set
即可。所有
答案 1 :(得分:22)
我想添加其他答案,可以使用setter来防止将对象置于无效状态。
例如,假设我要设置一个TaxId,建模为String。 setter的第一个版本可以如下:
private String taxId;
public void setTaxId(String taxId) {
this.taxId = taxId;
}
但是我们最好阻止使用无效的taxId来设置对象,所以我们可以引入一个检查:
private String taxId;
public void setTaxId(String taxId) throws IllegalArgumentException {
if (isTaxIdValid(taxId)) {
throw new IllegalArgumentException("Tax Id '" + taxId + "' is invalid");
}
this.taxId = taxId;
}
为了改善程序的模块性,下一步是将TaxId本身作为一个对象,能够自我检查。
private final TaxId taxId = new TaxId()
public void setTaxId(String taxIdString) throws IllegalArgumentException {
taxId.set(taxIdString); //will throw exception if not valid
}
同样对于吸气剂,如果我们没有值,该怎么办?也许我们希望有一条不同的道路,我们可以说:
public String getTaxId() throws IllegalStateException {
return taxId.get(); //will throw exception if not set
}
答案 2 :(得分:8)
我想你想要这样的东西:
public class Person {
private int age;
//public method to get the age variable
public int getAge(){
return this.age
}
//public method to set the age variable
public void setAge(int age){
this.age = age;
}
}
您只是在对象实例上调用这样的方法。这种方法特别有用,如果设置某些东西应该有副作用。例如。如果你想对某些事件做出反应,比如:
public void setAge(int age){
this.age = age;
double averageCigarettesPerYear = this.smokedCigarettes * 1.0 / age;
if(averageCigarettesPerYear >= 7300.0) {
this.eventBus.fire(new PersonSmokesTooMuchEvent(this));
}
}
当然,如果有人忘记拨打setAge(int)
他应该在哪里,并使用age
直接设置this.age
,这可能会很危险。
答案 3 :(得分:6)
具有访问器方法比直接访问字段更受欢迎,因为它控制字段的访问方式(可能会强制执行数据检查等)并适合接口(接口不能要求字段存在,只有方法)。
答案 4 :(得分:5)
Setter和getter用于替换从外部类直接访问成员变量。如果你在访问属性时使用setter和getter,你可以包括初始化,错误检查,复杂转换等。一些例子:
private String x;
public void setX(String newX) {
if (newX == null) {
x = "";
} else {
x = newX;
}
}
public String getX() {
if (x == null) {
return "";
} else {
return x;
}
}
答案 5 :(得分:4)
使用getter和setter(称为encapsulation
或 data-hiding
)的一些好处:
(最初回答here)
<强> 1。类的字段可以是只读的(仅通过提供getter)或只写(仅通过提供setter)。这使班级能够完全控制谁可以访问/修改其字段。
示例:
class EncapsulationExample {
private int readOnly = -1; // this value can only be read, not altered
private int writeOnly = 0; // this value can only be changed, not viewed
public int getReadOnly() {
return readOnly;
}
public int setWriteOnly(int w) {
writeOnly = w;
}
}
<强> 2。类的用户不需要知道类实际存储数据的方式。这意味着数据被分离并独立于用户而存在,从而允许更容易地修改和维护代码。这使得维护人员可以频繁更改,例如错误修复,设计和性能增强,同时不会影响用户。
此外,封装资源可以为每个用户统一访问,并且具有独立于用户的相同行为,因为此行为在类中内部定义。
示例(获取值):
class EncapsulationExample {
private int value;
public int getValue() {
return value; // return the value
}
}
现在如果我想要返回两倍的价值呢?我可以改变我的getter并且使用我的示例的所有代码都不需要更改并且将获得两倍的值:
class EncapsulationExample {
private int value;
public int getValue() {
return value*2; // return twice the value
}
}
第3。使代码更清晰,更易读,更容易理解。
以下是一个例子:
没有封装:
class Box {
int widthS; // width of the side
int widthT; // width of the top
// other stuff
}
// ...
Box b = new Box();
int w1 = b.widthS; // Hm... what is widthS again?
int w2 = b.widthT; // Don't mistake the names. I should make sure I use the proper variable here!
封装:
class Box {
private int widthS; // width of the side
private int widthT; // width of the top
public int getSideWidth() {
return widthS;
}
public int getTopWIdth() {
return widthT;
}
// other stuff
}
// ...
Box b = new Box();
int w1 = b.getSideWidth(); // Ok, this one gives me the width of the side
int w2 = b.getTopWidth(); // and this one gives me the width of the top. No confusion, whew!
看看您对获得哪些信息的控制程度以及第二个示例中的信息有多清楚。请注意,这个示例是微不足道的,在现实生活中,您将处理许多不同组件访问的大量资源的类。因此,封装资源可以更清楚地了解我们正在访问哪些资源以及以何种方式(获取或设置)。
此主题为good SO thread
。
这是关于数据封装的good read
。
答案 6 :(得分:2)
仅仅是因为OOP规则:数据隐藏和封装。将对象声明为公共对象并在大多数情况下即时更改它是一种非常糟糕的做法。还有许多其他原因,但根是OOP中的封装。并且“购买书籍或阅读面向对象编程”,在阅读任何有关OOP的书后,您将对此有所了解。
答案 7 :(得分:2)
上面的答案比我更好地总结了getter和setter的作用,但是我确实想补充一点,理想情况下你的代码应该被构造成减少纯getter和setter的使用,即那些没有复杂结构,验证和等等,因为它们破坏了封装。这并不意味着你不能使用它们(stivlo的答案显示了一个很好地使用getter和setter的例子),只是尽量减少你使用它们的频率。
问题是,getter和setter可以作为直接访问私有数据的解决方法。私有数据称为私有数据,因为它不打算与其他对象共享;它意味着对象状态的表示。允许其他对象访问对象的私有字段会破坏将其设置为私有的全部目的。此外,您为每个写入的getter或setter引入耦合。考虑一下,例如:
private String foo;
public void setFoo(String bar) {
this.foo = bar;
}
如果在某个地方,你决定不再需要foo,或者你想让它成为整数,会发生什么?现在,每个使用setFoo方法的对象都需要与foo一起更改。
答案 8 :(得分:1)
get()set()方法的好处如下..
示例:强>
private String personName;
private int personId;
public void setPersonName(String name) throws Exception{
if(!(name.equals("")||name=="")){
this.personName = name;
}
}
public String getPersonName(){
return this.personName;
}
public void setPersonId(int id) throws Exception{
this.personId = id;
}
public int getPersonId(){
return this.personId;
}
答案 9 :(得分:1)
以上答案都假设有问题的对象是具有行为的对象。 OOP中的高级策略是分离数据对象(包括zip,只有字段)和行为对象。
使用数据对象,可以省略getter而不是公共字段。它们通常没有setter,因为它们通常是不可变的 - 它们的字段是通过构造函数设置的,而且永远不会再存在。 有关详细信息,请查看Bob Martin的Clean Code或Pryce和Freeman的Growing OO Software...。
答案 10 :(得分:1)
public class Person{
private int age;
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
我想这就是你想要的.. 这也称为 pojo
答案 11 :(得分:0)
此答案与另一个问题合并。
您的getAge()
方法在Java中称为实例方法。
要调用实例方法,您应该有一个Class的对象,其中定义了此方法。
例如,如果在一个名为Person
的类中使用此方法,那么
使用new运算符
创建Person对象 Person p = new Person();
要获取Person
对象的年龄,请使用此方法
p.getAge()
答案 12 :(得分:0)
这是set方法的代码
public void setAge(int age){
this.age = age;
}
答案 13 :(得分:0)
如果您想要setAge创建方法
setAge(int age){
this.age = age;}
答案 14 :(得分:0)
我在这里没有看到第二个问题(为什么)的简单答案。所以这里。
假设您有一个在代码中经常使用的公共字段。每当您决定在提供或设置此字段之前需要执行额外操作时,您就会遇到问题。您必须为此字段创建一个特殊的getter和setter,并将完整的代码从直接使用字段更改为使用getter和setter。
现在想象一下,您正在开发一个被许多人广泛使用的库。当您需要进行如上所述的更改并将字段的直接访问权限设置为私有时,使用此字段的所有人的代码都将中断。
使用getter和setter是关于代码的未来规划,它使它更灵活。当然,您可以使用公共字段,尤其是对于只保存一些数据的简单类。但是,私下创建字段并为其编写get和set方法总是一个好主意。