জাভাতে ক্লাস <টি> কীভাবে ব্যবহার করবেন?


247

জেনেরিক্স সম্পর্কে এই বিষয়ে একটি ভাল আলোচনা আছে এবং তারা এই প্রশ্নটিতে সত্যই পর্দার আড়ালে কী করে , তাই আমরা সকলেই জানি যে Vector<int[]>এটি পূর্ণসংখ্যার অ্যারেগুলির একটি ভেক্টর, এবং HashTable<String, Person>যার কীগুলি স্ট্রিং এবং মানগুলির একটি টেবিল Person। যাইহোক, আমাকে কী স্ট্যাম্প ব্যবহার তা হ'ল Class<>

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

উত্তর:


136

শ্রেণীর শ্রেণীর জেনারাইড সংস্করণ ব্যবহার করা আপনাকে অন্যান্য জিনিসের মধ্যে যেমন পছন্দ করে তা লিখতে দেয়

Class<? extends Collection> someCollectionClass = someMethod();

এবং তারপরে আপনি নিশ্চিত হয়ে উঠতে পারেন যে আপনি প্রাপ্ত ক্লাস অবজেক্টটি প্রসারিত হয়েছে Collectionএবং এই শ্রেণীর একটি উদাহরণ (অন্তত) একটি সংগ্রহ হবে।


183

আমরা কেবল জানি " কোনও শ্রেণীর সমস্ত উদাহরণ একই জাভা.এল. শেয়ার করে that ধরণের শ্রেণীর ক্লাস অবজেক্ট "

যেমন)

Student a = new Student();
Student b = new Student();

তাহলে a.getClass() == b.getClass()সত্য।

এখন ধরে নিন

Teacher t = new Teacher();

জেনারিক ব্যতীত নীচে সম্ভব।

Class studentClassRef = t.getClass();

তবে এটা এখন ভুল ..?

যেমন) সাথে কল করা public void printStudentClassInfo(Class studentClassRef) {}যেতে পারেTeacher.class

এটি জেনেরিক ব্যবহার এড়ানো যায়।

Class<Student> studentClassRef = t.getClass(); //Compilation error.

এখন টি কি ?? টি হ'ল টাইপ প্যারামিটার (একে টাইপ ভেরিয়েবলও বলা হয়); কোণ বন্ধনী (<>) দ্বারা সীমিত, শ্রেণীর নাম অনুসরণ করে।
টি ক্লাস ফাইলটি লেখার সময় ঘোষিত ভেরিয়েবল নামের (যে কোনও নাম হতে পারে) এর মতো কেবল একটি প্রতীক। পরবর্তীতে টি
আরম্ভের সময় বৈধ শ্রেণীর নামের সাথে প্রতিস্থাপিত হবে ( HashMap<String> map = new HashMap<String>();)

যেমন) class name<T1, T2, ..., Tn>

সুতরাং Class<T>নির্দিষ্ট শ্রেণীর ধরণের ' T' এর একটি শ্রেণি অবজেক্টকে উপস্থাপন করে ।

ধরে নিন যে আপনার শ্রেণি পদ্ধতিতে নীচের মতো অজানা টাইপের প্যারামিটারগুলির সাথে কাজ করতে হবে

/**
 * Generic version of the Car class.
 * @param <T> the type of the value
 */
public class Car<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

এখানে টি কারনেমের মতো Stringটাইপ হিসাবে ব্যবহার করা যেতে পারে

বা টি মডেল নাম্বার হিসাবে Integerটাইপ হিসাবে ব্যবহার করা যেতে পারে ,

বা টি টি বৈধ গাড়ী উদাহরণ হিসাবে Objectটাইপ হিসাবে ব্যবহার করা যেতে পারে ।

এখন এখানে উপরেরটি সরল POJO যা রানটাইম সময়ে বিভিন্নভাবে ব্যবহার করা যেতে পারে।
সংগ্রহগুলি উদাহরণস্বরূপ) তালিকা, সেট, হাশম্যাপ সেরা উদাহরণ যা টি এর ঘোষণাপত্র অনুসারে বিভিন্ন অবজেক্টের সাথে কাজ করবে, তবে একবার আমরা টি স্ট্রিং
যেমন হিসাবে ঘোষণা করলাম ) HashMap<String> map = new HashMap<String>();তারপরে এটি কেবল স্ট্রিং ক্লাস উদাহরণ বস্তুগুলি গ্রহণ করবে।

