রানটাইমে জেনেরিক ধরণের ক্লাস পান


508

আমি কীভাবে এটি অর্জন করতে পারি?

public class GenericClass<T>
{
    public Type getMyType()
    {
        //How do I return the type of T?
    }
}

আমি এখন পর্যন্ত যা কিছু চেষ্টা করেছি তা সর্বদা Objectব্যবহৃত নির্দিষ্ট ধরণের পরিবর্তে টাইপ করে।


3
@ সামুয়েলভিডাল এটি। নেট নয়, এটি জাভা।
ফ্রন্টিয়ার

উত্তর:


317

অন্যরা যেমন উল্লেখ করেছে, নির্দিষ্ট পরিস্থিতিতে প্রতিবিম্বের মাধ্যমে এটি কেবল সম্ভব।

আপনার যদি সত্যিই টাইপের দরকার হয় তবে এটি হ'ল স্বাভাবিক (টাইপ-সেফ) ওয়ার্কআরাউন্ড প্যাটার্ন:

public class GenericClass<T> {

     private final Class<T> type;

     public GenericClass(Class<T> type) {
          this.type = type;
     }

     public Class<T> getMyType() {
         return this.type;
     }
}

58
আমি এই উত্তরটি পছন্দ করি তবে তা ইনস্ট্যান্টিয়েট করার জন্য কিছুটা জটিল:
এলিসিও ওক্যাম্পোস

1
আপনি যদি কোনও দাও / কারখানা / পরিচালক ব্যবহার করেন তবে এটি আরও বেশি ভার্বোজ। Foo foo1 = GetDao<Foo>(Foo.class).get(Foo.class, 1)
djmj

2
এটি সত্য, তবে স্টেটলেস রিমোট শিমের মতো সব ক্ষেত্রেই কাজ করছে না যা ধারক / প্রতিবিম্ব দ্বারা তাত্ক্ষণিকভাবে প্রবর্তিত।
djmj

6
আমার আগের মন্তব্যের ফলো-আপ হিসাবে - প্রচুর ব্যথার সাথে প্রতিবিম্বের সাথে খেলে আমি এই উত্তরটি ব্যবহার করে শেষ করেছি।
টোমা জ্যাটো - মনিকা পুনরায় ইনস্টল করুন

18
জেনেরিক স্ট্যাটিক কারখানার পদ্ধতি সরবরাহ করে আপনি অতিরিক্ত অতিরিক্ত রেফারেন্স পেতে পারেন। ভালো কিছু public static <T> GenericClass<T> of(Class<T> type) {...}এবং তারপর যেমন একে ডাকতে: GenericClass<String> var = GenericClass.of(String.class)। কিছুটা ভাল।
জোয়েরি হেন্ড্রিকেক্স

262

আমি এরকম কিছু দেখেছি

private Class<T> persistentClass;

public Constructor() {
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
 }

মধ্যে হাইবারনেট GenericDataAccessObjects উদাহরণ


84
এই কৌশলটি কাজ করে যেখানে প্রকারের প্যারামিটারটি তাত্ক্ষণিক সুপারক্লাসে সংজ্ঞায়িত করা হয়েছে, তবে টাইপ প্যারামিটারটি ধরণের শ্রেণিবিন্যাসের অন্য কোথাও সংজ্ঞায়িত করা থাকলে এটি ব্যর্থ হয়। আরও জটিল ক্ষেত্রে পরিচালনার জন্য টাইপটুলসের মতো কিছু ব্যবহার করা যেতে পারে। দস্তাবেজগুলিতে আরও পরিশীলিত জেনেরিক ডিএওর একটি উদাহরণ রয়েছে।
জোনাথন

25
এটি কেবলমাত্র ব্যবহৃত প্রকৃত টাইপ পরামিতি ফেরৎ যখন একটি ক্লাস কার্যকরী / কিছু জেনেরিক ঘোষণা আছে প্রসারিত, এটা যখন একটি ব্যবহৃত প্রকৃত টাইপ পরামিতি ফেরত দেয় না উদাহরণস্বরূপ instantiated করা হয়। অন্য কথায়, এটা করতে পারেন বলতে যে class A implements Comparable<String>, প্রকৃত টাইপ প্যারামিটার String, কিন্তু এটা করতে পারে না বলে যে এ Set<String> a = new TreeSet<String>(), প্রকৃত টাইপ প্যারামিটার String। প্রকৃতপক্ষে, টাইপ প্যারামিটার তথ্য সংকলনের পরে "মুছে ফেলা হয়", যেমন অন্যান্য উত্তরে ব্যাখ্যা করা হয়েছে।
সিউ চিং পং-আসুকা কেনজি-

32
আমি java.lang.Class cannot be cast to java.lang.reflect.ParameterizedTypeএই উত্তর পেয়ে যাচ্ছি ।
টোমা জ্যাটো - মনিকা পুনরায় ইনস্টল করুন

