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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 37 |
---|
linenumbers | true |
---|
|
private Objects() {
throw new AssertionError("No java.util.Objects instances for you!");
} |
Suhanjunk végig az eddig megvalósított metóduslistán...
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 56 |
---|
linenumbers | true |
---|
|
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
|
Használata:
Code Block |
---|
language | java |
---|
title | Example.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 |
---|
|
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 77 |
---|
linenumbers | true |
---|
|
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 |
---|
language | java |
---|
title | Example.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 |
---|
|
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 95 |
---|
linenumbers | true |
---|
|
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
|
Használata:
Code Block |
---|
language | java |
---|
title | Example.java |
---|
|
String a = null;
System.out.println(Objects.hashCode(a));
a = "semmi";
System.out.println(Objects.hashCode(a)); |
Az eredmény:
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 125 |
---|
linenumbers | true |
---|
|
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
|
Használata:
Code Block |
---|
language | java |
---|
title | Example.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 |
---|
|
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 139 |
---|
linenumbers | true |
---|
|
public static String toString(Object o) {
return String.valueOf(o);
}
|
Használata:
Code Block |
---|
language | java |
---|
title | Example.java |
---|
|
String a = null;
System.out.println(Objects.toString(a));
a = "semmi";
System.out.println(Objects.toString(a)); |
Az eredmény:
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 156 |
---|
linenumbers | true |
---|
|
public static String toString(Object o, String nullDefault) {
return (o != null) ? o.toString() : nullDefault;
}
|
Használata:
Code Block |
---|
language | java |
---|
title | Example.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 |
---|
|
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 180 |
---|
linenumbers | true |
---|
|
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 |
---|
language | java |
---|
title | Example.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 |
---|
|
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 199 |
---|
linenumbers | true |
---|
|
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
|
Használata:
Code Block |
---|
language | java |
---|
title | Example.java |
---|
|
String a = Objects.requireNonNull("semmi");
System.out.println(a);
String b = Objects.requireNonNull(null);
System.out.println(b); |
Az eredmény:
Code Block |
---|
|
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 |
---|
language | java |
---|
title | Objects.java |
---|
firstline | 224 |
---|
linenumbers | true |
---|
|
public static <T> T requireNonNull(T obj, String message) {
if (obj == null)
throw new NullPointerException(message);
return obj;
}
|
Használata:
Code Block |
---|
language | java |
---|
title | Example.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 |
---|
|
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/)