জেনেরিক পদ্ধতি

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

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

 class Util {
    // Generic static method
    public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

 class Pair<K, V> {

    private K key;
    private V value;
}

এখানে <K, V, Z, Y>পদ্ধতি আর্গুমেন্ট ব্যবহৃত ধরনের ঘোষণা যা উচিত রিটার্ন টাইপ যা আগে booleanএখানে।

নীচে; ধরণের ঘোষণাপত্রটি <T>পদ্ধতি স্তরে প্রয়োজন হয় না, কারণ এটি ইতিমধ্যে শ্রেণি পর্যায়ে ঘোষণা করা হয়েছে।

class MyClass<T> {
   private  T myMethod(T a){
       return  a;
   }
}

ক্লাস-লেভেল ধরণের প্যারামিটারগুলি কে, ভি, জেড এবং ওয়াই স্থির প্রসঙ্গে (এখানে স্থির পদ্ধতি) ব্যবহার করা যাবে না বলে নীচে ভুল।

class Util <K, V, Z, Y>{
    // Generic static method
    public static  boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

অন্যান্য ভ্যালিড স্কিনিয়ারস হয়

class MyClass<T> {

        //Type declaration <T> already done at class level
        private  T myMethod(T a){
            return  a;
        }

        //<T> is overriding the T declared at Class level;
        //So There is no ClassCastException though a is not the type of T declared at MyClass<T>. 
        private <T> T myMethod1(Object a){
                return (T) a;
        }

        //Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).  
        private T myMethod1(Object a){
                return (T) a;
        }       

        // No ClassCastException        
        // MyClass<String> obj= new MyClass<String>();
        // obj.myMethod2(Integer.valueOf("1"));
        // Since type T is redefined at this method level.
        private <T> T myMethod2(T a){
            return  a;
        }

        // No ClassCastException for the below
        // MyClass<String> o= new MyClass<String>();
        // o.myMethod3(Integer.valueOf("1").getClass())
        // Since <T> is undefined within this method; 
        // And MyClass<T> don't have impact here
        private <T> T myMethod3(Class a){
            return (T) a;
        }

        // ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
        // Should be o.myMethod3(String.valueOf("1").getClass())
    private  T myMethod3(Class a){
        return (T) a;
    }


        // Class<T> a :: a is Class object of type T
        //<T> is overriding of class level type declaration; 
        private <T> Class<T> myMethod4(Class<T> a){
            return  a;
        }
    }

এবং পরিশেষে স্থির পদ্ধতিতে সর্বদা সুস্পষ্ট <T>ঘোষণার প্রয়োজন হয়; এটি শ্রেণি স্তর থেকে প্রাপ্ত হবে না Class<T>। এটি ক্লাস স্তর টির কারণে উদাহরণের সাথে আবদ্ধ।

জেনারিক্সের উপর বিধিনিষেধগুলিও পড়ুন

ওয়াইল্ডকার্ডস এবং সাব টাইপিং

জেনেরিক পদ্ধতির জন্য যুক্তি টাইপ করুন


2
বেষ্টিত ওয়াইল্ডকার্ড আমার উত্তর stackoverflow.com/questions/1368166/...
Kanagavelu Sugumar

"শ্রেণি <T> নির্দিষ্ট শ্রেণীর ধরণের 'টি' এর একটি শ্রেণি অবজেক্টকে উপস্থাপন করে that ধন্যবাদ ..
bynu022

এই উত্তরটি ক্লাস (জাভাতে) সম্পর্কে কোনও প্রশ্নে (স্কুল থেকে) ক্লাসগুলি যেভাবে ব্যবহার করে তাতে মারাত্মক বিভ্রান্তিকর। বাক্য থেকে অন্য বাক্যে লেখক কী সম্পর্কে কথা বলছেন তা জানা শক্ত।
ইকক্স

@ ইকক্স আমি দুঃখিত, আপনার যদি নির্দিষ্ট প্রশ্ন থাকে তবে আমি এটি উন্নত করতে পারি।
কানাগাভেলু সুগুমার


32

জাভা ডকুমেন্টেশন থেকে:

[...] আরও আশ্চর্যজনকভাবে, ক্লাস ক্লাসটি উদার করা হয়েছে। ক্লাস লিটারেলগুলি এখন টাইপ টোকেন হিসাবে কাজ করে, রান-টাইম এবং সংকলন-টাইপ উভয় প্রকারের তথ্য সরবরাহ করে। এটি নতুন অ্যানোটেটেড এলিমেন্ট ইন্টারফেসে getAnnotation পদ্ধতি দ্বারা অনুকরণযুক্ত স্ট্যাটিক কারখানার একটি স্টাইলকে সক্ষম করে:

<T extends Annotation> T getAnnotation(Class<T> annotationType); 

এটি একটি জেনেরিক পদ্ধতি। এটি তার যুক্তি থেকে এটির টাইপ প্যারামিটার টির মান নির্ধারণ করে এবং নিম্নলিখিত স্নিপেট দ্বারা চিত্রিত হিসাবে টি এর উপযুক্ত উদাহরণ প্রদান করে:

Author a = Othello.class.getAnnotation(Author.class);

জেনারিকের আগে, আপনাকে ফলাফলটি লেখকের কাছে দিতে হবে। এছাড়াও আপনার কাছে সংকলকটি পরীক্ষা করার কোনও উপায় ছিল না যে প্রকৃত প্যারামিটারটি টীকাটির একটি সাবক্লাস উপস্থাপন করেছে। [...]

ঠিক আছে, আমাকে কখনও এই ধরণের জিনিস ব্যবহার করতে হয়নি। যে কেউ?


2
আমি (ভেবেছিলাম) করেছি। একটি কাঠামো (প্রকারের) আমি আপনার মডিউলের উপর নির্ভরশীল পরিষেবার ক্লাস নামটি পাস করার প্রয়োজনীয়তার সাথে কাজ করেছি। আমি পছন্দসই পরিমাণগুলিকে সীমাবদ্ধ করতে ক্লাস অবজেক্টগুলির উপরে যে স্তরটি তৈরি করেছি। Class<? extends X>আমার অনুভূত স্বরলিপিটি ব্যবহার করে আমি এটিকে কেবল 'পরিষেবা' প্রকারের মধ্যে সীমাবদ্ধ করতে পারি। কোনও সাধারণ 'পরিষেবা' প্রকার ব্যতীত, তাই আমি কেবল এটি দিয়েই করতে পারি Class<?>। হায়রে।
fwelstra

9

আমি class<T>পরিষেবা রেজিস্ট্রি লুপআপ তৈরি করার সময় দরকারী হয়েছি। যেমন

<T> T getService(Class<T> serviceClass)
{
    ...
}

5

অন্যান্য উত্তরগুলি যেমন উল্লেখ করেছে, কেন এটিকে classজেনেরিক করা হয়েছে তার অনেকগুলি এবং ভাল কারণ রয়েছে । তবে প্রচুর সময় রয়েছে যে আপনার সাথে জেনেরিক ধরনটি ব্যবহার করার কোনও উপায় নেই Class<T>। এই ক্ষেত্রে, আপনি কেবল হলুদগ্রহণের সতর্কতাগুলি উপেক্ষা করতে পারেন বা আপনি ব্যবহার করতে পারেন Class<?>... আমি এটি এটিই করি;)


@SuppressWarnings("unchecked")উদ্ধার করতে আসে! ( আপনার কোডটিতে সম্ভাব্য সমস্যাগুলি যতটা অস্পষ্ট করে তোলে যতটা সম্ভব ছোট স্কোপে সর্বদা এটি প্রয়োগ করার ক্ষেত্রে কেবল সতর্ক থাকুন ))
ডোনাল ফেলো

