범용 유형의 java.util을 가져옵니다.목록.
있습니다.
List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();
목록의 일반 유형을 쉽게 검색할 수 있는 방법이 있습니까?
이러한 필드가 실제로 특정 클래스의 필드일 경우 약간의 반성을 통해 얻을 수 있습니다.
package test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
public class Test {
List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();
public static void main(String... args) throws Exception {
Field stringListField = Test.class.getDeclaredField("stringList");
ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0];
System.out.println(stringListClass); // class java.lang.String.
Field integerListField = Test.class.getDeclaredField("integerList");
ParameterizedType integerListType = (ParameterizedType) integerListField.getGenericType();
Class<?> integerListClass = (Class<?>) integerListType.getActualTypeArguments()[0];
System.out.println(integerListClass); // class java.lang.Integer.
}
}
매개 변수 유형 및 메서드 반환 유형에 대해서도 이 작업을 수행할 수 있습니다.
그러나, 수강자가 클래스나 방법의 같은 범위내에 있는 경우, 수강자에 대해 알 필요가 있는 경우는, 이미 스스로 선언하고 있기 때문에, 수강자를 알 필요가 없습니다.
메서드 파라미터에도 동일한 작업을 수행할 수 있습니다.
Method method = someClass.getDeclaredMethod("someMethod");
Type[] types = method.getGenericParameterTypes();
//Now assuming that the first parameter to the method is of type List<Integer>
ParameterizedType pType = (ParameterizedType) types[0];
Class<?> clazz = (Class<?>) pType.getActualTypeArguments()[0];
System.out.println(clazz); //prints out java.lang.Integer
간단한 답변: 아니요.
복제품일 수 있으므로 현재 적절한 것을 찾을 수 없습니다.
Java는 유형 삭제라고 불리는 것을 사용합니다. 즉, 실행 시 두 개체가 동일함을 의미합니다.컴파일러는 목록에 정수 또는 문자열이 포함되어 있다는 것을 알고 있기 때문에 안전한 타입 환경을 유지할 수 있습니다.이 정보는 실행 시(개체 인스턴스 기준) 손실되며 목록에는 '개체'만 포함됩니다.
클래스에 대해, 어떤 유형으로 매개 변수를 지정할 수 있는지 알 수 있지만, 일반적으로 이것은 "객체"를 확장하는 모든 항목입니다.유형을 다음과 같이 정의하는 경우:
class <A extends MyClass> AClass {....}
AClass.class에는 파라미터 A가 MyClass에 의해 경계가 되어 있다는 사실만 포함되어 있습니다.그 이상의 것은 알 수 없습니다.
컬렉션의 일반 유형은 컬렉션에 실제로 개체가 포함되어 있는 경우에만 문제가 됩니다.그래서 그냥 하는 게 더 쉬울 것 같지 않아요?
Collection<?> myCollection = getUnknownCollectionFromSomewhere();
Class genericClass = null;
Iterator it = myCollection.iterator();
if (it.hasNext()){
genericClass = it.next().getClass();
}
if (genericClass != null) { //do whatever we needed to know the type for
런타임에는 범용 타입과 같은 것이 없지만 런타임에 포함된 오브젝트는 선언된 범용 타입과 동일한 타입임을 보증하기 때문에 아이템의 클래스를 처리하기 전에 테스트하는 것만으로 충분합니다.
다른 방법은 목록을 처리하여 올바른 유형의 멤버를 가져오거나 다른 멤버를 무시하거나 다른 멤버를 처리하는 것입니다.
Map<Class<?>, List<Object>> classObjectMap = myCollection.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(Object::getClass));
// Process the list of the correct class, and/or handle objects of incorrect
// class (throw exceptions, etc). You may need to group subclasses by
// filtering the keys. For instance:
List<Number> numbers = classObjectMap.entrySet().stream()
.filter(e->Number.class.isAssignableFrom(e.getKey()))
.flatMap(e->e.getValue().stream())
.map(Number.class::cast)
.collect(Collectors.toList());
그러면 클래스가 하위 클래스였던 모든 항목의 목록이 표시됩니다.Number
그런 다음 필요에 따라 처리할 수 있습니다.나머지 항목들은 다른 목록으로 걸러졌다.지도에 표시되므로 원하는 대로 처리하거나 무시할 수 있습니다.
다른 클래스의 항목을 모두 무시하는 경우는, 다음과 같이 간단하게 실시할 수 있습니다.
List<Number> numbers = myCollection.stream()
.filter(Number.class::isInstance)
.map(Number.class::cast)
.collect(Collectors.toList());
목록에 특정 클래스에 일치하는 항목만 포함되도록 유틸리티 메서드를 생성할 수도 있습니다.
public <V> List<V> getTypeSafeItemList(Collection<Object> input, Class<V> cls) {
return input.stream()
.filter(cls::isInstance)
.map(cls::cast)
.collect(Collectors.toList());
}
한 필드의 일반 유형을 찾는 경우:
((Class)((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]).getSimpleName()
유형의 가 있는 반환된 가 있을 때 이 했습니다.Collection
범용 타입에 액세스 합니다.
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
public class Test {
public List<String> test() {
return null;
}
public static void main(String[] args) throws Exception {
for (Method method : Test.class.getMethods()) {
Class returnClass = method.getReturnType();
if (Collection.class.isAssignableFrom(returnClass)) {
Type returnType = method.getGenericReturnType();
if (returnType instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) returnType;
Type[] argTypes = paramType.getActualTypeArguments();
if (argTypes.length > 0) {
System.out.println("Generic type is " + argTypes[0]);
}
}
}
}
}
}
출력은 다음과 같습니다.
범용 유형은 클래스 java.lang입니다.스트링
Steve K의 답변에 대해 자세히 설명하겠습니다.
/**
* Performs a forced cast.
* Returns null if the collection type does not match the items in the list.
* @param data The list to cast.
* @param listType The type of list to cast to.
*/
static <T> List<? super T> castListSafe(List<?> data, Class<T> listType){
List<T> retval = null;
//This test could be skipped if you trust the callers, but it wouldn't be safe then.
if(data!=null && !data.isEmpty() && listType.isInstance(data.iterator().next().getClass())) {
@SuppressWarnings("unchecked")//It's OK, we know List<T> contains the expected type.
List<T> foo = (List<T>)data;
return retval;
}
return retval;
}
Usage:
protected WhateverClass add(List<?> data) {//For fluant useage
if(data==null) || data.isEmpty(){
throw new IllegalArgumentException("add() " + data==null?"null":"empty"
+ " collection");
}
Class<?> colType = data.iterator().next().getClass();//Something
aMethod(castListSafe(data, colType));
}
aMethod(List<Foo> foo){
for(Foo foo: List){
System.out.println(Foo);
}
}
aMethod(List<Bar> bar){
for(Bar bar: List){
System.out.println(Bar);
}
}
런타임에는 할 수 없습니다.
그러나 반사를 통해 유형 매개변수에 액세스할 수 있습니다.해라
for(Field field : this.getDeclaredFields()) {
System.out.println(field.getGenericType())
}
법getGenericType()
라고 입력합니다. 이경, 것것의 of of of of of of in 、 、 in 、 in 、 in 、 。ParametrizedType
getRawType()
에는 (이것에는)이 됩니다.List.class
및 (''))getActualTypeArguments()
되며, 이 은 (길이가 1인 경우)를합니다.String.class
★★★★★★★★★★★★★★★★★」Integer.class
를 참조해 주세요.
같은 문제가 있었지만, 대신 인스턴스(instance)를 사용했습니다.이런 식으로 했습니까?
List<Object> listCheck = (List<Object>)(Object) stringList;
if (!listCheck.isEmpty()) {
if (listCheck.get(0) instanceof String) {
System.out.println("List type is String");
}
if (listCheck.get(0) instanceof Integer) {
System.out.println("List type is Integer");
}
}
}
여기에는 선택되지 않은 캐스팅을 사용해야 하므로 목록과 어떤 유형일 수 있는지 알고 있는 경우에만 이 작업을 수행하십시오.
generally반 、 냐 generally 、 냐 generally generally generally generally generally 。List<String>
★★★★★★★★★★★★★★★★★」List<Integer>
같은 런타임클래스를 공유합니다.
단, 목록을 보유하고 있는 필드의 선언된 유형을 반영할 수 있습니다(선언된 유형 자체가 값을 모르는 유형 매개 변수를 참조하지 않는 경우).
import org.junit.Assert;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class GenericTypeOfCollectionTest {
public class FormBean {
}
public class MyClazz {
private List<FormBean> list = new ArrayList<FormBean>();
}
@Test
public void testName() throws Exception {
Field[] fields = MyClazz.class.getFields();
for (Field field : fields) {
//1. Check if field is of Collection Type
if (Collection.class.isAssignableFrom(field.getType())) {
//2. Get Generic type of your field
Class fieldGenericType = getFieldGenericType(field);
//3. Compare with <FromBean>
Assert.assertTrue("List<FormBean>",
FormBean.class.isAssignableFrom(fieldGenericType));
}
}
}
//Returns generic type of any field
public Class getFieldGenericType(Field field) {
if (ParameterizedType.class.isAssignableFrom(field.getGenericType().getClass())) {
ParameterizedType genericType =
(ParameterizedType) field.getGenericType();
return ((Class)
(genericType.getActualTypeArguments()[0])).getSuperclass();
}
//Returns dummy Boolean Class to compare with ValueObject & FormBean
return new Boolean(false).getClass();
}
}
다른 사람들이 말한 것처럼, 유일한 정답은 "아니오"입니다. 유형이 지워졌습니다.
목록에 0이 아닌 수의 요소가 있는 경우 첫 번째 요소의 유형을 조사할 수 있습니다(예를 들어 getClass 메서드를 사용합니다).그러면 목록의 일반 유형을 알 수 없지만 일반 유형은 목록에 있는 유형의 슈퍼 클래스라고 가정하는 것이 합리적입니다.
나는 그 접근법을 옹호하지는 않겠지만, 난처한 상황에서는 그것이 유용할 수도 있다.
이를 위한 작은 도우미 방법:
/**
* Get type of collection field.
*
* @param aClass A class containing collection.
* @param collectionName A collection field name.
*/
@SneakyThrows
public static Class<?> getCollectionType(Class<?> aClass, String collectionName) {
Field field = aClass.getDeclaredField(collectionName);
ParameterizedType genericType = (ParameterizedType) field.getGenericType();
return (Class<?>) genericType.getActualTypeArguments()[0];
}
하여 Reflection을 .Field
은 그냥요.field.genericType
언급URL : https://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list
'programing' 카테고리의 다른 글
(Java) 패키지 구성에 대한 베스트 프랙티스가 있습니까? (0) | 2022.08.27 |
---|---|
StringUtils.isBlank() vs String.isEmpty() (0) | 2022.08.27 |
상태 변경 후 v-if를 사용하여 요소 숨기기 (0) | 2022.08.27 |
특정 방법으로 Vue.js Vuex 모듈 자동 등록 (0) | 2022.08.27 |
Vuex 이름 지정 저장소 집합 두 상태 (0) | 2022.08.27 |