Java-获取者的最佳实践,单个吸气剂或多个不同的variables?

我对Android编程相对较新(约2个月)是否有必要让几十个不同的variables获得?

例如 –

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

虽然有必要为浮点数和string设置不同的gettersetter,但这是不是很好的做法,如果是这样,为什么要使用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和setters如果没有一个很好的理由。

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

    因为你做这样的事情的时刻

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

    我可以感觉到堆栈溢出的下一个问题, “为什么我的高度总是为0?

    然后发布代码

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

    从技术上讲,当你在任何地方犯错误的时候,你会有问题find问题的根源。 那么,你很幸运,这些田地都是float ,它们不一定是。

    编辑:顺便说一下,这实际上是一些在数据库查询中定义感兴趣的领域的典型问题。 如在,不得不指定你正在寻找一个String的字段。

    一个真实的例子是RealmQuery<T>

    RealmQuery<T>看起来像这样:

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

    他们在哪里假设class级User是这样的:

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

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

    但是这里最重要的是你需要提供字段名称"name"

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

    例如,在Criteria API中,而不是

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

    他们有这样的元模型:

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

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

    同样,我倾向于使用Realm的方法是创build一个“元模型”(尽pipe现在可以通过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(); } } } 

    因此,您可以像这样replace查询

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

    但是对于getter和setter,你已经有了types安全性,而且你已经拥有了不必记住头脑的方法 – 所以你需要编译时间错误检查。

    所以要回答你的问题,在Java中用string名称引用variables是一个不好的做法是因为

    1)错别字可能发生,错误只在运行时发生,而不是编译时间

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

    吸气剂和固化剂给你types安全。 但是,仅将它用于需要从课程外部访问(获取/设置)的variables。 你可以并且应该通过使用合适的构造函数来最小化它,这在大多数情况下是正确的,因为它通过消除背景中的魔法变化来增加代码的清晰度,这对于multithreading代码可能是严重的痛苦,但是可以即使在编程不良的普通代码中也是一个大问题。

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

    顺便说一句:现在大多数IDE像Eclipse一样可以为你自动生成。

    只需在需要时创buildgetter和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,你需要做很多检查。

    我也不是getter / setters的朋友,但他们可能是这里最好的解决scheme。 IDE将为这些字段提供代码生成。

    理由:坚如磐石,不容易出错,更容易为以后的变化。

    当真正需要的时候只做吸气剂/吸气剂。 一个public void move(float, float)和其他更有趣的方法可能会把坐标计算大部分放在类本身。

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

    我认为这只是一种习惯,你的回报有些东西可以正常工作,但更容易打电话和了解:

     class.getHeight() 

     class.returnSomething("height") 

    有趣的话题。 我觉得还有第三个答案。 有一个说法,说吸气剂和定型剂是邪恶的 ,你应该避免使用它们。 因为你基本上声明成员是private但是通过getter和setter来授予公共的修改权限。

    让我们比较两者。 这是一个使用getters和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()); 

    现在让我们创build相同的类,而不使用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模式增加了一些额外的input。 然而,使用getter和setters有很多好处 。

    反对使用面向对象语言的getter和setter的全部观点可以概括为:

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

    作为一个简单的例子,假设我们想把一个Person的信息写入数据库。 一些开发者倾向于做的是创build一个具有函数的数据库接口

     void writeToPersons(Person person) 

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

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

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

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

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

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

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