4

@ কাইর হাগলিনের জবাব অনুসরণ করে জ্যাক্সবি পদ্ধতি ছাড়ার আরও একটি উদাহরণ জ্যাকএক্সবি আনমারশেলিংয়ের ডকুমেন্টেশনে দেখা যায় :

public <T> T unmarshal( Class<T> docClass, InputStream inputStream )
         throws JAXBException {
  String packageName = docClass.getPackage().getName();
  JAXBContext jc = JAXBContext.newInstance( packageName );
  Unmarshaller u = jc.createUnmarshaller();
  JAXBElement<T> doc = (JAXBElement<T>)u.unmarshal( inputStream );
  return doc.getValue();
}

এটি unmarshalএকটি স্বেচ্ছাসেবী JAXB সামগ্রী ট্রি ধরণের একটি দস্তাবেজ ফিরিয়ে আনতে দেয় ।


2

আপনি প্রায়শই ওয়াইল্ডকার্ডগুলির সাথে ব্যবহার করতে চান Class। উদাহরণস্বরূপ, Class<? extends JComponent>আপনাকে শ্রেণিটির কিছু সাবক্লাস নির্দিষ্ট করার অনুমতি দেয় JComponent। আপনি যদি Classউদাহরণটি পুনরুদ্ধার করে থাকেন Class.forName, তবে আপনি Class.asSubclassউদাহরণ তৈরির চেষ্টা করার আগে কাস্ট করার জন্য ব্যবহার করতে পারেন ।


2

