मुझे जेनेरिक प्रकार टी का एक वर्ग उदाहरण कैसे मिलेगा?


700

मेरे पास एक जेनरिक क्लास है Foo<T>,। की एक विधि में Foo, मैं श्रेणी के प्रकार को प्राप्त करना चाहता हूं T, लेकिन मैं अभी कॉल नहीं कर सकता T.class

इसका उपयोग करने के लिए पसंदीदा तरीका क्या है T.class?


2
इस प्रश्न में उत्तर देने का प्रयास करें। मुझे लगता है कि इसके समान है। stackoverflow.com/questions/1942644/…
एमिल



1
import com.fasterxml.jackson.core.type.TypeReference; new TypeReference<T>(){}
बोगदान शूलगा

जवाबों:


569

संक्षिप्त उत्तर यह है, कि जावा में रनटाइम प्रकार के सामान्य प्रकार के मापदंडों का पता लगाने का कोई तरीका नहीं है। मेरा सुझाव है कि अधिक जानकारी के लिए जावा ट्यूटोरियल में टाइप इरैचर के बारे में अध्याय पढ़ें ।

इसका एक लोकप्रिय समाधान यह है Classकि जेनेरिक प्रकार के कंस्ट्रक्टर में टाइप पैरामीटर को पास किया जाए , जैसे

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
    }
}

73
यह उत्तर एक वैध समाधान प्रदान करता है, लेकिन यह कहना गलत है कि रनटाइम में सामान्य प्रकार खोजने का कोई तरीका नहीं है। यह पता चला है कि एक प्रकार का कटाव कंबल के क्षरण की तुलना में कहीं अधिक जटिल है। मेरा जवाब आपको दिखाता है कि कक्षाएं सामान्य प्रकार कैसे प्राप्त करें।
बेन थर्ले

3
@BenThurley नीट ट्रिक, लेकिन जहां तक ​​मैं इसे देख सकता हूं यह केवल तभी काम करता है जब इसे इस्तेमाल करने के लिए कोई जेनेरिक सुपरपाइप हो। मेरे उदाहरण में, आप F <T> में T के प्रकार को पुनः प्राप्त नहीं कर सकते हैं।
Zsolt Török

@webjockey नहीं, आपको नहीं करना चाहिए। typeParameterClassकंस्ट्रक्टर में डिफ़ॉल्ट असाइनमेंट के बिना असाइन करना पूरी तरह से ठीक है। इसे दूसरी बार सेट करने की कोई आवश्यकता नहीं है।
Adowrath

यह पहला समाधान है जो मन में आता है, लेकिन कई बार यह आप नहीं हैं जो वस्तुओं का निर्माण / आरंभ करेंगे। इसलिए आप कंस्ट्रक्टर का उपयोग नहीं कर पाएंगे। डेटाबेस से JPA संस्थाओं को पुनः प्राप्त करते समय उदाहरण के लिए।
परमवीर सिंह करवाल

234

मैं क्लासपाथ पर एक अतिरिक्त निर्भरता जोड़े बिना खुद को ऐसा करने का एक रास्ता ढूंढ रहा था। कुछ जांच के बाद मैंने पाया कि यह है जब तक आप एक सामान्य महाप्रकार है के रूप में संभव। यह मेरे लिए ठीक था क्योंकि मैं एक डीएओ परत के साथ एक सामान्य परत के साथ काम कर रहा था । यदि यह आपके परिदृश्य में फिट बैठता है तो यह IMHO का सबसे साफ दृष्टिकोण है।

अधिकांश जेनरिक उन मामलों का उपयोग करते हैं, जिनके बारे में मुझे पता चला है कि किसी प्रकार के जेनेरिक सुपरपाइप उदाहरण के List<T>लिए ArrayList<T>या इसके GenericDAO<T>लिए हैं DAO<T>, आदि।

शुद्ध जावा समाधान

लेख जावा में रनटाइम पर जेनेरिक प्रकार तक पहुंचनेबताता है कि आप शुद्ध जावा का उपयोग करके कैसे कर सकते हैं।

@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 ";
    }

1
कृपया समाधान के अर्थ को स्पष्ट करेंप्रस्तावना तर्क
gstackoverflow

getClass () java.lang.Object की एक विधि है जो रनटाइम के दौरान विशिष्ट ऑब्जेक्ट की कक्षा को लौटा देगी, यह वह ऑब्जेक्ट है जिसके लिए आप प्रकार को हल करना चाहते हैं। AbstractHibernateDao.class केवल सामान्य वर्ग श्रेणी पदानुक्रम के आधार वर्ग या सुपरक्लास का नाम है। आयात विवरण शामिल है, इसलिए आपको डॉक्स को आसानी से खोजने और खुद को जांचने में सक्षम होना चाहिए। यह पृष्ठ docs.spring.io/spring/docs/current/javadoc-api/org/…
बेन

4.3.6 और उच्चतर संस्करण के साथ वसंत समाधान क्या है । यह वसंत 4.3.6 के साथ काम नहीं करता है।
इरलान

