Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

A Java7 egyik csendes újítása a java.util.Objects osztály, amely közel tucatnyi statikus metódust ad az objektumok kezeléséhez, amely metódusok egy része nem esik zavarba, ha null értéket kap. Az Objects tipikus esete utility osztályoknak, final módosítóval van ellátva, illetve van egy privát konstruktora is:

Code Block
languagejava
titleObjects.java
firstline37
linenumberstrue
private Objects() {
  throw new AssertionError("No java.util.Objects instances for you!");
}

Suhanjunk végig az eddig megvalósított metóduslistán... (smile)

equals

Az első metódus egy egyszerű egyezőség vizsgálat, amely levizsgálja a két összehasonlítandó paraméter közül az elsőt, hogy annak értéke nem null, majd ezek után végzi el az összevetést, így ez a metódus null safe: használata során nem kell NullPointerException kivételre számítanunk. A forrása egyszerű:

Code Block
languagejava
titleObjects.java
firstline56
linenumberstrue
public static boolean equals(Object a, Object b) {
  return (a == b) || (a != null && a.equals(b));
}

Használata:

Code Block
languagejava
titleExample.java
String a = null;
String b = null;
System.out.println(Objects.equals(a, b));
b = "nem üres";
System.out.println(Objects.equals(a, b));
a = "nem üres";
System.out.println(Objects.equals(a, b));

Az eredmény:

Code Block
languagehtml/xml
true
false
true

deepEquals

A deepEquals metódus hasonlít a fentire, de sima equals helyett az Arrays.deepEquals metódust hívja meg null ellenőrzéssel, így egy sorban tudunk két tömböt összevetni:

Code Block
languagejava
titleObjects.java
firstline77
linenumberstrue
public static boolean deepEquals(Object a, Object b) {
  if (a == b)
    return true;
  else if (a == null || b == null)
    return false;
  else
    return Arrays.deepEquals0(a, b);
}

Használata:

Code Block
languagejava
titleExample.java
String[] a = null;
String[] b = null;
System.out.println(Objects.deepEquals(a, b));
b = new String[]{"semmi", "újabb semmi"};
System.out.println(Objects.deepEquals(a, b));
a = new String[]{"semmi", "újabb semmi"};
System.out.println(Objects.deepEquals(a, b));

Az eredmény:

Code Block
languagehtml/xml
true
false
true

hashCode

A hashCode lehetőséget ad null safe hívásra, az átadott objektumnak csak akkor hívódik meg a hashCode metódusa, ha a paraméter nem null:

Code Block
languagejava
titleObjects.java
firstline95
linenumberstrue
public static int hashCode(Object o) {
  return o != null ? o.hashCode() : 0;
}

Használata:

Code Block
languagejava
titleExample.java
String a = null;
System.out.println(Objects.hashCode(a));
a = "semmi";
System.out.println(Objects.hashCode(a));

Az eredmény:

Code Block
languagehtml/xml
0
109322039

hash

Hasonlít az előzőre, azzal a különbséggel, hogy a metódus paraméterlistája dinamikusan bővíthető, s az eredményül kapott objektum-tömb átadásra kerül a Arrays.hashCode metódusnak, így lehetőségünk van null biztos hash képzésre több argumentumból:

Code Block
languagejava
titleObjects.java
firstline125
linenumberstrue
public static int hash(Object... values) {
  return Arrays.hashCode(values);
}

Használata:

Code Block
languagejava
titleExample.java
String a = null;
String b = null;
System.out.println(Objects.hash(a, b));
b = "semmi";
System.out.println(Objects.hash(a, b));
a = "semmi";
System.out.println(Objects.hash(a, b));

Az eredmény:

Code Block
languagehtml/xml
961
109323000
-796661087

toString

Ez a metódus kissé kilóg a többi közül, mert null biztos konverzióra eddig is lehetőség volt az alább is látható String.valueOf(o) használatával:

Code Block
languagejava
titleObjects.java
firstline139
linenumberstrue
public static String toString(Object o) {
  return String.valueOf(o);
}

Használata:

Code Block
languagejava
titleExample.java
String a = null;
System.out.println(Objects.toString(a));
a = "semmi";
System.out.println(Objects.toString(a));

Az eredmény:

Code Block
languagehtml/xml
null
semmi

toString + alapértelmezett érték

