범용 타입 T의 클래스인스턴스를 가져오려면 어떻게 해야 하나요?
는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.Foo<T>
.법방 . . ..Foo
T
저는 안T.class
.
이 를 회피할 때론 으로 피하는 것이 좋습니다.T.class
간단히 말하면 Java에서는 범용 타입 파라미터의 런타임타입을 확인할 수 없습니다.상세한 것에 대하여는, Java Tutorial 의 type erase 에 관한 장을 참조해 주세요.
은 '입니다.Class
type 파라미터를 범용 타입의 생성자로 변환합니다(예:
class Foo<T> {
final Class<T> typeParameterClass;
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}
클래스 패스에 의존하지 않고 직접 할 수 있는 방법을 찾고 있었습니다.조사해 본 결과, 범용 슈퍼 타입만 있으면 가능하다는 것을 알았습니다.범용 레이어 슈퍼 타입의 DAO 레이어로 작업하고 있었기 때문에, 이 점에서는 문제가 없었습니다.이것이 시나리오에 맞는다면 IMHO에서 가장 깔끔한 접근법입니다.
지금까지 접한 대부분의 범용 사용 사례에는 다음과 같은 일반적인 슈퍼타입이 있습니다. List<T>
★★★★★★에ArrayList<T>
★★★★★★★★★★★★★★★★★」GenericDAO<T>
★★★★★★에DAO<T>
등등.
순수 자바 솔루션
"Java 런타임에 일반 유형에 액세스" 문서에서는 순수 Java를 사용하여 일반 유형을 액세스하는 방법을 설명합니다.
@SuppressWarnings("unchecked")
public GenericJpaDao() {
this.entityBeanType = ((Class) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]);
}
스프링 솔루션
제 프로젝트는 스프링을 이용한 것이었는데 스프링은 유형을 찾는 편리한 유틸리티 방법이 있어서 더욱 좋습니다.이게 제일 깔끔해 보여서 저한테는 가장 좋은 방법이에요.스프링을 사용하지 않았다면 자신만의 유틸리티 방법을 작성할 수 있었을 것입니다.
import org.springframework.core.GenericTypeResolver;
public abstract class AbstractHibernateDao<T extends DomainObject> implements DataAccessObject<T>
{
@Autowired
private SessionFactory sessionFactory;
private final Class<T> genericType;
private final String RECORD_COUNT_HQL;
private final String FIND_ALL_HQL;
@SuppressWarnings("unchecked")
public AbstractHibernateDao()
{
this.genericType = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), AbstractHibernateDao.class);
this.RECORD_COUNT_HQL = "select count(*) from " + this.genericType.getName();
this.FIND_ALL_HQL = "from " + this.genericType.getName() + " t ";
}
풀코드 예시
어떤 사람들은 이것을 작동시키기 위해 코멘트에 어려움을 겪고 있기 때문에, 저는 두 가지 방법을 모두 보여주기 위해 작은 애플리케이션을 작성했습니다.https://github.com/benthurley82/generic-type-resolver-test
작은 . 즉, 자신의 허점을 하면, '허점'이 있습니다.이러한 허점을 정의하면Foo
추상적인 수업입니다., 을 다음과 같이 . : , 、 음 、 래 、 음 、 음 음 、 음 음 that that that
Foo<MyType> myFoo = new Foo<MyType>(){};
(마지막에 있는 이중 괄호를 주의해 주세요).
, 그럼 이제 이 글자의 할 수 .T
「 」:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
, 「」, 「」는 해 주세요.mySuperclass
.클래스 정의의 최종 을 실제로 합니다.T
.
우아한 , 어떤 이 더 좋은지, 어떤 것이 더 좋은지 .new Foo<MyType>(){}
★★★★★★★★★★★★★★★★★」new Foo<MyType>(MyType.class);
당신의 코드로.
예를 들어 다음과 같습니다.
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;
/**
* Captures and silently ignores stack exceptions upon popping.
*/
public abstract class SilentStack<E> extends ArrayDeque<E> {
public E pop() {
try {
return super.pop();
}
catch( NoSuchElementException nsee ) {
return create();
}
}
public E create() {
try {
Type sooper = getClass().getGenericSuperclass();
Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];
return (E)(Class.forName( t.toString() ).newInstance());
}
catch( Exception e ) {
return null;
}
}
}
그 후, 다음과 같이 입력합니다.
public class Main {
// Note the braces...
private Deque<String> stack = new SilentStack<String>(){};
public static void main( String args[] ) {
// Returns a new instance of String.
String s = stack.pop();
System.out.printf( "s = '%s'\n", s );
}
}
인 접근법은 '/'/'/''를 추가하는 입니다.class
다음과 같이 합니다.
public class Foo<T> {
private Class<T> type;
public Foo(Class<T> type) {
this.type = type;
}
public Class<T> getType() {
return type;
}
public T newInstance() {
return type.newInstance();
}
}
일반적인 추상 슈퍼클래스가 있다고 가정해 보겠습니다.
public abstract class Foo<? extends T> {}
다음으로 Foo를 확장한 두 번째 클래스와 T:를 확장한 일반 막대가 있습니다.
public class Second extends Foo<Bar> {}
클래스는 수강할 수 .Bar.class
에서 Foo를 Type
에서) (bert bruynoog를 사용하여 합니다. 답변에서) 그리고 그것을 사용하여 추론합니다.Class
★★★★★★★★★★★★★★★★★★:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
//Parse it as String
String className = tType.toString().split(" ")[1];
Class clazz = Class.forName(className);
이 연산은 이상적이지 않으므로 계산값을 캐시하여 여러 번 계산하지 않도록 하는 것이 좋습니다.일반적인 DAO 구현에는 일반적인 용도가 있습니다.
최종 구현:
public abstract class Foo<T> {
private Class<T> inferedClass;
public Class<T> getGenericClass(){
if(inferedClass == null){
Type mySuperclass = getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
String className = tType.toString().split(" ")[1];
inferedClass = Class.forName(className);
}
return inferedClass;
}
}
다른 함수의 Foo 클래스 또는 Bar 클래스에서 호출된 경우 반환되는 값은 Bar.class입니다.
유효한 솔루션은 다음과 같습니다.
@SuppressWarnings("unchecked")
private Class<T> getGenericTypeClass() {
try {
String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
Class<?> clazz = Class.forName(className);
return (Class<T>) clazz;
} catch (Exception e) {
throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
}
}
참고: 슈퍼클래스로만 사용할 수 있습니다.
- 클래스타입 클래스)로.
Child extends Generic<Integer>
)
또는
- 익명 구현으로 작성해야 합니다(
new Generic<Integer>() {};
나는 추상 일반 수업 시간에 이 문제가 있었다.이 경우 솔루션은 다음과 같이 단순해집니다.
abstract class Foo<T> {
abstract Class<T> getTClass();
//...
}
이후 파생 클래스:
class Bar extends Foo<Whatever> {
@Override
Class<T> getTClass() {
return Whatever.class;
}
}
대부분의 답변과 달리 가능합니다(외부 라이브러리 없이도 가능).
다음은 이 문제에 대한 저의 (어색하지만 효과적인) 솔루션입니다.
import java.lang.reflect.TypeVariable;
public static <T> Class<T> getGenericClass() {
__<T> instance = new __<T>();
TypeVariable<?>[] parameters = instance.getClass().getTypeParameters();
return (Class<T>)parameters[0].getClass();
}
// Generic helper class which (only) provides type information. This avoids
// the usage of a local variable of type T, which would have to be initialized.
private final class __<T> {
private __() { }
}
활자가 지워져서 할 수 없어요.Stack Overflow 질문 Java generics - type erasure - 언제, 어떻게 되는지도 참조하십시오.
다른 사용자가 제안한 클래스보다 더 나은 경로는 클래스로 수행할 수 있는 개체를 전달하는 것입니다. 예를 들어 새 인스턴스를 만드는 것입니다.
interface Factory<T> {
T apply();
}
<T> void List<T> make10(Factory<T> factory) {
List<T> result = new ArrayList<T>();
for (int a = 0; a < 10; a++)
result.add(factory.apply());
return result;
}
class FooFactory<T> implements Factory<Foo<T>> {
public Foo<T> apply() {
return new Foo<T>();
}
}
List<Foo<Integer>> foos = make10(new FooFactory<Integer>());
범용 클래스가 있기 때문에 다음과 같은 변수가 있을 것입니다.
private T t;
(이 변수는 생성자에서 값을 취해야 합니다.)
이 경우, 다음의 방법을 간단하게 작성할 수 있습니다.
Class<T> getClassOfInstance()
{
return (Class<T>) t.getClass();
}
도움이 됐으면 좋겠다!
다음과 같은 가능성이 있습니다.
class Foo<T> {
Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(Foo.class, this.getClass()).get(0);
}
hibernate-generic-dao/blob/master/dao/src/main/java/com/googlecode/genericdao/DA에서 두 가지 기능이 필요합니다.OUtil.java.
나는 그것을 할 수 있는 일반적이고 간단한 방법을 찾았다.클래스 정의의 위치에 따라 일반 유형을 반환하는 메서드를 만들었습니다.다음과 같은 클래스 정의를 가정합니다.
public class MyClass<A, B, C> {
}
다음으로 다음 유형을 유지하는 Atribute를 다음에 나타냅니다.
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
// Getters and setters (not necessary if you are going to use them internally)
}
그런 다음 일반 정의의 인덱스에 따라 유형을 반환하는 일반 메서드를 생성할 수 있습니다.
/**
* Returns a {@link Type} object to identify generic types
* @return type
*/
private Type getGenericClassType(int index) {
// To make it use generics without supplying the class type
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return ((ParameterizedType) type).getActualTypeArguments()[index];
}
마지막으로 컨스트럭터에서는 메서드를 호출하여 각 유형에 대한 인덱스를 전송합니다.전체 코드는 다음과 같습니다.
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
public MyClass() {
this.aType = (Class<A>) getGenericClassType(0);
this.bType = (Class<B>) getGenericClassType(1);
this.cType = (Class<C>) getGenericClassType(2);
}
/**
* Returns a {@link Type} object to identify generic types
* @return type
*/
private Type getGenericClassType(int index) {
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return ((ParameterizedType) type).getActualTypeArguments()[index];
}
}
다른 답변에서 설명한 바와 같이, 이것을 사용하려면ParameterizedType
어프로치, 수업 연장이 필요하지만, 완전히 새로운 수업 연장을 위한 추가 작업인 것 같습니다.
따라서 클래스를 추상화하면 클래스를 확장하여 하위 분류 요건을 충족할 수 있습니다.(롬복의 @Getter 사용).
@Getter
public abstract class ConfigurationDefinition<T> {
private Class<T> type;
...
public ConfigurationDefinition(...) {
this.type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
...
}
}
새 클래스를 정의하지 않고 확장합니다.(마지막에 {}을(를) 적어주세요)...원하는 경우를 제외하고 아무것도 덮어쓰지 마십시오.)
private ConfigurationDefinition<String> myConfigA = new ConfigurationDefinition<String>(...){};
private ConfigurationDefinition<File> myConfigB = new ConfigurationDefinition<File>(...){};
...
Class stringType = myConfigA.getType();
Class fileType = myConfigB.getType();
그것은 꽤 직설적이다.같은 클래스 내에서 필요한 경우:
Class clazz = this.getClass();
ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
try {
Class typeClass = Class.forName( parameterizedType.getActualTypeArguments()[0].getTypeName() );
// You have the instance of type 'T' in typeClass variable
System.out.println( "Class instance name: "+ typeClass.getName() );
} catch (ClassNotFoundException e) {
System.out.println( "ClassNotFound!! Something wrong! "+ e.getMessage() );
}
많은 사람들이 이 기술을 몰라요!사실, 오늘 막 발견했어요!꿈만 같아!이 예를 확인해 주세요.
public static void main(String[] args) {
Date d=new Date(); //Or anything you want!
printMethods(d);
}
public static <T> void printMethods(T t){
Class<T> clazz= (Class<T>) t.getClass(); // There you go!
for ( Method m : clazz.getMethods()){
System.out.println( m.getName() );
}
}
public <T> T yourMethodSignature(Class<T> type) {
// get some object and check the type match the given type
Object result = ...
if (type.isAssignableFrom(result.getClass())) {
return (T)result;
} else {
// handle the error
}
}
제네릭스를 사용하고 있는 클래스/인터페이스를 확장 또는 실장하고 있는 경우는, 기존의 클래스/인터페이스를 전혀 변경하지 않고, 부모 클래스/인터페이스의 범용 타입을 취득할 수 있습니다.
있을 수 있어 3possibilities,.
사례 1언제 당신의 클래스는 제네릭을 사용하여 클래스를 확장하고 있다.
public class TestGenerics {
public static void main(String[] args) {
Type type = TestMySuperGenericType.class.getGenericSuperclass();
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
class GenericClass<T> {
public void print(T obj){};
}
class TestMySuperGenericType extends GenericClass<Integer> {
}
사례 2너의 클래스는 제네릭을 사용하는 인터페이스를 시행하고 있다.
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
class TestMySuperGenericType implements GenericClass<Integer> {
public void print(Integer obj){}
}
너의 인터페이스 제네릭을 사용하는 인터페이스를 확장하고 있사례 3.
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
interface TestMySuperGenericType extends GenericClass<Integer> {
}
사실, 타입의 당신의 수업에 밭이 있으신가 보T.만약 형식 T의 필드 무슨 일이 일어나는지 제네릭 매개 변수 형식 쓰시게요?그래서, 단순히 그 분야에 대한 instanceof을 할 수 있다.
내 경우엔 난 a다
List<.T>조목;in my class, and I check if the class type is "Locality" by
만약(items.get(0)instanceof어서 전통 및 지역성을 음...
가능하면 수업의 총 수를 제한된다 물론, 이것으로만 작동합니다.
이 질문은 오래되었지만, 지금 가장 좋은 것은 구글을 사용하는 것이다.Gson
.
커스텀을 취득하는 예viewModel
.
Class<CustomViewModel<String>> clazz = new GenericClass<CustomViewModel<String>>().getRawType();
CustomViewModel<String> viewModel = viewModelProvider.get(clazz);
제네릭 형식 클래스
class GenericClass<T>(private val rawType: Class<*>) {
constructor():this(`$Gson$Types`.getRawType(object : TypeToken<T>() {}.getType()))
fun getRawType(): Class<T> {
return rawType as Class<T>
}
}
나는 제네릭이 이용한 메서드에 T.class을 통과하길 원했다.
메서드 readFile.csv 파일 fullpath으로 액세스에 의해 지정된 읽는다.내용이 다른 csv 파일이 있을 수 있으므로 모델 파일 클래스를 통과해야 적절한 오브젝트를 얻을 수 있습니다.일반적인 방법으로 csv 파일을 읽고 싶었기 때문에.어떤 이유에서인지 위의 해결책 중 어느 것도 나에게는 효과가 없었다.사용할 필요가 있다Class<? extends T> type
파일의 합니다.CSV opencsv 。
private <T>List<T> readFile(String fileName, Class<? extends T> type) {
List<T> dataList = new ArrayList<T>();
try {
File file = new File(fileName);
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
Reader headerReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
CSVReader csvReader = new CSVReader(headerReader);
// create csv bean reader
CsvToBean<T> csvToBean = new CsvToBeanBuilder(reader)
.withType(type)
.withIgnoreLeadingWhiteSpace(true)
.build();
dataList = csvToBean.parse();
}
catch (Exception ex) {
logger.error("Error: ", ex);
}
return dataList;
}
readFile 메서드는 이렇게 호출됩니다.
List<RigSurfaceCSV> rigSurfaceCSVDataList = readSurfaceFile(surfaceFileName, RigSurfaceCSV.class);
회피책을 사용하고 있습니다.
class MyClass extends Foo<T> {
....
}
MyClass myClassInstance = MyClass.class.newInstance();
언급URL : https://stackoverflow.com/questions/3437897/how-do-i-get-a-class-instance-of-generic-type-t
'programing' 카테고리의 다른 글
스토어에서 Vue 플러그인을 사용하는 방법 (0) | 2022.06.05 |
---|---|
크기 뒤에 괄호를 사용해야 하는 이유와 시기 (0) | 2022.06.05 |
활성 사용자의 User Details를 가져오는 방법 (0) | 2022.06.05 |
Java RegEx 메타 문자(.)와 일반 도트? (0) | 2022.06.05 |
vuex - 권장되지 않는 경우에도 직접 상태를 변경할 수 있습니까? (0) | 2022.06.05 |