1
"प्योर जावा सॉल्यूशन" का लिंक टूटा हुआ है, यह अब ब्लॉग है। xebia.com/acessing-generic-types-at-runtime-in-java
Nick Breen

1
@ AlikElzin-kilaka यह वसंत वर्ग GenericTypeResolver का उपयोग करके कंस्ट्रक्टर में आरंभीकृत होता है।
बेन थर्ले

103

हालांकि एक छोटी खामी है: यदि आप अपनी Fooकक्षा को सार के रूप में परिभाषित करते हैं । इसका मतलब यह होगा कि आपको निम्न वर्ग को तुरंत समझना होगा:

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 );
    }
}

5
यह आसानी से यहाँ पर सबसे अच्छा जवाब है! इसके अलावा, इसके लायक क्या है, यह वह रणनीति है जिसके लिए Google Guice बाइंडिंग क्लास के लिए उपयोग करता हैTypeLiteral
ATG

14
ध्यान दें कि हर बार ऑब्जेक्ट निर्माण की इस पद्धति का उपयोग किया जाता है, एक नया अनाम वर्ग बनाया जाता है। दूसरे शब्दों में, दो वस्तुओं aऔर bइस तरह से बनाए जाने से दोनों एक ही वर्ग का विस्तार करेंगे लेकिन समान उदाहरण वर्ग नहीं होंगे। a.getClass() != b.getClass()
मार्टिन सेरानो

3
एक परिदृश्य है जिसमें यह काम नहीं करता है। यदि Foo को एक इंटरफ़ेस लागू करना चाहिए, जैसे कि Serializable, अनाम वर्ग की तुलना में तब तक Serializable नहीं होगा जब तक कि वर्ग तात्कालिकता नहीं है। मैंने इसे क्रमबद्ध फैक्ट्री क्लास बनाकर इसे हल करने का प्रयास किया जो फू से उत्पन्न अनाम वर्ग बनाता है, लेकिन फिर, किसी कारण से, getActualTypeArguments वास्तविक वर्ग के बजाय सामान्य प्रकार देता है। उदाहरण के लिए: (नया FooFactory <MyType> ())। createFoo ()
Lior Chaga

38

एक मानक दृष्टिकोण / वर्कअराउंड / समाधान एक 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();
    }
 }

1
लेकिन ऐसा लग रहा था कि वास्तविक उपयोग में @ कोई भी काम नहीं कर सकता है?
अल्फ्रेड हुआंग

@AlfredHuang चारों ओर का काम उस वर्ग के लिए एक बीन बनाना होगा जो ऐसा करता है और ऑटोरिंग पर निर्भर नहीं है।
कालेबज

20

कल्पना कीजिए कि आपके पास एक विशिष्ट सुपरक्लास है जो सामान्य है:

public abstract class Foo<? extends T> {}

और फिर आपके पास एक दूसरा वर्ग है जो फू को एक सामान्य बार के साथ बढ़ाता है जो टी का विस्तार करता है:

public class Second extends Foo<Bar> {}

आप Bar.classFoo वर्ग में Type(बर्ट ब्रुनेओघे उत्तर से) का चयन करके और 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;
    }
}

वापस लौटाया जाने वाला मान बार.क्लास है जब अन्य फ़ंक्शन में फू क्लास से या बार क्लास से मंगवाया जाता है।


1
toString().split(" ")[1]यही समस्या थी, "class "
इग्नाइटेकोडर्स

16

यहाँ एक काम कर समाधान है:

@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 <> ");
    }
} 

नोट: केवल सुपरक्लास के रूप में इस्तेमाल किया जा सकता है

  1. टाइप क्लास के साथ बढ़ाया जाना है ( Child extends Generic<Integer>)

या

  1. अनाम कार्यान्वयन के रूप में बनाया जाना है ( new Generic<Integer>() {};)

3
getTypeName कॉल स्ट्रिंग, इसलिए .get द्वारा प्रतिस्थापित किया जा सकता हैआकारप्रचारप्रबंध () [[0] .toString ();
यारोस्लाव कोवबस


9

क्लास द्वारा सुझाए गए क्लास से बेहतर रास्ता एक ऑब्जेक्ट में पास करना है, जो आप क्लास के साथ किया जा सकता है, जैसे, एक नया उदाहरण बनाएं।

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>());

@ रिकी क्लार्कसन: मैं यह नहीं देखता कि कैसे इस कारखाने को पैरामीट्रीड फॉक्स वापस करना चाहिए। क्या आप बता सकते हैं कि आपको इसमें से फू <T> कैसे मिलता है? ऐसा लगता है कि यह केवल अपरिमित Foo देता है। टी 10 मेक नहीं है बस यहाँ फू?
ib84

@ ib84 मैंने कोड तय किया है; मुझे लगता है कि जब मैंने मूल रूप से उत्तर लिखा था तो फू को मानकीकृत किया गया था।
रिकी क्लार्कसन

9

मुझे अमूर्त सामान्य वर्ग में यह समस्या थी। इस विशेष मामले में, समाधान सरल है:

abstract class Foo<T> {
    abstract Class<T> getTClass();
    //...
}

और बाद में व्युत्पन्न वर्ग पर:

class Bar extends Foo<Whatever> {
    @Override
    Class<T> getTClass() {
        return Whatever.class;
    }
}

हाँ, यह है, लेकिन मैं इस वर्ग को बढ़ाते हुए बहुत कम छोड़ना चाहूंगा। Droidpl के जवाब की जाँच करें
परमवीर सिंह करवाल

5

इस समस्या के लिए मेरे पास एक बदसूरत (प्रभावी लेकिन प्रभावी) समाधान है, जिसका उपयोग मैंने हाल ही में किया था:

import java.lang.reflect.TypeVariable;


public static <T> Class<T> getGenericClass()
{
    __<T> ins = new __<T>();
    TypeVariable<?>[] cls = ins.getClass().getTypeParameters(); 

    return (Class<T>)cls[0].getClass();
}

private final class __<T> // generic helper class which does only provide type information
{
    private __()
    {
    }
}

5

यह संभव है:

class Foo<T> {
  Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(Foo.class, this.getClass()).get(0);
}

आपको हाइबरनेट-जेनेरिक-डाओ / ब्लॉब / मास्टर / डाओ / src / main / java / com / googlecode / genericdao / dao / DAOUtil.java से दो कार्यों की आवश्यकता है

अधिक स्पष्टीकरण के लिए, जेनरिक को प्रतिबिंबित करना देखें ।


3

मुझे ऐसा करने का एक सामान्य और सरल तरीका मिला। मेरी कक्षा में मैंने एक ऐसी विधि बनाई जो सामान्य परिभाषा को वर्ग परिभाषा में स्थिति के अनुसार लौटाती है। आइए इस तरह एक वर्ग की परिभाषा मानें:

public class MyClass<A, B, C> {

}

अब प्रकारों को बनाए रखने के लिए कुछ विशेषताएँ बनाते हैं:

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];
    }
}

2

जैसा कि अन्य उत्तरों में बताया गया है, इसका उपयोग करने के लिए ParameterizedType दृष्टिकोण , आपको कक्षा का विस्तार करने की आवश्यकता है, लेकिन यह एक पूरी नई कक्षा बनाने के लिए अतिरिक्त काम की तरह लगता है जो इसे विस्तारित करता है ...

इसलिए, कक्षा को सार बनाते हुए यह आपको इसे विस्तारित करने के लिए मजबूर करता है, इस प्रकार उपवर्ग आवश्यकता को संतुष्ट करता है। (lombok के @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();

2

मुझे लगता है कि, चूंकि आपके पास एक सामान्य वर्ग है, इसलिए आपके पास एक चर होगा:

private T t;

(इस चर को कंस्ट्रक्टर पर मान लेना होगा)

उस स्थिति में आप बस निम्न विधि बना सकते हैं:

Class<T> getClassOfInstance()
{
    return (Class<T>) t.getClass();
}

आशा है ये मदद करेगा!


1
   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
        }
   }

1

यदि आप जेनेरिक का उपयोग कर रहे किसी भी वर्ग / इंटरफ़ेस का विस्तार या कार्यान्वयन कर रहे हैं, तो आप किसी भी मौजूदा क्लास / इंटरफ़ेस को संशोधित किए बिना, जेनेरिक प्रकार के मूल वर्ग / इंटरफ़ेस प्राप्त कर सकते हैं।

तीन संभावनाएं हो सकती हैं,

केस 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> {
}

1

यह बहुत सीधे आगे है। यदि आपको एक ही वर्ग के भीतर से जरूरत है:

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() );
    }

0

वास्तव में, मुझे लगता है कि आपके पास टी के अपने वर्ग में एक क्षेत्र है। यदि टी का कोई क्षेत्र नहीं है, तो एक सामान्य प्रकार होने का क्या मतलब है? तो, आप बस उस क्षेत्र पर एक Instof कर सकते हैं।

मेरे मामले में, मैं ए

सूची <टी> आइटम;
मेरी कक्षा में, और मैं जाँचता हूँ कि क्या वर्ग प्रकार "स्थानीयता" है

अगर (items.get (0) Instof स्थानीयता) ...

बेशक, यह केवल तभी काम करता है जब संभव वर्गों की कुल संख्या सीमित हो।


4
यदि आइटम .isEmpty () सत्य है तो मैं क्या करूं?
अराजक 3 ईक्लिब्रियम

0

यह प्रश्न पुराना है, लेकिन अब सबसे अच्छा उपयोग Google है 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>
    }
}

0

मैं T.class को एक ऐसी विधि से पारित करना चाहता था जो जेनरिक का उपयोग करती है

विधि readFile एक पूर्ण फ़ाइल के साथ फ़ाइलनाम द्वारा निर्दिष्ट .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;
}

इस तरह से रीडफाइल विधि कहा जाता है

List<RigSurfaceCSV> rigSurfaceCSVDataList = readSurfaceFile(surfaceFileName, RigSurfaceCSV.class);

-4

मैं इसके लिए वर्कअराउंड का उपयोग कर रहा हूं:

class MyClass extends Foo<T> {
....
}

MyClass myClassInstance = MyClass.class.newInstance();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.