4
এই পন্থাটি Class-Mateজ্যাকসন লোকদের কাছ থেকে ব্যবহার করেও অর্জন করা যেতে পারে । আমি এখানে একটি গিস্ট
ইউনস্পেস

5
@ টোম্যাজাটো সহজভাবে কল করা উপরের কোডটি আমার জন্য একই ব্যতিক্রম ঘটেছে। আমি জানি যে এটি কিছুটা দেরি হয়ে গেছে, তবে যাইহোক, আমার ক্ষেত্রে, আমাকে (Class<T>) ((ParameterizedType)getClass().getSuperclass().getGenericSuperclass()).getActualTypeArguments()প্রকৃত ধরণের যুক্তি পেতে কল করতে হয়েছিল।
অ্যান্ড্রু ম্যাককোইস্ট

98

জেনারিকগুলি রান-টাইমে পুনরায় সংশোধিত হয় না । এর অর্থ রান-টাইমে তথ্য উপস্থিত নেই।

পশ্চাদগম্য সামঞ্জস্যতা জাগ্রত করার সময় জাভাতে জেনেরিক যোগ করা একটি ট্যুর-ডি-ফোর্স ছিল (আপনি এটি সম্পর্কে চূড়ান্ত কাগজটি দেখতে পারেন: ভবিষ্যতের জন্য নিরাপদ করা: জাভা প্রোগ্রামিং ভাষায় উদারতা যোগ করা )।

বিষয়টিতে একটি সমৃদ্ধ সাহিত্য রয়েছে, এবং কিছু লোক বর্তমান অবস্থা সম্পর্কে অসন্তুষ্ট , কেউ কেউ বলে যে এটি আসলে প্রলুব্ধ এবং এর সত্যিকার প্রয়োজন নেই। আপনি উভয় লিঙ্কটি পড়তে পারেন, আমি সেগুলি বেশ আকর্ষণীয় পেয়েছি।


179
অবশ্যই আমরা অসন্তুষ্ট, .NET এর চেয়ে আরও ভাল জেনেরিক হ্যান্ডলিং মেকানিজম রয়েছে
প্যাসেরিয়ার

6
@ পেসারিয়র: তবে একা রিফাইড জেনারিকস জাভা কে .NET এর স্তরে নিয়ে আসবে না। মানগুলির ধরণগুলির জন্য একটি বিশেষায়িত কোড কমপক্ষে কেন জেনিক্সের ক্ষেত্রে .NET ভাল for
জোচিম সৌর

@ জোছিমসৌয়ার, হ্যাঁ মান ধরণের আমি সবসময় জাভা তাদের চাই। বিটিডব্লিউ বিশেষায়িত কোড বলতে কী বোঝ?
পেসারিয়ার

3
@ spaaarky21 না, সংকলনের সময় জেনেরিক ধরণের পরামিতিগুলি সরানো হয় (তথাকথিত "ক্ষয়", আপনি এটি গুগল করতে পারেন)। ফ্রাভাবাবের উত্তরের কৌশলটি কেবল তখনই কাজ করে যদি সুপারক্লাসের টাইপ প্যারামগুলি স্থিরভাবে জানা থাকে (জনাথনের প্রথম কমেন্টটি দেখুন)
ইভার্নালি

1
জাভা টাইপ ক্ষয় একটি designতিহাসিক নকশা ত্রুটি; এটি প্রয়োগের জন্য যতটা কোড লেখা হয়েছিল তার চেয়ে বেশি পেতে কোড লেখা হয়েছিল to
অভিজিৎ সরকার

68

পেয়ারা ব্যবহার করুন।

import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;

public abstract class GenericClass<T> {
  private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) { };
  private final Type type = typeToken.getType(); // or getRawType() to return Class<? super T>

  public Type getType() {
    return type;
  }

  public static void main(String[] args) {
    GenericClass<String> example = new GenericClass<String>() { };
    System.out.println(example.getType()); // => class java.lang.String
  }
}

কিছুক্ষণ আগে, আমি এখানে অ্যাবস্ট্রাক্ট ক্লাস এবং সাবক্ল্যাসিসহ কয়েকটি পূর্ণদৃষ্টির উদাহরণ পোস্ট করেছি

Note: এই প্রয়োজন যে আপনি একটি instantiate উপশ্রেণী এর GenericClassতাই এটি টাইপ প্যারামিটার সঠিকভাবে আবদ্ধ করতে পারেন। অন্যথায় এটি ঠিক হিসাবে টাইপ ফিরে আসবে T


3
লক্ষ্য করুন যে আমি একটি খালি বেনামে সাবক্লাস তৈরি করেছি (শেষে দুটি কোঁকড়ানো ধনুর্বন্ধনী দেখুন)। এটি জাভার রানটাইম টাইপ মুছে ফেলার লড়াইয়ের প্রতিচ্ছবি ব্যবহার করে। আপনি এখানে আরও শিখতে পারেন: কোড. google.com/p/guava-libraries/wiki/ReflectionExplained
কোডি এ। রায়

