Определение типа объектов в коллекции или массиве

предположим, что у меня есть массив 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 удерживать только "точечные" объекты.


два способа сделать это:

  1. использовать instanceof оператора.

  2. вызов 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());
    }