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 instanceof
operator 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 instanceof
wynik false
, podczas gdy isArray
zgłaszaNullPointerException
.
Zastosowana do tablicy pierwotnej instanceof
daje wyniki, false
chyba że typ składnika w operandzie po prawej stronie dokładnie odpowiada typowi składnika. W przeciwieństwie do isArray()
tego zwróci true
dla dowolnego typu składnika.
obj instanceof int[]
daje false
to wynik po przypisaniu int[]
do obj
, to się mylisz.
obj instanceof Object[]
ustępuje, false
jeśli Object obj = new int[7]
.
java.lang.Object
, więc to ma sens. Ale instanceof
nadal 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, instanceof
zapewnia alternatywę o wysokiej wydajności.
Jeśli obj
jest typu int[]
powiedz, to będzie mieć tablicę, Class
ale 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ć.
isArray
jest metodą Class
, nie Type
, więc oczywiście jej GenericArrayTypeImpl
nie ma. I getClass
nigdy 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 Type
jest 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ć.