3
@ কোডাআ.আর আপনার কোডটি নিক্ষেপ করে java.lang.IllegalArgumentException: class com.google.common.reflect.TypeToken isn't parameterized। তাই আমি লাইন পরিবর্তিত new TypeToken(getClass()) { }করতে new TypeToken<T>(getClass()) { }। এখন কোডটি ঠিকঠাক চলছে, তবে প্রকারটি এখনও 'টি'। এটি দেখুন: gist.github.com/m-manu/9cda9d8f9d53bead2035
মনু মঞ্জুনাথ

3
@ ডোমিনিক দয়া করে আপডেট হওয়া উদাহরণটি দেখুন যা আপনি নিজের পরীক্ষার জন্য অনুলিপি এবং কপি করতে পারেন। আমি একটি নোটও স্পষ্ট করে জানিয়েছি যে আপনাকে অবশ্যই একটি সাবক্লাস ইনস্ট্যান্ট করতে হবে (যেমন দেখানো হয়েছে)। সাধারণ শিষ্টাচার হিসাবে পরামর্শ হিসাবে, আপনি "ইচ্ছাকৃত চিন্তাভাবনা" এর পোস্টারকে অভিযুক্ত করার আগে দয়া করে কোনও লিঙ্কযুক্ত নিবন্ধ এবং সম্পর্কিত জাভাদোকগুলি পড়ুন। আমি একাধিকবার অনুরূপ প্রোডাকশন কোড ব্যবহার করেছি। আমি যে পেয়ারা সাহায্যকারীদের প্রদর্শন করছি তা এই সঠিক ব্যবহারের জন্য এবং তাদের জাভাদোকরা এই প্রশ্নের প্রায় সঠিক উত্তর দেখায়। docs.guava-libraries.googlecode.com/git/javadoc/com/google/…
কোডি এ। রে

1
এই উত্তরটি জাভা 8-এর সাথে দুর্দান্ত কাজ করে - আমার কাছে বিভিন্ন ধরণের নির্গত করার জন্য একটি ইন্টারফেস এবং কারখানার শ্রেণি রয়েছে এবং ব্যবহারকারীরা সহজেই প্রকারটি নির্ধারণ করতে সক্ষম হতে চান। আমার ইন্টারফেসে আমি ডিফল্ট পদ্ধতিটি যুক্ত করেছি: default Type getParameterType() { final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {}; final Type type = typeToken.getType(); return type; }
রিচার্ড স্যান্ড

2
@ কোডা.আরে যেহেতু এটি কেবলমাত্র সাবক্লাসগুলির সাথে কাজ করে GenericClass, আপনার সেই শ্রেণিটি করা উচিত abstractযাতে ভুল ব্যবহার সংকলন না হয়।
মার্টিন

37

অবশ্যই, আপনি পারেন।

জাভা পিছনের সামঞ্জস্যতার কারণে, রান সময়ে তথ্য ব্যবহার করে না । তবে তথ্যটি আসলে উপস্থিত মেটাডেটা হিসাবে এবং প্রতিবিম্বের মাধ্যমে অ্যাক্সেস করা যায় (তবে এটি এখনও টাইপ-চেকিংয়ের জন্য ব্যবহৃত হয় না)।

অফিসিয়াল এপিআই থেকে:

http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29

তবে আপনার দৃশ্যের জন্য আমি প্রতিবিম্ব ব্যবহার করব না। আমি ব্যক্তিগতভাবে ফ্রেমওয়ার্ক কোডের জন্য এটি ব্যবহার করতে বেশি আগ্রহী। আপনার ক্ষেত্রে আমি কেবল কনস্ট্রাক্টর প্যারাম হিসাবে টাইপটি যুক্ত করব।


10
getActualTypeArguments কেবল তাত্ক্ষণিক শ্রেণীর জন্য প্রকারের আর্গুমেন্টগুলি দেয়। আপনার যদি জটিল ধরণের শ্রেণিবিন্যাস থাকে যেখানে টি শ্রেণিবিন্যাসের যে কোনও জায়গায় প্যারামিটারাইজড হতে পারে তবে এটি কী তা নির্ধারণ করার জন্য আপনাকে কিছুটা কাজ করতে হবে। এটি টাইপটুলস যা কমবেশি তা করে।
জোনাথন

36

জাভা জেনেরিকগুলি বেশিরভাগ সময়ই সংকলন করে থাকে, এর অর্থ এই যে টাইপ তথ্য রানটাইমে হারিয়ে যায়।

class GenericCls<T>
{
    T t;
}

মত কিছু সংকলিত হবে

class GenericCls
{
   Object o;
}

রানটাইমে টাইপের তথ্য পেতে আপনাকে এটিকে কর্টারের যুক্তি হিসাবে যুক্ত করতে হবে।

class GenericCls<T>
{
     private Class<T> type;
     public GenericCls(Class<T> cls)
     {
        type= cls;
     }
     Class<T> getType(){return type;}
}

উদাহরণ:

GenericCls<?> instance = new GenericCls<String>(String.class);
assert instance.getType() == String.class;

