Frage Warum sollte ich nicht unveränderliche POJOs anstelle von JavaBeans verwenden?


Ich habe jetzt ein paar Java-Anwendungen implementiert, bisher nur Desktop-Anwendungen. Ich bevorzuge es, unveränderliche Objekte für die Weitergabe der Daten in der Anwendung zu verwenden, anstatt Objekte mit Mutatoren (Setter) zu verwenden und Getter), auch JavaBeans genannt.

Aber in der Java-Welt scheint es viel häufiger zu sein, JavaBeans zu verwenden, und ich kann nicht verstehen, warum ich sie stattdessen verwenden sollte. Persönlich sieht der Code besser aus, wenn er nur mit unveränderlichen Objekten arbeitet, anstatt den Zustand ständig zu verändern.

Unveränderliche Objekte werden auch in empfohlen Punkt 15: Veränderlichkeit minimieren, Effektives Java 2ed.

Wenn ich ein Objekt habe Person implementiert als a JavaBean es würde aussehen wie:

public class Person {
    private String name;
    private Place birthPlace;

    public Person() {}

    public setName(String name) {
        this.name = name;
    }

    public setBirthPlace(Place birthPlace) {
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

Und das gleiche Person implementiert als ein unveränderlich Objekt:

public class Person {
    private final String name;
    private final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

Oder näher an einem struct in C:

public class Person {
    public final String name;
    public final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }
}

Ich könnte auch Getter im unveränderlichen Objekt haben, um die Implementierungsdetails zu verbergen. Aber da ich es nur als struct Ich bevorzuge es, die "Getter" zu überspringen und es einfach zu halten.

Ich verstehe einfach nicht, warum es besser ist, JavaBeans zu verwenden oder ob ich mit meinen unveränderlichen POJOs weitermachen kann und sollte.

Viele der Java-Bibliotheken scheinen JavaBeans besser zu unterstützen, aber vielleicht wird mehr Unterstützung für unveränderliche POJOs mit der Zeit beliebter?


75
2017-08-18 10:33


Ursprung


Antworten:


Bevorzugen JavaBeans Wann

  • Sie müssen mit Umgebungen interagieren, die sie erwarten
  • Sie haben viele Eigenschaften, für die es unpraktisch wäre, alle Initialisierungen bei der Instanziierung durchzuführen
  • Sie haben einen Zustand, der aus irgendeinem Grund teuer oder unmöglich zu kopieren ist, aber eine Mutation erfordert
  • Sie denken, dass Sie irgendwann ändern müssen, wie auf Eigenschaften zugegriffen wird (z. B. von gespeicherten zu berechneten Werten, Zugriffsberechtigung usw.).
  • Sie wollen Kodierungsstandards folgen, die gedankenlos darauf bestehen, dass es irgendwie "objektorientierter" ist, JavaBeans zu verwenden

Bevorzugen Sie unveränderliche POJOs Wann

  • Sie haben eine kleine Anzahl einfacher Eigenschaften
  • Sie müssen nicht mit Umgebungen interagieren, die JavaBean-Konventionen annehmen
  • Es ist einfach (oder zumindest möglich), den Zustand beim Klonen Ihres Objekts zu kopieren
  • Sie haben nie vor, das Objekt überhaupt zu klonen
  • Sie sind ziemlich sicher, dass Sie nie ändern müssen, wie auf Eigenschaften wie oben zugegriffen wird
  • Es macht Ihnen nichts aus, dem Jammern zu lauschen, wenn Ihr Code nicht ausreichend "objektorientiert" ist

74
2017-08-18 11:00



Ich war überrascht, dass das Wort Faden tauchte nirgendwo in dieser Diskussion auf.

Einer der Hauptvorteile von unveränderlichen Klassen besteht darin, dass sie inhärent threadsicher sind, da kein veränderbarer, gemeinsamer Status vorliegt.

Dies erleichtert nicht nur die Codierung, sondern bietet Ihnen als Nebeneffekt auch zwei Leistungsvorteile:

  • Weniger Bedarf für die Synchronisation.

  • Mehr Spielraum für die Verwendung von endgültigen Variablen, die spätere Compiler-Optimierungen erleichtern können.

Ich versuche wirklich, zu unveränderlichen Objekten statt zu JavaBean-Stilklassen zu gelangen. Das Freilegen der Eingeweide von Objekten über Getter und Setter sollte wahrscheinlich nicht die Standardauswahl sein.


37
2017-08-18 11:29



Nun, es kommt darauf an, was du versuchst. Wenn Sie mit einer persistenten Schicht arbeiten und eine Zeile aus der Datenbank in ein POJO holen und eine Eigenschaft ändern und sie zurückspeichern möchten, wäre die Verwendung von JavaBean besser, besonders wenn Sie viele Eigenschaften haben.

Berücksichtigen Sie, dass Ihre Person, hat viele Felder wie, erste, mittlere, Nachname, Geburtsdatum, Familienmitglieder, Ausbildung, Job, Gehalt usw.

Und diese Person ist zufällig eine Frau, die gerade geheiratet hat und akzeptiert hat, dass ihr Nachname geändert wird, und Sie müssen die Datenbank aktualisieren.

Wenn Sie unveränderliches POJO verwenden, holen Sie ein Person-Objekt, das sie repräsentiert, dann erstellen Sie ein neues Person-Objekt, dem Sie alle Eigenschaften, die Sie nicht geändert haben, und den neuen Nachnamen übergeben und speichern.

Wenn es eine Java-Bean wäre, können Sie einfach setLastName () und speichern Sie es.

Es ist "Veränderlichkeit minimieren" und nicht "veränderbare Objekte verwenden". Einige Situationen funktionieren besser mit veränderbaren Objekten, es ist wirklich Ihre Aufgabe zu entscheiden, ob ein veränderbares Objekt besser zu Ihrem Programm passt oder nicht. Du solltest nicht immer sagen: "Benutze unveränderliche Objekte", sondern schau dir an, wie viele Klassen du unveränderbar machen kannst, bevor du anfängst, dich selbst zu verletzen.


16
2017-08-18 10:41



Zusammenfassend andere Antworten denke ich, dass:

  • Inmutabilität erleichtert die Korrektheit (Strukturen können als Referenz übergeben werden, und Sie wissen, dass nichts von einem fehlerhaften / böswilligen Client zerstört wird) und Einfachheit des Codes
  • Mutabilität erleichtert die Homogenität: Spring und andere Frameworks erstellen ein Objekt ohne Argumente, legen Objekteigenschaften und fest voi là. Erleichtern Sie sich auch die Verwendung von Interfaces mit der gleichen Klasse, um Daten zu geben und Änderungen zu speichern (was Sie nicht benötigen get(id): Client und save(MutableClient), wobei MutableClient ein Nachkomme von Client ist.

Wenn es einen Zwischenpunkt gäbe (create, set properties, make inmutable), könnten Frameworks mehr zu einem untauglichen Ansatz führen.

Wie auch immer, ich schlage vor, in unveränderlichen Objekten als "nur Java Beans" zu denken, was den Punkt betont, dass wenn Sie ein guter Junge sind und diese gefährliche setProperty Methode nicht berühren, alles in Ordnung ist.


7
2017-08-18 11:29



Aus Java 7 können Sie unveränderliche Beans, das Beste aus beiden Welten, haben. Verwenden Sie die Annotation @ConstructorProperties für Ihren Konstruktor.

public class Person {
    private final String name;
    private final Place birthPlace;

    @ConstructorProperties({"name", "birthPlace"})
    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

3
2017-09-23 08:02



Ich glaube nicht, dass unveränderliche Objekte so populär werden, um ehrlich zu sein.

Ich sehe die Vorteile, aber Frameworks wie Hibernate und Spring sind derzeit sehr beliebt (und das aus gutem Grund), und sie funktionieren wirklich am besten mit Beans.

Ich denke also nicht, dass Unveränderbarkeit schlecht ist, aber es würde sicherlich Ihre Integrationsmöglichkeiten mit aktuellen Frameworks einschränken.

BEARBEITEN Die Kommentare veranlassen mich, meine Antwort ein wenig zu klären.

Es gibt sicherlich Problembereiche, in denen Unveränderbarkeit sehr nützlich ist und tatsächlich verwendet wird. Aber ich denke, der aktuelle Default scheint veränderlich zu sein, da dies meistens erwartet wird und nur unveränderbar, wenn das einen klaren Vorteil hat.

Und obwohl es in der Tat möglich ist, Konstruktoren mit Argumenten im Frühjahr zu verwenden, scheint es eine Möglichkeit zu sein, Legacy- und / oder Drittanbieter-Code mit Ihrem schönen, brandneuen Spring-Code zu verwenden. Zumindest habe ich das aus der Dokumentation entnommen.


2
2017-08-18 10:39