জাভা <T>মানে জেনেরিক ক্লাস। জেনেরিক ক্লাস হল এমন একটি ক্লাস যা কোনও প্রকারের ডেটা টাইপের উপর কাজ করতে পারে বা অন্য কথায় আমরা বলতে পারি এটি ডেটা টাইপ ইন্ডিপেন্ডেন্ট।

public class Shape<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

যেখানে টি মানে টাইপ। এখন আপনি যখন এই শেপ ক্লাসের উদাহরণ তৈরি করবেন তখন এটি কী ডেটা টাইপ করে কাজ করবে তার জন্য আপনাকে সংকলকটি বলতে হবে।

উদাহরণ:

Shape<Integer> s1 = new Shape();
Shape<String> s2 = new Shape();

পূর্ণসংখ্যা একটি প্রকার এবং স্ট্রিংও এক প্রকার।

<T>বিশেষত জেনেরিক প্রকারের জন্য দাঁড়িয়েছে। জাভা ডক্স মতে - একটি জেনেরিক টাইপ একটি জেনেরিক বর্গ বা ইন্টারফেস যে হয় স্থিতিমাপ প্রকারের।


0

কেবল অন্য উদাহরণে বলতে গেলে, ক্লাসের জেনেরিক সংস্করণ ( Class<T>) কোনও ব্যক্তিকে যেমন নীচের মতো জেনেরিক ফাংশন লিখতে দেয়।

public static <T extends Enum<T>>Optional<T> optionalFromString(
        @NotNull Class<T> clazz,
        String name
) {
    return Optional<T> opt = Optional.ofNullable(name)
            .map(String::trim)
            .filter(StringUtils::isNotBlank)
            .map(String::toUpperCase)
            .flatMap(n -> {
                try {
                    return Optional.of(Enum.valueOf(clazz, n));
                } catch (Exception e) {
                    return Optional.empty();
                }
            });
}

-2

এটি শুরুতেই বিভ্রান্তিকর। তবে এটি নীচের পরিস্থিতিতে সহায়তা করে:

class SomeAction implements Action {
}

// Later in the code.
Class<Action> actionClass = Class.forName("SomeAction"); 
Action action = actionClass.newInstance();
// Notice you get an Action instance, there was no need to cast.

4
অ্যাকশনকে = নতুন অ্যাকশন () বলার এটি কি কেবল অবিশ্বাস্যরকম জটিল উপায় নয়?
কার্ল 19

1
Action a = new Action() ? Actionআমি একটি ইন্টারফেস, এটি SomeActionআমরা একটি উদাহরণ পেতে চেষ্টা করছি। আমাদের কেবল SomeActionরানটাইম এ উপলব্ধ নাম আছে ।
ফাস্টকোডেজাভা

এটি টাইপচেকিং পাস করে না: জাভা সংকলকটি </ c >> Class.forName ("কিছু কিছু") </code> <code>Class<Action> </code> টাইপের হবে তা বলার উপায় নেই রানটাইমে পরিচিত হতে হবে।
টনিও

@ ট্যানিও, ঠিক আছে, তাই আপনাকে সম্ভবত প্রথম লাইনটি কোনও ধরণের চেষ্টা / ধরার জন্য আবদ্ধ করতে হবে। তবে ধরে নিই যে সেখানে কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয়নি, দ্বিতীয় লাইনটি কাজের গ্যারান্টিযুক্ত।
ম্যাট্রিক্সফ্রোগ

2
আপনি যা সত্যই বর্ণনা করছেন তা হ'ল SomeAction.class প্যাটার্ন ক্লাস <এর সাথে মেলে? অ্যাকশন> - প্রসারিত, যদি আপনার কোনও পদ্ধতি ব্যবহারঅ্যাকশন থাকে (শ্রেণি <? ক্রম প্রসারিত হয়> ক্লাস) থাকে তবে আপনি ব্যবহারঅ্যাকশন (SomeAction.class) কল করতে পারেন।
টমাস অ্যান্ড্রুজ

-5

কেবল গরুর মাংসের ক্লাসটি ব্যবহার করুন:

public <T> T beefmarshal( Class<beef> beefClass, InputBeef inputBeef )
     throws JAXBException {
     String packageName = docClass.getPackage().getBeef();
     JAXBContext beef = JAXBContext.newInstance( packageName );
     Unmarshaller u = beef.createBeef();
     JAXBElement<T> doc = (JAXBElement<T>)u.beefmarshal( inputBeef );
     return doc.getBeef();
}

4
এটি সত্যই প্রশ্নের পুরো উত্তর সরবরাহ করে না। যদি আপনি ভাবেন যে আপনার কিছু যোগ করার আছে তবে এই উত্তরটি সম্পাদনা করুন।
মাস্টারএএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.