9
private final Class<T> type;
নেক্সা

এটি থেকে কীভাবে আমি একটি অ্যারে টাইপ তৈরি করতে পারি:Type t = //String[]
পাভেল সিওচ

নিবন্ধন করুন আশা করি এটি সহায়তা করে (জাভাদোকটি এখানে ডক্স.ওরকল
জাভাজ /

@ পাওয়েলসিওচ তৈরি অ্যারে থেকে প্রকারটি পেতে একটি .getClass () মিস করেছেন। অ্যারে ক্লাস করার সরাসরি উপায় বলে মনে হয় না। বেশিরভাগ জাভা সংগ্রহগুলি কেবল তার পরিবর্তে অবজেক্ট [] ব্যবহার করে।
জোসেফেক্স

23
public abstract class AbstractDao<T>
{
    private final Class<T> persistentClass;

    public AbstractDao()
    {
        this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
                .getActualTypeArguments()[0];
    }
}

3
আমি এই উত্তরটিকে সমর্থন করছি কারণ এটি এমন একটি সমাধান যা প্রশ্ন জিজ্ঞাসার জন্য কাজ করে। যাইহোক, যারা একাধিক জেনেরিক ক্লাসের সাথে আমার মতো শ্রেণির শ্রেণিবিন্যাসে wardর্ধ্বমুখী নেভিগেট করতে চান তাদের পক্ষে এটি কার্যকর হবে না। কারণ আপনি আসল ক্লাসের পরিবর্তে java.lang.object পাবেন।
কেএমসি

3
দয়া করে মনে রাখবেন যে জেনেরিক ধরণের
ধারন করা

জাভা 11
JRA_TLL

@ JRA_TLL আপনি সম্ভবত কিছু ভুল করেছেন @ আমি এটি কেবল জাভা 12 এর সাথে ব্যবহার করেছি এবং একটি কবজির মতো কাজ করি।
গুগি

আপনি যদি ক্রমবিন্যাসে নেভিগেট করতে চান তবে জেনেরিকস্পারক্লাসকে ক্লাস <*> এ কাস্ট করতে পারেন এবং জেনেরিকসপারক্লাস পেতে পারেন। পছন্দসই একটি লুপ।
fupduck

21

আমি অনুসরণ পদ্ধতির ব্যবহার করেছি:

public class A<T> {

    protected Class<T> clazz;

    public A() {
        this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public Class<T> getClazz() {
        return clazz;
    }
}

public class B extends A<C> {
   /* ... */
    public void anything() {
       // here I may use getClazz();
    }
}

9
আমি "থ্রেডে ব্যতিক্রম" মূল "জাভা.এলং.ক্লাসকাস্টএক্সেপশন: জাভা.লং.ক্লাসটি এই নমুনা কোডটির সাথে java.lang.reflect.ParameterizedType" কাস্ট করতে পারি না
yuyang

16

আমি মনে করি না আপনি যা করতে পারেন, জাভা সংকলন করার সময় টাইপ ইরেজর ব্যবহার করেন যাতে আপনার কোডটি প্রি-জেনেরিক তৈরি হওয়া অ্যাপ্লিকেশন এবং লাইব্রেরির সাথে সামঞ্জস্যপূর্ণ।

ওরাকল ডক্স থেকে:

Erasure টাইপ করুন

সংকলন সময়ে শক্ততর প্রকারের চেক সরবরাহ এবং জেনেরিক প্রোগ্রামিং সমর্থন করার জন্য জেনারিকসটি জাভা ভাষার সাথে প্রবর্তিত হয়েছিল। জেনেরিকগুলি প্রয়োগ করতে, জাভা সংকলক প্রকারটি মুছে ফেলার জন্য প্রযোজ্য:

সমস্ত ধরণের পরামিতি জেনেরিক প্রকারগুলিকে তাদের সীমানা বা অবজেক্টের সাথে প্রতিস্থাপন করুন যদি প্রকারের পরামিতিগুলি আনবাউন্ড না থাকে। উত্পাদিত বাইটকোডে, কেবলমাত্র সাধারণ ক্লাস, ইন্টারফেস এবং পদ্ধতি রয়েছে। প্রকারের সুরক্ষা সংরক্ষণ করতে প্রয়োজনে টাইপ ক্যাসেটগুলি sertোকান। বর্ধিত জেনেরিক ধরণের পলিমারফিজম সংরক্ষণের জন্য সেতু পদ্ধতি তৈরি করুন। প্রকার মুছে ফেলা নিশ্চিত করে যে পরামিতিযুক্ত ধরণের জন্য কোনও নতুন ক্লাস তৈরি করা হয়নি; ফলস্বরূপ, জেনেরিকগুলি কোনও রানটাইম ওভারহেড ব্যয় করে না।

http://docs.oracle.com/javase/tutorial/java/generics/erasure.html


হ্যাঁ, এটা অসম্ভব। জাভাটির কাজ করার জন্য পুনরায় সংশোধিত জেনেরিকের প্রয়োজন হবে।
হেনিং

15

আয়ান রবার্টসনের এই নিবন্ধে বর্ণিত প্রযুক্তিটি আমার পক্ষে কাজ করে।

সংক্ষিপ্ত দ্রুত এবং নোংরা উদাহরণে:

 public abstract class AbstractDAO<T extends EntityInterface, U extends QueryCriteria, V>
 {
    /**
     * Method returns class implementing EntityInterface which was used in class
     * extending AbstractDAO
     *
     * @return Class<T extends EntityInterface>
     */
    public Class<T> returnedClass()
    {
        return (Class<T>) getTypeArguments(AbstractDAO.class, getClass()).get(0);
    }

    /**
     * Get the underlying class for a type, or null if the type is a variable
     * type.
     *
     * @param type the type
     * @return the underlying class
     */
    public static Class<?> getClass(Type type)
    {
        if (type instanceof Class) {
            return (Class) type;
        } else if (type instanceof ParameterizedType) {
            return getClass(((ParameterizedType) type).getRawType());
        } else if (type instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType) type).getGenericComponentType();
            Class<?> componentClass = getClass(componentType);
            if (componentClass != null) {
                return Array.newInstance(componentClass, 0).getClass();
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * Get the actual type arguments a child class has used to extend a generic
     * base class.
     *
     * @param baseClass the base class
     * @param childClass the child class
     * @return a list of the raw classes for the actual type arguments.
     */
    public static <T> List<Class<?>> getTypeArguments(
            Class<T> baseClass, Class<? extends T> childClass)
    {
        Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
        Type type = childClass;
        // start walking up the inheritance hierarchy until we hit baseClass
        while (!getClass(type).equals(baseClass)) {
            if (type instanceof Class) {
                // there is no useful information for us in raw types, so just keep going.
                type = ((Class) type).getGenericSuperclass();
            } else {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Class<?> rawType = (Class) parameterizedType.getRawType();

                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
                for (int i = 0; i < actualTypeArguments.length; i++) {
                    resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
                }

                if (!rawType.equals(baseClass)) {
                    type = rawType.getGenericSuperclass();
                }
            }
        }

        // finally, for each actual type argument provided to baseClass, determine (if possible)
        // the raw class for that type argument.
        Type[] actualTypeArguments;
        if (type instanceof Class) {
            actualTypeArguments = ((Class) type).getTypeParameters();
        } else {
            actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
        }
        List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
        // resolve types by chasing down type variables.
        for (Type baseType : actualTypeArguments) {
            while (resolvedTypes.containsKey(baseType)) {
                baseType = resolvedTypes.get(baseType);
            }
            typeArgumentsAsClasses.add(getClass(baseType));
        }
        return typeArgumentsAsClasses;
    }
  }

3
এই কোডের কোন নির্দিষ্ট লাইনে প্রকৃত, রান-টাইম ধরণের পরামিতিগুলি পড়া হচ্ছে?
ইভান মাতাবুলজ

এখানে? Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
ওন্দ্রেজ বোজেক

9

আমি মনে করি আরও একটি মার্জিত সমাধান আছে।

আপনি যা করতে চান তা হ'ল (নিরাপদে) জেনেরিক টাইপ প্যারামিটারের ধরণটি ক্লাস থেকে শুরু করে সুপার ক্লাসে।

আপনি যদি ক্লাসে ক্লাসের ধরণটিকে "মেটাডেটা" হিসাবে ভাবার অনুমতি দেন, যা রানটাইমে মেটাডেটা এনকোডিংয়ের জন্য জাভা পদ্ধতিটি প্রস্তাব করে: টীকাগুলি।

প্রথমে এই লাইনগুলি বরাবর একটি কাস্টম টীকা সংজ্ঞায়িত করুন:

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityAnnotation {
    Class entityClass();
}

তারপরে আপনাকে আপনার সাবক্লাসে টীকা যুক্ত করতে হবে।

@EntityAnnotation(entityClass =  PassedGenericType.class)
public class Subclass<PassedGenericType> {...}

তারপরে আপনি এই বেসটি আপনার বেস ক্লাসে ক্লাসের ধরণ পেতে ব্যবহার করতে পারেন:

import org.springframework.core.annotation.AnnotationUtils;
.
.
.

private Class getGenericParameterType() {
    final Class aClass = this.getClass();
    EntityAnnotation ne = 
         AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);

    return ne.entityClass();
}

এই পদ্ধতির কিছু সীমাবদ্ধতা হ'ল:

  1. আপনি জেনেরিক প্রকারটি নির্দিষ্ট করুন (PassedGenericType ) টিডব্লিউও স্থানে নন-ডিআরআইয়ের পরিবর্তে ।
  2. এটি কেবলমাত্র যদি আপনি কংক্রিটের সাবক্লাসগুলি পরিবর্তন করতে পারেন তবেই সম্ভব।

হ্যাঁ, এটি নন-ডিআরওয়াই, তবে এটি উপরে বর্ণিত এক্সটেনশন পদ্ধতির চেয়ে পরিষ্কার। আমি এটা পছন্দ। ধন্যবাদ
agodinhost

8

এটি আমার সমাধান:

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class GenericClass<T extends String> {

  public static void main(String[] args) {
     for (TypeVariable typeParam : GenericClass.class.getTypeParameters()) {
      System.out.println(typeParam.getName());
      for (Type bound : typeParam.getBounds()) {
         System.out.println(bound);
      }
    }
  }
}

10
এটি এই প্রশ্নের উত্তর নয়।
অ্যাডাম আর্ল্ড

1
আমার কোড প্রশ্নের সঠিক সমাধান নয়। এটি ক্লাসের জেনেরিক ধরণের প্যারামিটারগুলি দেয়, তবে টি এর প্রকৃত প্রকার নয় not তবে এটি অন্যদের জন্য সহায়ক হতে পারে যারা এই প্রশ্নটি নিয়ে পদস্খলন করে এবং আমার সমাধান খুঁজছেন।
ম্যাথিয়াস এম

1
getClass ()। getGenericSuperclass () একই প্রভাব অর্জন করবে।
গোর্কি

5

এখানে সমাধান কাজ করছে !!!

@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>)
বা

2 দিয়ে প্রসারিত করতে হবে 2. বেনামে বাস্তবায়ন হিসাবে তৈরি করতে হবে ( new Generic<Integer>() {};)


4

আপনি পারবেন না। আপনি ক্লাসে টি টাইপের টি সদস্যের একটি ভেরিয়েবল যুক্ত করলে (আপনি এটি আরম্ভ করতে হবে না), আপনি টাইপটি পুনরুদ্ধার করতে এটি ব্যবহার করতে পারেন।


2
ওফ, ঠিক আছে। আপনি কি একটি কন্সট্রাকটর থেকে এটা ইনিশিয়ালাইজ করতে হবে।
অ্যান্ড্রুমু

4

এখানে একটি উপায় যা আমাকে একবার বা দুবার ব্যবহার করতে হয়েছিল:

public abstract class GenericClass<T>{
    public abstract Class<T> getMyType();
}

সাথে

public class SpecificClass extends GenericClass<String>{

    @Override
    public Class<String> getMyType(){
        return String.class;
    }
}

4
এটি প্রযুক্তিগতভাবে কাজ করে, তবে এটি সাধারণ ক্ষেত্রে সমাধান করে না, এবং আমি মনে করি যে এটিই মূল পোস্টারটি পরে।
ggb667

এটি যেমন রয়েছে তেমনই ভোট দেওয়ার যোগ্য নয় - মূল পোস্টারটি সুস্পষ্ট হয়নি hasn't এই উত্তরটি অফার একটি নকশা প্যাটার্ন যে করে কাজ এবং বাস্তবায়ন সহজ, প্রদত্ত এটা জেনেরিক বর্গ বিমূর্ত করতে উপযুক্ত।
ভার্চুয়ালমিচেল

4

এই ক্যাবটির জন্য একটি সহজ সমাধান নীচের মত হতে হবে

public class GenericDemo<T>{
    private T type;

    GenericDemo(T t)
    {
        this.type = t;
    }

    public String getType()
    {
        return this.type.getClass().getName();
    }

    public static void main(String[] args)
    {
        GenericDemo<Integer> obj = new  GenericDemo<Integer>(5);
        System.out.println("Type: "+ obj.getType());
    }
}

3

এখানে কয়েকটি উত্তর সম্পূর্ণ করতে, আমাকে পুনরাবৃত্তির সাহায্যে হাইয়ারার্কি কতটা উঁচু হোক না কেন প্যারামেট্রিজেড টাইপটি মাইজেনারিক ক্লাসের পেতে হয়েছিল:

private Class<T> getGenericTypeClass() {
        return (Class<T>) (getParametrizedType(getClass())).getActualTypeArguments()[0];
}

private static ParameterizedType getParametrizedType(Class clazz){
    if(clazz.getSuperclass().equals(MyGenericClass.class)){ // check that we are at the top of the hierarchy
        return (ParameterizedType) clazz.getGenericSuperclass();
    } else {
        return getParametrizedType(clazz.getSuperclass());
    }
}

1

আমার কৌশলটি এখানে:

public class Main {

    public static void main(String[] args) throws Exception {

        System.out.println(Main.<String> getClazz());

    }

    static <T> Class getClazz(T... param) {

        return param.getClass().getComponentType();
    }

}

1
দ্রষ্টব্য: যখন টাইপ ভেরিয়েবল হয় এটি কাজ করে নাT । কেস যে Tএকটি টাইপ পরিবর্তনশীল, ভারার্গস এর ইরেজিওর একটি অ্যারের সৃষ্টি T। যেমনঃ http://ideone.com/DIPNwd দেখুন ।
রেডিওডেফ

1
এটি "অবজেক্ট" ফিরিয়ে দেয়
ইয়াহিয়া

হতে পারে আপনি অন্য কোনও প্রশ্নের উত্তর দেওয়ার চেষ্টা করছেন 🤔
খান

1

জেনেরিক প্রকারটি ব্যবহার করে আপনি যদি কোনও ভেরিয়েবল সঞ্চয় করেন তবে আপনি সহজেই এই সমস্যাটি সমাধান করতে পারেন একটি getClassType পদ্ধতি যুক্ত করে:

public class Constant<T> {
  private T value;

  @SuppressWarnings("unchecked")
  public Class<T> getClassType () {
    return ((Class<T>) value.getClass());
  }
}

আমি প্রদত্ত শ্রেণীর অবজেক্টটি পরবর্তীতে এটি কোনও প্রদত্ত শ্রেণীর উদাহরণ কিনা তা পরীক্ষা করতে ব্যবহার করি:

Constant<?> constant = ...;
if (constant.getClassType().equals(Integer.class)) {
    Constant<Integer> integerConstant = (Constant<Integer>)constant;
    Integer value = integerConstant.getValue();
    // ...
}

2
দুর্ভাগ্যক্রমে এটি সমস্যাযুক্ত। সবার আগে, যদি valueহয় null? সর্বোপরি, যদি valueএকটি সাবক্লাস হয় T? এটি ফিরে Constant<Number> c = new Constant<Number>(new Integer(0)); Class<Number> n = c.getClassType();আসা Integer.classউচিত ফিরে Number.class। ফিরে আসা আরও সঠিক হবে Class<? extends T>Integer.class একটি Class<? extends Number> কিন্তু একটি না Class<Number>
রেডিওডেফ

1

এখানে আমার সমাধান

public class GenericClass<T>
{
    private Class<T> realType;

    public GenericClass() {
        findTypeArguments(getClass());
    }

    private void findTypeArguments(Type t) {
        if (t instanceof ParameterizedType) {
            Type[] typeArgs = ((ParameterizedType) t).getActualTypeArguments();
            realType = (Class<T>) typeArgs[0];
        } else {
            Class c = (Class) t;
            findTypeArguments(c.getGenericSuperclass());
        }
    }

    public Type getMyType()
    {
        // How do I return the type of T? (your question)
        return realType;
    }
}

আপনার শ্রেণি শ্রেণিবিন্যাসের কত স্তর রয়েছে তা বিবেচনা না করেই, এই সমাধানটি এখনও কাজ করে, উদাহরণস্বরূপ:

public class FirstLevelChild<T> extends GenericClass<T> {

}

public class SecondLevelChild extends FirstLevelChild<String> {

}

এই ক্ষেত্রে, getMyType () = java.lang.String


এই টি ধরণ এটা java.lang.String না ব্যতীত কোড ক্লাস <টি> এ প্রকার গোপন করতে ব্যর্থ হচ্ছে টি ফিরে আসছে আসছে না
Mohy Eldeen

আমি তৈরি একটি অনলাইন নমুনা এখানে। সংকলন এবং সম্পাদন ক্লিক করুন, তারপরে আপনি ফলাফল পেতে পারেন। tutorialspPoint.com/…
লিন ইউ চেং

আমার জন্য কাজ করে - যখন ওয়াইল্ডফ্লাই ওয়েল্ড সিডিআই একটি বিকল্প পদ্ধতি ভেঙে দেয়।
আন্দ্রে

আমি পেয়েছিException in thread "main" java.lang.NullPointerException at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.<init>(Main.java:43) at Main.main(Main.java:61)
yuyang

0
public static final Class<?> getGenericArgument(final Class<?> clazz)
{
    return (Class<?>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
}

0

এখানে আমার সমাধান। উদাহরণগুলির এটি ব্যাখ্যা করা উচিত। একমাত্র প্রয়োজনীয়তা একটি সাবক্লাস অবশ্যই জেনেরিক প্রকার সেট করতে হবে, কোনও বস্তু নয়।

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;

public class TypeUtils {

    /*** EXAMPLES ***/

    public static class Class1<A, B, C> {

        public A someA;
        public B someB;
        public C someC;

        public Class<?> getAType() {
            return getTypeParameterType(this.getClass(), Class1.class, 0);
        }

        public Class<?> getCType() {
            return getTypeParameterType(this.getClass(), Class1.class, 2);
        }
    }

    public static class Class2<D, A, B, E, C> extends Class1<A, B, C> {

        public B someB;
        public D someD;
        public E someE;
    }

    public static class Class3<E, C> extends Class2<String, Integer, Double, E, C> {

        public E someE;
    }

    public static class Class4 extends Class3<Boolean, Long> {

    }

    public static void test() throws NoSuchFieldException {

        Class4 class4 = new Class4();
        Class<?> typeA = class4.getAType(); // typeA = Integer
        Class<?> typeC = class4.getCType(); // typeC = Long

        Field fieldSomeA = class4.getClass().getField("someA");
        Class<?> typeSomeA = TypeUtils.getFieldType(class4.getClass(), fieldSomeA); // typeSomeA = Integer

        Field fieldSomeE = class4.getClass().getField("someE");
        Class<?> typeSomeE = TypeUtils.getFieldType(class4.getClass(), fieldSomeE); // typeSomeE = Boolean


    }

    /*** UTILS ***/

    public static Class<?> getTypeVariableType(Class<?> subClass, TypeVariable<?> typeVariable) {
        Map<TypeVariable<?>, Type> subMap = new HashMap<>();
        Class<?> superClass;
        while ((superClass = subClass.getSuperclass()) != null) {

            Map<TypeVariable<?>, Type> superMap = new HashMap<>();
            Type superGeneric = subClass.getGenericSuperclass();
            if (superGeneric instanceof ParameterizedType) {

                TypeVariable<?>[] typeParams = superClass.getTypeParameters();
                Type[] actualTypeArgs = ((ParameterizedType) superGeneric).getActualTypeArguments();

                for (int i = 0; i < typeParams.length; i++) {
                    Type actualType = actualTypeArgs[i];
                    if (actualType instanceof TypeVariable) {
                        actualType = subMap.get(actualType);
                    }
                    if (typeVariable == typeParams[i]) return (Class<?>) actualType;
                    superMap.put(typeParams[i], actualType);
                }
            }
            subClass = superClass;
            subMap = superMap;
        }
        return null;
    }

    public static Class<?> getTypeParameterType(Class<?> subClass, Class<?> superClass, int typeParameterIndex) {
        return TypeUtils.getTypeVariableType(subClass, superClass.getTypeParameters()[typeParameterIndex]);
    }

    public static Class<?> getFieldType(Class<?> clazz, AccessibleObject element) {
        Class<?> type = null;
        Type genericType = null;

        if (element instanceof Field) {
            type = ((Field) element).getType();
            genericType = ((Field) element).getGenericType();
        } else if (element instanceof Method) {
            type = ((Method) element).getReturnType();
            genericType = ((Method) element).getGenericReturnType();
        }

        if (genericType instanceof TypeVariable) {
            Class<?> typeVariableType = TypeUtils.getTypeVariableType(clazz, (TypeVariable) genericType);
            if (typeVariableType != null) {
                type = typeVariableType;
            }
        }

        return type;
    }

}

-1

আমি উপরের @ মুসিওর মতোই করেছি কিন্তু কোটলিনে এটি এইভাবে করা যেতে পারে:

class A<T : SomeClass>() {

    var someClassType : T

    init(){
    this.someClassType = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
    }

}

-4

এটি কারও কাজে লাগতে পারে। আপনি java.lang.ref.WeakReferences ব্যবহার করতে পারেন; এই পথে:

class SomeClass<N>{
  WeakReference<N> variableToGetTypeFrom;

  N getType(){
    return variableToGetTypeFrom.get();
  }
}

এই ক্লাসটি কীভাবে ব্যবহার করার কথা? কেন WeakReference? আপনার উত্তর সহ কিছু ব্যাখ্যা সরবরাহ করুন, কেবল কিছু কোড নয়।
অভিজিৎ সরকার ২

সুতরাং আপনার যদি একটি থাকে তবে আপনি SomeClass<MyClass> ইনস্ট্যান্টিয়েট করতে পারেন SomeClassএবং getTypeসেই দৃষ্টিতে ফোন করতে পারেন এবং রানটাইমটি হতে পারে MyClass
দ্য লিচ

অবশ্যই, তবে কেন WeakReference? আপনি যা বলেছিলেন তা অন্যান্য উত্তরগুলির চেয়ে আলাদা নয়।
অভিজিৎ সরকার

প্রথমে আমার পদ্ধতিটি সংক্ষিপ্ত (কম কোড), দ্বিতীয়টি দুর্বল উল্লেখগুলি তাদের রেফারেন্টগুলিকে চূড়ান্ত করতে সক্ষম হতে বাধা দেয় না এবং যতদূর আমি জানি এটি প্রতিবিম্ব ব্যবহার করে না, সুতরাং এটি দ্রুত
দ্যল্যাচ

এই কিছু ধরণ এই যে টাইপ, যা, FYI, আপনি লেফাফা আক্ষরিক কোন ধরনের করতে পারেন একটি অবজেক্ট ফেরৎ পাবেন না, ( AtomicReference, List, Set)।
ফ্রন্টিয়ার

-5

আমি এটি একটি সহজ বোধগম্য এবং সহজেই ব্যাখ্যাযোগ্য সমাধান হিসাবে পেয়েছি

public class GenericClass<T> {

    private Class classForT(T...t) {
        return t.getClass().getComponentType();
    }

    public static void main(String[] args) {
        GenericClass<String> g = new GenericClass<String>();

        System.out.println(g.classForT());
        System.out.println(String.class);
    }
}

ব্যাখ্যা কর (T...t)। (এজন্য এই কোডটি কার্যকর হয় না))
ক্রিস্টোফার স্নাইডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.