【问题标题】:What's the advantage of POJO?POJO有什么优势?
【发布时间】:2012-12-19 19:19:35
【问题描述】:

在我的项目中,我有一个小数据结构Key

public class Key implements Serializable {

  private static final long serialVersionUID = 1L;

  public String db;
  public String ref;
  public Object id;

  protected Key() {
  }

  public Key(String db, String ref, Object id) {
    this.db = db;
    this.ref = ref;
    this.id = id;
  }
}

是的,这个类很简单,每个字段都可以公开访问。

但有人建议我改用 POJO 样式类,但当我问他们为什么无法告诉我时。

在我看来,调用 getterssetters 比直接访问字段要慢。

那么为什么我必须使用 POJO 编程风格呢?

【问题讨论】:

  • 调用 getter 和 setter 比直接访问字段慢。 错误信息。直接操作变量是一个非常糟糕的主意。想象一下有人可以在代码中设置 age=-11111;这很糟糕。如果您有 getter/setter,您可以在将值设置为字段之前验证无效值。
  • 如果值是不可变的,您可以将它们设为final 以防止非法值被设置
  • 从技术上讲,您在上面编码的是 POJO。
  • “不透明”是我见过的一个术语,但含义并不完全相同,因为并非所有字段都被假定为可以通过不透明对象访问。
  • 我很惊讶为什么没有人提到@pradeep simha 的回答涉及 oop 的非常基本的事情。封装!!!

标签: java pojo


【解决方案1】:

取自维基百科:

POJO 是 Plain Old Java Object 的首字母缩写词。该名称用于 强调给定的对象是一个普通的 Java 对象,而不是一个 特殊对象。

POJO 通常很简单,因此不会依赖于其他库、接口或注释。这增加了在多种项目类型(Web、桌面、控制台等)中重复使用它的机会。

正如有人已经在 cmets 中指出的那样,您的对象在技术上已经是 POJO,但是您特别询问了更类似于 JavaBeans 的 getter 和 setter。

我能想到使用 getter 和 setter 的原因有很多:

  1. 您可能只想获取一些值(即只读值)。使用字段,客户端可以直接获取和设置值。如果字段被标记为 final,则可以将它们设为只读,但这并不总是保证它们是不可变的(参见第 9 点)。
  2. Getter 和 setter 方法允许您在不破坏类的公共接口的情况下更改底层数据类型,从而使其(和您的应用程序)更加健壮和适应变化。
  3. 您可能希望调用其他代码,例如在获取或更改值时发出通知。这在您当前的课程中是不可能的。
  4. 您正在公开您的类的实现,这在某些情况下可能存在安全风险。
  5. Java bean 是围绕 POJO 设计的,这意味着如果您的类没有作为一个类来实现,那么某些希望您的类遵守这些公认原则的工具和库就不能使用它。
  6. 您可以公开由字段 I.E. 支持的值。计算值,例如 getFullName(),它是由字段支持的 getFirstName()getLastName() 的串联。
  7. 您可以向您的 setter 方法添加验证,以确保传递的值是正确的。这可确保您的课程始终处于有效状态。
  8. 您可以在 getter 和 setter 中设置断点,以便在获取或更改值时调试代码。
  9. 如果该字段是一个对象(即不是原始类型),那么您的类的内部状态可以被其他对象修改,这可能会导致错误或安全风险。您可以通过返回对象的 copy 来防止 POJO 的 getter 中出现这种情况,以便客户端可以在不影响对象状态的情况下处理数据。请注意,拥有 final 字段并不总能保护您免受此类攻击,因为 客户端仍然可以更改被引用的对象(假设该对象本身是可变的)您只是不能在设置后将字段指向不同的引用。

是的,通过方法调用访问或设置值可能比直接访问字段慢,但差异几乎不明显,它肯定不会成为您程序的瓶颈。

虽然优点很明显,但这并不意味着 getter 和 setter 是灵丹妙药。在设计真实的、强大的可扩展类时,需要考虑许多“问题”。

This 对一个非常相似的问题的回答详细介绍了设计具有 getter 和 setter 的类时的一些注意事项。尽管根据您设计的课程类型,这些建议可能更相关。一个类,在大型系统中构成 API 的一部分,而不是简单的数据传输对象。

另请注意,在某些情况下,具有直接字段的类可能是有利的,例如当速度很重要或内存有限时,尽管 只有在分析您的代码并发现它实际上是一个瓶颈

还要小心,不要将 所有 字段包装在 getter 和 setter 中,因为这确实缺少封装的意义。

This 回答很好地总结了选择 POJO 而不是带有 getter 和 setter 的 JavaBean 样式对象的原因。

【讨论】:

  • 返回可变对象类型的代码往往是丑陋和模棱两可的,因为返回的对象是否“附加”到其他任何东西很少很明显。您如何看待让方法将数据复制到调用者提供的可变对象中?由于调用者提供了对象,因此不会混淆是否有其他任何东西持有对它的引用,并且会受到对其进一步更改的影响。
【解决方案2】:

使用私有类变量和公共 getter 和 setter,它们将为您提供封装。

【讨论】:

    【解决方案3】:

    Getter 和 setter,尤其是最简单的形式将被 JIT 编译器内联,从而消除方法调用开销。这听起来很像过早的优化。如果您曾经遇到瓶颈,请分析并查看它发生的位置。我相当肯定它不会在属性访问中。

    【讨论】:

    • @jackalope 这取决于您使用的是哪种 JVM。 Android 的 Dalvic 做的优化可能比 Oracle 或 IBM JVM 做的少或其他优化。
    • @jackalope - 在大多数情况下,任何相当好的 JITC 都会删除 getter/setter 调用。
    • Thomas,公平地说 Dalvik 不是 JVM。
    【解决方案4】:

    给自己买一本《Effective Java》一书。

    • 第 14 项,在公共类中使用访问器方法而不是公共字段。

    在这篇文章中,Joshua Bloch 说包私有或嵌套类中的公共字段没有任何固有的错误,但强烈建议不要使用公共类。

    他对这个主题进行了更详细的介绍,这是一本很棒的书,建议你买一本。

    【讨论】:

    • 如果您的意思是有效 Java,那么我同意这是一本好书。
    • @Benjamin 我一直在写!它就在我面前。
    【解决方案5】:

    想象一下,如果其他程序员正在使用您的代码。如果您不提供 setter 和 getter 方法,那么他可以直接调用您的变量,它肯定会影响您的代码。并且可能会导致安全问题 所以通过提供 POJO 类,你是在强迫他调用你的方法,而不是直接调用你的实例变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 2010-09-08
      • 1970-01-01
      • 2012-11-30
      • 2013-04-08
      • 2014-10-04
      • 2017-03-25
      相关资源
      最近更新 更多