Определение типа объектов в коллекции или массиве
Предположим, что у меня есть массив 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?
Ответы
Ответ 1
Массивы (например, 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>
)
Невозможно получить параметр типа. Java использует тип erasure, поэтому информация теряется во время выполнения.
Вы можете угадать объявленный тип коллекций на основе типов элементов:
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
}
}
Ответ 2
Вы можете использовать классы getComponentType()
. Например.
public static final Class<?> getBaseType(Object obj) {
Class<?> type = obj.getClass();
while (type.isArray()) {
type = type.getComponentType();
}
return type;
}
type
будет тогда любым базовым типом.
Это будет работать, если obj
- double[][][][][][]
или просто double[]
или что-то еще.
Что касается дженериков, те вещи в <
и >
. Вызывается стирание типа, то есть вы не можете определить, какой тип из самого ArrayList
.
Ответ 3
В случае массивов его можно идентифицировать по типу array
, (например, array
of int[][]
всегда будет давать вам int
.
В случае ArrayList
, если ваш ArrayList
является гетерогенными объектами, тогда get(i)
всегда даст вам элемент типа Object
. Чтобы узнать свой класс, вы можете использовать метод getClass()
Object
.
Ответ 4
Следующий код работает... как вы просили.
Здесь я использовал
object.getClass(). GetSimpleName()
для arraylist вы должны добавить элемент определенного типа, так как вы используете generics. а затем получить их и использовать тот же метод getClass(). getSimpleName().
public class ShowObjectType {
public static void main(String[] args) {
int arr[][] = { { 2, 3 }, { 4, 0 } };
char[][] arr1 = { { 'a', 'c' }, { 'b', 'd' } };
ArrayList<Integer> arr2 = new ArrayList<Integer>();
arr2.add(4);
ArrayList<Point> arr3 = new ArrayList<Point>();
arr3.add(new Point());
System.out.println(arr.getClass().getSimpleName());
System.out.println(arr1.getClass().getSimpleName());
System.out.println(arr2.get(0).getClass().getSimpleName());
System.out.println(arr3.get(0).getClass().getSimpleName());
}
}
class Point {
}
надеюсь, что это поможет
Ответ 5
Да, они называются Generics. Но лучше подумать, что это заставляет арриалиста удерживать только "точечные" объекты.
Ответ 6
Два способа сделать это:
Для этого вы также можете обратиться к тому, что я нашел:
http://docs.oracle.com/javase/tutorial/reflect/class/classNew.html
Ответ 7
Вы можете получить базовый тип массива как:
Object obj = new Long[0];
Class ofArray = obj.getClass().getComponentType();
Для типа Collection вы можете использовать метод 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);
}
...
}
Ответ 8
Для примитивных типов вы можете использовать этот код:
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());
}