Az előzőnél sokkal hasznosabb metódus a most következő, amelynél megadhatunk egy alapértelmezett értéket, ha az átadott objektum értéke null:

Code Block
languagejava
titleObjects.java
firstline156
linenumberstrue
public static String toString(Object o, String nullDefault) {
  return (o != null) ? o.toString() : nullDefault;
}

Használata:

Code Block
languagejava
titleExample.java
String a = null;
System.out.println(Objects.toString(a, "hopsza, ez null"));
a = "semmi";
System.out.println(Objects.toString(a));

Az eredmény:

Code Block
languagehtml/xml
hopsza, ez null
semmi

compare

A compare metódus két objektum összehasonlítására jó, s ez a többi metódushoz képest két okból is rendhagyó:

  • nem null safe
  • kell neki egy Comparator implementáció, amely szükség esetén lehet null safe
Code Block
languagejava
titleObjects.java
firstline180
linenumberstrue
public static <T> int compare(T a, T b, Comparator<? super T> c) {
  return (a == b) ? 0 :  c.compare(a, b);
}

Használata (hibát okoz):

Code Block
languagejava
titleExample.java
Comparator<String> comparator = new Comparator<String>() {
  public int compare(String o1, String o2)
  {
    return o1.compareTo(o2);
  }
};
    
String a = null;
String b = null;
System.out.println(Objects.compare(a, b, comparator));
b = "semmi";
System.out.println(Objects.compare(a, b, comparator));
a = "semmi";
System.out.println(Objects.compare(a, b, comparator));

Az eredmény:

Code Block
languagehtml/xml
0
Exception in thread "main" java.lang.NullPointerException
    at hu.javaforum.showobjects.App$1.compare(App.java:19)
    at hu.javaforum.showobjects.App$1.compare(App.java:15)
    at java.util.Objects.compare(Objects.java:181)
    at hu.javaforum.showobjects.App.main(App.java:27)

requireNonNull

Ez egy nagyon hasznos metódus, jegyezzük meg, mert nem csinál ugyan sokat, de azt gyakran használjuk, ha paramétereket ellenőrzünk! Megvizsgálja, hogy az átadott első paraméter null értékű-e, ha igen, akkor dob egy NullPointerException kivételt, ha nem, akkor visszaadja az objektumot:

Code Block
languagejava
titleObjects.java
firstline199
linenumberstrue
public static <T> T requireNonNull(T obj) {
  if (obj == null)
    throw new NullPointerException();
  return obj;
}

Használata:

Code Block
languagejava
titleExample.java
String a = Objects.requireNonNull("semmi");
System.out.println(a);
String b = Objects.requireNonNull(null);
System.out.println(b);

Az eredmény:

Code Block
languagehtml/xml
semmi
Exception in thread "main" java.lang.NullPointerException
    at java.util.Objects.requireNonNull(Objects.java:201)
    at hu.javaforum.showobjects.App.main(App.java:17)

requireNonNull + szöveg

Hasonló a fentihez, ám ez esetben megadhatunk egy szöveget, amely adott esetben átadódik a NullPointerException kivételnek:

Code Block
languagejava
titleObjects.java
firstline224
linenumberstrue
public static <T> T requireNonNull(T obj, String message) {
  if (obj == null)
    throw new NullPointerException(message);
  return obj;
}

Használata:

Code Block
languagejava
titleExample.java
String a = Objects.requireNonNull("semmi", "A paraméter értéke null");
System.out.println(a);
String b = Objects.requireNonNull(null, "A paraméter értéke null");
System.out.println(b);

Az eredmény:

Code Block
languagehtml/xml
semmi
Exception in thread "main" java.lang.NullPointerException: A paraméter értéke null
    at java.util.Objects.requireNonNull(Objects.java:226)
    at hu.javaforum.showobjects.App.main(App.java:17)

Konklúzió

Nagyon hasznos osztály, használja mindenki – aki teheti, ugyanis nagyon sok saját osztály van a projektjeinkben, amelyek hasonló vagy pontosan ilyen módon működnek, mivel egy-egy fenti metódus használatával a forráskódunk egyszerűbb és átláthatóbb lesz, másrészt kevesebb saját forráskódot kell majd karbantartanunk.

(inspiráció: www.javabeat.net/2012/06/java-util-objects-a-static-utility-for-objects-introduced-in-java-7/)


Viewtracker