Java-针对不同variables的getter,single getter或multiple的最佳实践?

我对Android编程相对较新(约2个月)是否有必要为几十个不同的variables设置getter

例如 –

//Yes I realise that this isn't 'dozens' public float getX() { return position.x; } public float getY() { return position.y; } public float getWidth() { return width; } public float getHeight() { return height; } public float getRotation() { return rotation; } 

虽然有必要为浮点数和字符串设置不同的getter和setter,但这是不好的做法,如果是这样,为什么要使用类似switch语句的东西来返回不同的variables呢?

 public float returnSomething(String theThing) { switch (theThing) { case "height": return height; case "rotation" : return rotation; case "width": return width; default: return 0; } } 

那么,上面的代码被认为是坏的吗? 如果是这样,请解释原因。

感谢任何帮助,这不是一个真正的问题,因为无论哪种方式都可以正常工作,我只是不明白为什么人们会使用几十个getter和setter如果没有充分的理由。

我想同样的问题适用于制定者

    因为你做的事情就像

     public float returnSomething(String theThing) { switch (theThing) { case "height": return height; case "rotation" : return rotation; case "width": return width; default: return 0; } } 

    我可以感受Stack Overflow的下一个问题, “为什么我的身高总是0?”

    然后发布代码就像

     public class GameThingy { //... private void doStuff(GameObject gameObject) { float gravity = 5*gameObject.returnSomething("hieght"); gameObject.setSomething("velocyty", gravity+50); } } 

    从技术上讲,当你在任何地方写错字时,你会遇到问题的根源。 那个,你很幸运,这些田地都是float ,它们不一定是。

    编辑:顺便说一下,这实际上是在某些数据库查询中定义感兴趣的字段时的典型问题。 如同,必须通过String指定您正在查找的字段。

    一个真实的例子是RealmQuery

    RealmQuery看起来像这样:

     RealmQuery query = realm.where(User.class); // Add query conditions: query.equalTo("name", "John"); // Execute the query: RealmResults result1 = query.findAll(); 

    他们假设类的User是这样的:

     public class User { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 

    一个有趣的说明是,Realm创建了一个“代理子类”,在这里他们重新定义了setNamegetName方法(也就是说,你需要getters / setters来使一些系统工作!他们假设你拥有它们!)

    但重要的是你需要提供带有"name"的字段名称。

    之后, 任何人都可以打错字 ,或者你只是不记得头顶的字段 。 在这种特殊情况下,他们倾向于创建一个元模型 (为您存储字段名称的东西),目的是您不必使用字符串来引用字段名称。

    例如,在Criteria API中,而不是

     Root pet = cq.from(Pet.class); cq.select(pet.get("name")); 

    他们有这样的元模型:

     Root pet = cq.from(Pet.class); cq.select(pet.get(Pet_.name)); 

    因此,它消除了对String的需求。

    同样地,我倾向于使用Realm来创建一个“元模型”(尽管现在可以使用RealmFieldNamesHelper自动生成它):

     public class User extends RealmObject { @PrimaryKey private long id; private String name; public static enum Fields { //this is the "metamodel" ID("id"), NAME("name"); private String fieldName; Fields(String fieldName) { this.fieldName = fieldName; } public String getField() { return fieldName; } @Override public String toString() { return getField(); } } } 

    因此您可以像这样替换查询

     RealmResults result2 = realm.where(User.class) .equalTo(User.Fields.NAME.getField(), "John") .or() .equalTo(User.Fields.NAME.getField(), "Peter") .findAll(); 

    但是对于getter和setter,你已经拥有了types安全性,并且你已经拥有了你不必记住的方法 – 因此,你有编译时错误检查。

    因此,要回答您的问题,在Java中通过字符串名称引用variables是不好的原因是因为

    1.)可能发生拼写错误,错误仅在运行时发生,而不是在编译时发生

    2.)不是types安全的 ; 你很幸运,无论在这个例子中是什么,你都可以得到float ,但是当它可以是一个String ,你需要返回Object并使用public T get(String field) { ... }或者使用public T get(String field) { ... }无论谁调用该方法,都必须确切地知道他们正在接收什么 – 也容易出现运行时错误。

    Getters&Setters为您提供types安全。 但是,仅将它用于需要从类外部访问(获取/设置)的variables。 您可以并且应该通过使用合适的构造函数来最小化它,这在大多数情况下是正确的方法,因为它通过消除背景中的神奇变化来提高代码的清晰度,这对于multithreading代码来说可能是一个严重的痛苦,但可以是即使在编程不佳的常规代码中也存在很大问题。

    仅仅因为你有二十个级别的私有variables并不意味着你必须为每个variables创建getXXX()和setXXX()!

    顺便说一下:现在大多数IDE都像Eclipse一样自动生成它们。

    只需在需要时创建getter和setter。

     public float returnSomething(String theThing) { switch (theThing) { case "height": return height; case "rotation" : return rotation; case "width": return width; default: return 0; } } 

    如果你试图做area = returnSomething("width") * returnSomething("heigth")你将总是以0区域结束。 为什么,注意拼写错误。 如果你有单独的方法,那么编译器会在编译时说出来。

    此外,如果您有许多variables,则需要进行大量检查。

    我也不是吸气者/制定者的朋友,但他们可能是这里最好的解决方案。 IDE将为这些字段提供代码生成。

    原因:坚如磐石,不易出错,以后更容易。

    在真正需要时只制作吸气剂/固定剂。 public void move(float, float)和其他更有趣的方法可能会将坐标计算大部分放在类本身内。

    您只需要为需要使用或更新的variables声明getter和setter。

    我认为这只是一种习惯,你的回报可以很好地工作,但是更容易打电话和理解:

     class.getHeight() 

     class.returnSomething("height") 

    有趣的话题。 我觉得还有第三个答案。 有一种说法认为Getters和Setter是邪恶的 ,你应该避免使用它们。 因为您基本上将成员声明为private成员,但通过getter和setter授予公共修改访问权限。

    让我们比较两者。 这是一个使用getter和setter的人类

     public class Person { private String name; private int age; public String getName() { return this.name; } public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int name) { this.age = age; } } 

    使用这个类:

     Person me = new Person(); me.setName("Ian"); me.setAge(24); System.out.println("Name: " + me.getName()); System.out.println("Age: " + me.getAge()); 

    现在让我们创建相同的类,而不使用getter和setter。

     public class Person { public String name; public int age; } 

    和访问将是:

     Person me = new Person(); me.name = "Ian"; me.age = 24; System.out.println("Name: " + me.name); System.out.println("Age: " + me.age); 

    正如您所看到的,getter和setter模式增加了相当多的额外输入。 然而,使用getter和setter有很多优点 。

    反对在面向对象语言中使用getter和setter的整个论点可以概括为:

    程序代码获取信息然后做出决定。 面向对象的代码告诉对象做事。 – 亚历克夏普

    举个简单的例子,假设我们要将Person的信息写入数据库。 一些开发人员倾向于做的是创建一个具有函数的数据库接口

     void writeToPersons(Person person) 

    它将使用getter和setter将所需数据写入数据库。

    根据getter和setter nay的说法, Person本身应该负责自己编写数据库。

     public class Person implements Storable { public void writeToDatabase() { } } 

    要回答你的问题,我宁愿使用getter和setter而不是你的第二个建议,因为你最终会为每个属性添加一组常量或枚举。 这需要在两个不同的地方进行代码维护,这只会增加另一个故障点。

    我同意以前的答案,但我会稍微概括一下。 returnSomething方法的问题在于它将一些拼写检查从编译时转移到运行时。

    有些时间和地点非常灵活,大多数检查都是在运行时完成的。 在那些情况下,我不使用Java。

    编译时间检查以及支持它们的语言的最大优点是它们完全相当于普遍量化的测试:“对于每个不使用reflection的可编译程序,每个get请求都是有效的属性。” 而不是“对于此测试套件中的所有测试用例,每个获取请求都是针对有效属性”。