Определение типа объектов в коллекции или массиве
предположим, что у меня есть массив int[][] или массив char[][] или ArrayList. Есть ли способ в java узнать тип базового класса массива. Например:
int[][] gives output as int.
char[][] gives output as char.
ArrayList<Integer> gives output Integer.
ArrayList<Point> gives Point. (It should also work for a custom type)
можно ли это сделать на Java?
8 ответов
массивы (например,int[][])
вы можете получить тип компонента массива, используя getComponentType():
(new int[10][10]).getClass().getComponentType().getComponentType(); // int
для массивов произвольной глубины используйте цикл:
Object array = new int[10][][][];
Class<?> type = array.getClass();
while (type.isArray())
{
type = type.getComponentType();
}
assert type == Integer.TYPE;
Универсального Типа (например,ArrayList<Integer>)
невозможно получить параметр type. Java использует стирания типа, поэтому информация теряется во время выполнения.
вы можете угадать объявленный тип коллекций на основе типов элементов:
import java.util.*;
public class CollectionTypeGuesser
{
static Set<Class<?>> supers(Class<?> c)
{
if (c == null) return new HashSet<Class<?>>();
Set<Class<?>> s = supers(c.getSuperclass());
s.add(c);
return s;
}
static Class<?> lowestCommonSuper(Class<?> a, Class<?> b)
{
Set<Class<?>> aSupers = supers(a);
while (!aSupers.contains(b))
{
b = b.getSuperclass();
}
return b;
}
static Class<?> guessElementType(Collection<?> collection)
{
Class<?> guess = null;
for (Object o : collection)
{
if (o != null)
{
if (guess == null)
{
guess = o.getClass();
}
else if (guess != o.getClass())
{
guess = lowestCommonSuper(guess, o.getClass());
}
}
}
return guess;
}
static class C1 { }
static class C2 extends C1 { }
static class C3A extends C2 { }
static class C3B extends C2 { }
public static void main(String[] args)
{
ArrayList<Integer> listOfInt = new ArrayList<Integer>();
System.out.println(guessElementType(listOfInt)); // null
listOfInt.add(42);
System.out.println(guessElementType(listOfInt)); // Integer
ArrayList<C1> listOfC1 = new ArrayList<C1>();
listOfC1.add(new C3A());
System.out.println(guessElementType(listOfC1)); // C3A
listOfC1.add(new C3B());
System.out.println(guessElementType(listOfC1)); // C2
listOfC1.add(new C1());
System.out.println(guessElementType(listOfC1)); // C1
}
}
вы можете использовать классы getComponentType(). Например.
public static final Class<?> getBaseType(Object obj) {
Class<?> type = obj.getClass();
while (type.isArray()) {
type = type.getComponentType();
}
return type;
}
type будет тогда любым базовым типом.
это будет работать, если obj is double[][][][][][] или просто double[], или что-то еще.
что касается дженериков, то эти вещи в < и >. Происходит стирание типа, то есть вы не можете определить, какой тип они из .
в случае массивов он может быть идентифицирован с помощью типа array (например,array of int[][] всегда будет давать вам int.
в случае ArrayList, если ArrayList тогда гетерогенные объекты,get(i) всегда будет давать вам элемент типа Object. Чтобы узнать его класс, вы можете использовать getClass() метод Object.
Да, они называются дженериками. Но лучше думать, что это заставляет Arraylist удерживать только "точечные" объекты.
два способа сделать это:
использовать
instanceofоператора.вызов
getClass()на объекте (сначала проверьте значение null).
для этого вы также можете сослаться на то, что я нашел: http://docs.oracle.com/javase/tutorial/reflect/class/classNew.html
Вы можете получить базовый тип массива как:
Object obj = new Long[0];
Class ofArray = obj.getClass().getComponentType();
для типа коллекции можно использовать метод getClass() или instanceof. Например:
ArrayList<Object> list = ...;
for (Object obj : list) {
if (obj instanceof String) {
...
}
}
for (Object o : list) {
if (o.getClass().equals(Integer.TYPE)) {
handleInt((int)o);
}
else if (o.getClass().equals(String.class)) {
handleString((String)o);
}
...
}
для примитивных типов вы можете использовать этот код:
public static void main(String[] args) {
int arr[] = {1,2,3};
int arr2[][] = {{1},{2},{3}};
char arrc[] = {'v', 'c', 'r'};
System.out.println(arr.getClass().getCanonicalName());
System.out.println(arr2.getClass().getCanonicalName());
System.out.println(arrc.getClass().getCanonicalName());
}
выход:
int[]
int[][]
char[]
для ArrayList, если вам нужно работать с его элементами (если список не пуст) вы можете проверить тип первого элемента
ArrayList<Integer> arrInt = new ArrayList<Integer>();
arrInt.add(100);
if (arrInt instanceof List && arrInt.size() > 0) {
System.out.println(arrInt.get(0).getClass().getCanonicalName());
}