Czy istnieje różnica preferencji lub zachowania między używaniem:
if(obj.getClass().isArray()) {}
i
if(obj instanceof Object[]) {}
?
Czy istnieje różnica preferencji lub zachowania między używaniem:
if(obj.getClass().isArray()) {}
i
if(obj instanceof Object[]) {}
?
Odpowiedzi:
W większości przypadków należy użyć rozszerzenia instanceof do sprawdzenia, czy obiekt jest tablicą operatora.
Ogólnie rzecz biorąc, typ obiektu jest testowany przed obniżeniem do określonego typu, który jest znany w czasie kompilacji. Na przykład, być może napisałeś jakiś kod, który może działać z Integer[]rozszerzeniem lub int[]. Chciałbyś chronić swoje obsady za pomocą instanceof:
if (obj instanceof Integer[]) {
Integer[] array = (Integer[]) obj;
/* Use the boxed array */
} else if (obj instanceof int[]) {
int[] array = (int[]) obj;
/* Use the primitive array */
} else ...
Na poziomie maszyny JVM instanceofoperator tłumaczy na konkretną „instancję” dokonuje kod bajtowy , który jest zoptymalizowany w większości implementacji JVM.
W rzadszych przypadkach możesz użyć odbicia, aby przejść przez graf obiektów nieznanych typów. W takich przypadkach isArray()metoda może być pomocna, ponieważ nie znasz typu komponentu w czasie kompilacji; możesz na przykład implementować jakiś mechanizm serializacji i być w stanie przekazać każdy składnik tablicy do tej samej metody serializacji, niezależnie od typu.
Istnieją dwa specjalne przypadki: odwołania o wartości null i odwołania do tablic pierwotnych.
Zerowe odwołanie spowoduje instanceofwynik false, podczas gdy isArrayzgłaszaNullPointerException .
Zastosowana do tablicy pierwotnej instanceofdaje wyniki, falsechyba że typ składnika w operandzie po prawej stronie dokładnie odpowiada typowi składnika. W przeciwieństwie do isArray()tego zwróci truedla dowolnego typu składnika.
obj instanceof int[]daje falseto wynik po przypisaniu int[]do obj, to się mylisz.
obj instanceof Object[]ustępuje, falsejeśli Object obj = new int[7].
java.lang.Object, więc to ma sens. Ale instanceofnadal można go używać do testowania prymitywnych tablic.
isArray()należy używać wywołań . W bardzo nieogólnym, specjalnym przypadku posiadania tylko tablic obiektów, instanceofzapewnia alternatywę o wysokiej wydajności.
Jeśli objjest typu int[]powiedz, to będzie mieć tablicę, Classale nie będzie instancją Object[]. Więc co chcesz zrobić obj. Jeśli masz zamiar to rzucić, idź z instanceof. Jeśli zamierzasz użyć odbicia, użyj .getClass().isArray().
getClass().isArray() jest znacznie wolniejszy na Sun Java 5 lub 6 JRE niż na IBM.
Do tego stopnia, że korzystanie clazz.getName().charAt(0) == '['z Sun JVM jest szybsze.
Niedawno napotkałem problem podczas aktualizacji aplikacji Groovy z JDK 5 do JDK 6. Używanie isArray()nie powiodło się w JDK6:
MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...
Zmiana, aby instanceof Object[]to naprawić.
isArrayjest metodą Class, nie Type, więc oczywiście jej GenericArrayTypeImplnie ma. I getClassnigdy nie możesz zwrócić nie- Class Type, więc ty (lub Groovy ??) musiałeś zrobić coś złego, aby to uzyskać, na przykład zakładając, że każdy Typejest Class.
Odbicie tablicy w języku Java jest stosowane w przypadkach, gdy nie masz instancji klasy, na której można by wykonać „instanceof”. Na przykład, jeśli piszesz pewien rodzaj struktury iniekcyjnej, która wstrzykuje wartości do nowej instancji klasy, takiej jak JPA, musisz użyć funkcji isArray ().
Pisałem o tym na blogu na początku grudnia. http://blog.adamsbros.org/2010/12/08/java-array-reflection/
Jeśli kiedykolwiek będziesz miał wybór między rozwiązaniem odblaskowym a nieodblaskowym, nigdy nie wybieraj rozwiązania odblaskowego (obejmującego obiekty klasy). Nie chodzi o to, że jest „źle” czy coś, ale wszystko, co wymaga refleksji, jest generalnie mniej oczywiste i mniej jasne.
Nie ma różnicy w zachowaniu, które mogę znaleźć między tymi dwoma (poza oczywistym przypadkiem zerowym). Jeśli chodzi o preferowaną wersję, wybrałbym drugą. Jest to standardowa metoda w Javie.
Jeśli dezorientuje to czytelników twojego kodu (ponieważ String[] instanceof Object[]jest prawdą), możesz użyć pierwszego, aby być bardziej wyraźnym, jeśli recenzenci kodu będą o to pytać.