<এর মধ্যে পার্থক্য কী? সুপার ই> এবং <? E> প্রসারিত?


147

মধ্যে পার্থক্য কি <? super E>এবং <? extends E>?

উদাহরণস্বরূপ আপনি যখন ক্লাসটি একবার দেখুন তখন java.util.concurrent.LinkedBlockingQueueনির্মাতার জন্য নিম্নলিখিত স্বাক্ষর রয়েছে:

public LinkedBlockingQueue(Collection<? extends E> c)

এবং পদ্ধতির জন্য একটি:

public int drainTo(Collection<? super E> c)

উত্তর:


182

প্রথমটি বলে যে এটি "কিছু ধরণের যা ই এর পূর্বপুরুষ"; দ্বিতীয়টি বলে যে এটি "কিছু প্রকার যা E এর একটি সাবক্লাস"। (উভয় ক্ষেত্রে ই নিজেই ঠিক আছে)

সুতরাং কনস্ট্রাক্টর ? extends Eফর্মটি ব্যবহার করে তাই এটি গ্যারান্টি দেয় যে যখন এটি সংগ্রহ থেকে মানগুলি নিয়ে আসে তখন তারা সমস্ত ই বা কিছু উপক্লাস হবে (যেমন এটি সামঞ্জস্যপূর্ণ)। drainToপদ্ধতি মান লাগাতে চেষ্টা করছে বা তাই সংগ্রহের একটি উপাদান প্রকার থাকা হয়েছে, সংগ্রহ E বা সুপারক্লাস

উদাহরণ হিসাবে ধরুন, আপনার যেমন শ্রেণিক শ্রেণিবিন্যাস রয়েছে:

Parent extends Object
Child extends Parent

এবং ক LinkedBlockingQueue<Parent>। আপনি এই পাসিংটি এমনভাবে তৈরি করতে পারবেন List<Child>যা সমস্ত উপাদানকে নিরাপদে অনুলিপি করবে, কারণ প্রত্যেকটি Childপিতা-মাতা। আপনি একটিতে পাস করতে পারেন নি List<Object>কারণ কিছু উপাদানগুলির সাথে সামঞ্জস্য হতে পারে না Parent

তেমনিভাবে আপনি এই সারিটি একটিতে ফেলে দিতে পারেন List<Object>কারণ প্রতিটিই Parentএকটি Object... তবে আপনি এটিকে একটিতে ফেলে দিতে পারেননি List<Child>কারণ এর List<Child>সমস্ত উপাদানগুলির সাথে সামঞ্জস্য হওয়ার প্রত্যাশা Child


25
+1 টি। এটি আসলে ব্যবহারিক পার্থক্য। আনতে প্রসারিত, সন্নিবেশ করানোতে দুর্দান্ত।
ইশাই 14

1
@ জনের প্রথম অনুচ্ছেদে আপনি কী বোঝাতে চেয়েছেন (উভয় ক্ষেত্রে ই নিজেই ঠিক আছে?)
গীক

2
@ গীক: আমি বোঝাতে চাইছি যদি আপনার মতো কিছু থাকে ? extends InputStreamবা ? super InputStreamতবে আপনি একটি InputStreamযুক্তি হিসাবে ব্যবহার করতে পারেন ।
জন স্কিটি

কার্যকর জাভাতে জোস ব্লক দ্বারা আমি কখনই পিসিএস ব্যাখ্যাটি পাই নি। তবে @ যিশাই, এটি মনে রাখার একটি সহায়ক উপায়। সম্ভবত আমরা একটি নতুন
স্মৃতিচারণের

সুতরাং আমি যদি এটি সঠিকভাবে পড়ে থাকি তবে "<? E> প্রসারিত" "এর কি প্রয়োজন?" "E" এর একটি সাবক্লাস, এবং "<? সুপার ই>" "" E "এর"? "এর একটি সাবক্লাস প্রয়োজন, তাই না?
এল সস্ক্রিপ্টর জাস্টিসিরো

130

এর কারণগুলি জাভা কীভাবে জেনেরিক প্রয়োগ করে তার উপর ভিত্তি করে।

একটি অ্যারে উদাহরণ

অ্যারেগুলির সাহায্যে আপনি এটি করতে পারেন (অ্যারেগুলি সমকামী)

Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;

তবে, আপনি যদি এটি করার চেষ্টা করেন তবে কী হবে?

myNumber[0] = 3.14; //attempt of heap pollution

এই শেষ লাইনটি ঠিক জরিমানা সংকলন করবে, তবে আপনি যদি এই কোডটি চালান, আপনি একটি পেতে পারেন ArrayStoreException। কারণ আপনি একটি সংখ্যার অ্যারেতে একটি ডাবল রাখার চেষ্টা করছেন (কোনও সংখ্যার রেফারেন্সের মাধ্যমে অ্যাক্সেস হওয়া নির্বিশেষে)।

এর অর্থ হ'ল আপনি সংকলককে বোকা বানাতে পারবেন তবে রানটাইম টাইপ সিস্টেমটিকে বোকা বানাতে পারবেন না। এবং এটি তাই কারণ অ্যারে আমরা যা পুনরায় সংশোধনযোগ্য প্রকারগুলি বলি । এর অর্থ রানটটাইম জাভা জানে যে এই অ্যারেটি আসলে পূর্ণসংখ্যার অ্যারে হিসাবে ইনস্ট্যান্ট করা হয়েছিল যা কেবল প্রকারের একটি রেফারেন্সের মাধ্যমে অ্যাক্সেস করা যায় Number[]

সুতরাং, যেমন আপনি দেখতে পাচ্ছেন, একটি জিনিস হ'ল অবজেক্টের প্রকৃত ধরণ এবং অন্য জিনিসটি আপনি এটি অ্যাক্সেস করতে ব্যবহার করেন এমন রেফারেন্সের ধরণটি, তাই না?

জাভা জেনারিক্সের সাথে সমস্যা

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

তবে এখানে গুরুত্বপূর্ণ বিষয়টি হ'ল যেহেতু রানটাইমের সময় কোনও ধরণের তথ্য নেই, তাই আমরা নিশ্চিত হচ্ছি যে আমরা গাদা দূষণ করছি না।

এই ক্ষেত্রে,

List<Integer> myInts = new ArrayList<Integer>();
myInts.add(1);
myInts.add(2);

List<Number> myNums = myInts; //compiler error
myNums.add(3.14); //heap pollution

যদি জাভা সংকলক আপনাকে এটি করতে বাধা দেয় না, রানটাইম টাইপ সিস্টেমটি আপনাকে বাধা দিতে পারে না, কারণ রানটাইমের সময় কোনও উপায় নেই, এটি নির্ধারণ করার জন্য যে এই তালিকাটি কেবলমাত্র পূর্ণসংখ্যার একটি তালিকা হতে পারে determine জাভা রানটাইম আপনাকে যা যা করতে চান এই তালিকায় রাখবে, যখন এটিতে কেবল পূর্ণসংখ্যার উপস্থিতি থাকতে হবে, কারণ এটি তৈরি হওয়ার পরে এটি পূর্ণসংখ্যার তালিকা হিসাবে ঘোষণা করা হয়েছিল।

যেমন, জাভা ডিজাইনারগণ নিশ্চিত করেছেন যে আপনি সংকলককে বোকা বানাতে পারবেন না। আপনি যদি সংকলককে বোকা বানাতে না পারেন (যেমন আমরা অ্যারে দিয়ে করতে পারি) আপনি রানটাইম টাইপ সিস্টেমটিকেও বোকা বানাতে পারবেন না।

যেমনটি, আমরা বলি যে জেনেরিক প্রকারগুলি অ-সংশোধনযোগ্য

স্পষ্টতই, এটি বহুবর্ষকে বাধাগ্রস্ত করবে। নিম্নলিখিত উদাহরণ বিবেচনা করুন:

static long sum(Number[] numbers) {
   long summation = 0;
   for(Number number : numbers) {
      summation += number.longValue();
   }
   return summation;
}

এখন আপনি এটি এর মতো ব্যবহার করতে পারেন:

Integer[] myInts = {1,2,3,4,5};
Long[] myLongs = {1L, 2L, 3L, 4L, 5L};
Double[] myDoubles = {1.0, 2.0, 3.0, 4.0, 5.0};

System.out.println(sum(myInts));
System.out.println(sum(myLongs));
System.out.println(sum(myDoubles));

আপনি যদি জেনেরিক সংগ্রহ সহ একই কোডটি প্রয়োগ করার চেষ্টা করেন তবে আপনি সফল হতে পারবেন না:

static long sum(List<Number> numbers) {
   long summation = 0;
   for(Number number : numbers) {
      summation += number.longValue();
   }
   return summation;
}

আপনি যদি চেষ্টা করেন তবে আপনি সংকলক এরোগুলি পেয়ে যাবেন ...

List<Integer> myInts = asList(1,2,3,4,5);
List<Long> myLongs = asList(1L, 2L, 3L, 4L, 5L);
List<Double> myDoubles = asList(1.0, 2.0, 3.0, 4.0, 5.0);

System.out.println(sum(myInts)); //compiler error
System.out.println(sum(myLongs)); //compiler error
System.out.println(sum(myDoubles)); //compiler error

সমাধানটি হল জাভা জেনেরিকের দুটি শক্তিশালী বৈশিষ্ট্য যা covariance এবং বিপরীতমুখী হিসাবে পরিচিত হিসাবে ব্যবহার করা শিখতে হয়।

সহভেদাংক

প্রচলিত সাহায্যে আপনি কোনও কাঠামো থেকে আইটেমগুলি পড়তে পারেন, তবে আপনি এতে কিছুই লিখতে পারবেন না। এই সমস্ত বৈধ ঘোষণা।

List<? extends Number> myNums = new ArrayList<Integer>();
List<? extends Number> myNums = new ArrayList<Float>();
List<? extends Number> myNums = new ArrayList<Double>();

এবং আপনি থেকে পড়তে পারেন myNums:

Number n = myNums.get(0); 

কারণ আপনি নিশ্চিত হতে পারেন যে প্রকৃত তালিকায় যা কিছু আছে, এটি একটি সংখ্যায় আপস করা যেতে পারে (সংখ্যার প্রসারিত সমস্ত কিছুর পরে একটি সংখ্যা, তাই না?)

তবে আপনাকে কোনও সমবায় কাঠামোতে কিছু দেওয়ার অনুমতি নেই।

myNumst.add(45L); //compiler error

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

Contravariance

বিপরীতে আপনি বিপরীতে করতে পারেন। আপনি জিনিসগুলিকে জেনেরিক কাঠামোর মধ্যে রাখতে পারেন তবে আপনি এটি থেকে পড়তে পারবেন না।

List<Object> myObjs = new List<Object>();
myObjs.add("Luke");
myObjs.add("Obi-wan");

List<? super Number> myNums = myObjs;
myNums.add(10);
myNums.add(3.14);

এই ক্ষেত্রে, অবজেক্টের প্রকৃত প্রকৃতি হ'ল অবজেক্টগুলির একটি তালিকা, এবং বৈপরীত্যের মাধ্যমে আপনি সংখ্যাগুলিকে এতে স্থাপন করতে পারেন, মূলত কারণ সমস্ত সংখ্যারই তাদের পূর্বপুরুষ হিসাবে অবজেক্ট থাকে। যেমন, সমস্ত নম্বর বস্তু এবং তাই এটি বৈধ।

যাইহোক, আপনি এই সংকীর্ণ কাঠামোটি থেকে কোনও নম্বর পাবেন বলে ধরে নিয়ে নিরাপদে কিছু পড়তে পারবেন না।

Number myNum = myNums.get(0); //compiler-error

আপনি দেখতে পাচ্ছেন, যদি সংকলক আপনাকে এই লাইনটি লেখার অনুমতি দেয় তবে আপনি রানটাইমটিতে একটি ক্লাসকাস্ট এক্সেকশন পাবেন।

নীতি পান / রাখুন

যেমন, যখন আপনি কেবল কোনও কাঠামোর বাইরে জেনেরিক মান নেওয়ার ইচ্ছা করেন তখন কোভারিয়েন্স ব্যবহার করুন, যখন আপনি কেবল জেনেরিক মানগুলিকে কোনও কাঠামোর মধ্যে রাখবেন এবং যখন আপনি উভয়ই করার ইচ্ছা করেন তখন সঠিক জেনেরিক প্রকারটি ব্যবহার করুন cont

আমার কাছে সর্বোত্তম উদাহরণটি হ'ল নিম্নলিখিতটি যা কোনও তালিকা থেকে অন্য তালিকায় অনুলিপি করে। এটি কেবল উত্স থেকে আইটেম পায় এবং এটি কেবলমাত্র লক্ষ্যগুলিতে আইটেম রাখে

public static void copy(List<? extends Number> source, List<? super Number> target) {
    for(Number number : source) {
        target(number);
    }
}

সমাজতন্ত্র এবং বৈপরীত্যের শক্তিগুলিকে ধন্যবাদ এটি এরকম একটি মামলার জন্য কাজ করে:

List<Integer> myInts = asList(1,2,3,4);
List<Double> myDoubles = asList(3.14, 6.28);
List<Object> myObjs = new ArrayList<Object>();

copy(myInts, myObjs);
copy(myDoubles, myObjs);

27
এই উত্তরটি শীর্ষে উঠা উচিত। সুন্দর ব্যাখ্যা।
সুরেশ আত্তা

1
@ উইন্ডালোরজো, একটি ছোট টাইপ রয়েছে যা আপনি কনট্রাভেরিয়েন্সের আওতায় ঠিক করতে চান। আপনি বলছেন List<Object> myObjs = new List<Object();(যা >দ্বিতীয়টির জন্য বন্ধ হয়ে যাচ্ছে Object)।

এই সূক্ষ্ম ধারণাগুলির দুর্দান্ত, সহজ এবং স্পষ্ট উদাহরণ!
db1234

অন্যদের জিনিস মনে রাখতে সহায়তা করতে আপনি কিছু যুক্ত করতে পারেন। আপনি যখন একটি সুপার ক্লাস থেকে কোনও পদ্ধতি কল করতে চান, আপনি ব্যবহার করুন super.methodName। ব্যবহার করার সময় <? super E>, এর অর্থ " superদিকনির্দেশের কিছু " যেমন দিকের কোনও কিছুর বিপরীতে থাকে extends। উদাহরণ: Objectহয় superদিক Number(যেহেতু এটি একটি সুপার ক্লাস হয়) এবং Integerহয় extends(যেহেতু প্রসারিত দিক Number)।
BrainStorm.exe

59

<? extends E>Eউপরের সীমা হিসাবে সংজ্ঞায়িত : "এটিতে কাস্ট করা যেতে পারে E"।

<? super E>Eনিম্ন সীমা হিসাবে সংজ্ঞায়িত : "এটিতে Eকাস্ট করা যেতে পারে।"


6
আমি যে পার্থক্যটি দেখেছি তার মধ্যে এটি অন্যতম সেরা সাধারণ / ব্যবহারিক সারাংশ।
জ্যাব

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

3
@ tgm1024 "সুপারক্লাস" এবং "সাবক্লাস" আপনাকে অবশ্যই অনেক সমস্যায় ফেলবে।
ডেভিড মোলস

@ ডেভিডমোলস, কেন? আমি যা বলছি তা আপনি পরিষ্কারভাবে অনুসরণ করছেন না । "সুপারক্লাস" "সুপারসেট" এর অনুরূপ; বিশেষজ্ঞের ধারণাটি আইএস-এ সম্পর্কের অধীনে প্রয়োগযোগ্যতার হ্রাস। অ্যাপল আইএস-এ ফল। ফল (সুপারক্লাস) একটি উপসেট হিসাবে অ্যাপল (সাবক্লাস) সহ একটি সুপারসেট। সেই মৌখিক সম্পর্কটা ঠিক আছে। আমি যা ভাঙার কথা বলছি তা হ'ল "উচ্চতর" এবং "নিম্ন" এর "সুপারসেট" এবং "সাবসেট" এর অভ্যন্তরীণ ম্যাপিং রয়েছে। ওওতে শর্ত হিসাবে উচ্চ এবং নিম্নগুলি এড়ানো উচিত।

1
@ tgm1024 "সুপার-" ল্যাটিন সুপার "উপরে, উপর" এবং "উপ-" ল্যাটিন সাব "নীচে, নীচে" থেকে এসেছে। এটি বলতে গেলে, ব্যুৎপত্তিগতভাবে, সুপার আপ এবং সাব ডাউন রয়েছে।
ডেভিড মোল

12

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

ধারণাটি হ'ল যদি আপনার কোডটি যদি বস্তু থেকে জেনেরিক মান গ্রহণ করে তবে আপনার প্রসারিত ব্যবহার করা উচিত। আপনি যদি জেনেরিক ধরণের জন্য নতুন মান তৈরি করে থাকেন তবে আপনার সুপার ব্যবহার করা উচিত।

উদাহরণস্বরূপ:

public void pushAll(Iterable<? extends E> src) {
  for (E e: src) 
    push(e);
}

এবং

public void popAll(Collection<? super E> dst) {
  while (!isEmpty())
    dst.add(pop())
}

তবে সত্যই আপনার এই বইটি পরীক্ষা করা উচিত: http://java.sun.com/docs/books/effective/



7

আপনি পারে মেয়াদের জন্য google করতে চান contravariance ( <? super E>) এবং সহভেদাংক ( <? extends E>)। আমি দেখতে পেয়েছি যে জেনেরিকগুলি বোঝার সময় সবচেয়ে দরকারী জিনিসটি ছিল আমার এর পদ্ধতি স্বাক্ষরটি বোঝার জন্য Collection.addAll:

public interface Collection<T> {
    public boolean addAll(Collection<? extends T> c);
}

শুধু আপনি একটি যোগ করতে পারবেন চাই চাই যেমন Stringএকটি থেকে List<Object>:

List<Object> lo = ...
lo.add("Hello")

পদ্ধতির মাধ্যমে আপনার একটি List<String>(বা কোনও সংগ্রহ String) যুক্ত করতে সক্ষম হওয়া উচিত addAll:

List<String> ls = ...
lo.addAll(ls)

তবে আপনার বুঝতে হবে যে a List<Object>এবং a List<String>সমান নয় এবং পূর্ববর্তীটি পূর্বের একটি সাবক্লাস নয়। যা দরকার তা হল একটি কোভেরিয়েন্ট টাইপ প্যারামিটারের ধারণা ie যেমনটি<? extends T> বিট।

একবার আপনার এটি হয়ে গেলে, পরিস্থিতিগুলি বিবেচনা করা সহজ যেখানে আপনি বৈষম্যও চান ( Comparableইন্টারফেসটি দেখুন)।


4

উত্তরের আগে; দয়া করে এটি পরিষ্কার থাকুন

  1. জেনারিকস কেবল TYPE_SAFETY টি নিশ্চিত করার জন্য সময় বৈশিষ্ট্য সংকলন করে, এটি RUTIME এর সময় উপলব্ধ হবে না।
  2. জেনারিক্সের সাথে কেবল একটি রেফারেন্সই এই ধরণের সুরক্ষাকে বাধ্য করবে; যদি রেফারেন্সটি জেনেরিকের সাথে ঘোষণা না করা হয় তবে এটি নিরাপদ প্রকার ছাড়াই কাজ করবে।

উদাহরণ:

List stringList = new ArrayList<String>();
stringList.add(new Integer(10)); // will be successful.

আশা করি এটি আপনাকে ওয়াইল্ডকার্ড আরও স্পষ্ট বুঝতে সাহায্য করবে।

//NOTE CE - Compilation Error
//      4 - For

class A {}

class B extends A {}

public class Test {

    public static void main(String args[]) {

        A aObj = new A();
        B bObj = new B();

        //We can add object of same type (A) or its subType is legal
        List<A> list_A = new ArrayList<A>();
        list_A.add(aObj);
        list_A.add(bObj); // A aObj = new B(); //Valid
        //list_A.add(new String()); Compilation error (CE);
        //can't add other type   A aObj != new String();


        //We can add object of same type (B) or its subType is legal
        List<B> list_B = new ArrayList<B>();
        //list_B.add(aObj); CE; can't add super type obj to subclass reference
        //Above is wrong similar like B bObj = new A(); which is wrong
        list_B.add(bObj);



        //Wild card (?) must only come for the reference (left side)
        //Both the below are wrong;   
        //List<? super A> wildCard_Wrongly_Used = new ArrayList<? super A>();
        //List<? extends A> wildCard_Wrongly_Used = new ArrayList<? extends A>();


        //Both <? extends A>; and <? super A> reference will accept = new ArrayList<A>
        List<? super A> list_4__A_AND_SuperClass_A = new ArrayList<A>();
                        list_4__A_AND_SuperClass_A = new ArrayList<Object>();
                      //list_4_A_AND_SuperClass_A = new ArrayList<B>(); CE B is SubClass of A
                      //list_4_A_AND_SuperClass_A = new ArrayList<String>(); CE String is not super of A  
        List<? extends A> list_4__A_AND_SubClass_A = new ArrayList<A>();
                          list_4__A_AND_SubClass_A = new ArrayList<B>();
                        //list_4__A_AND_SubClass_A = new ArrayList<Object>(); CE Object is SuperClass of A


        //CE; super reference, only accepts list of A or its super classes.
        //List<? super A> list_4__A_AND_SuperClass_A = new ArrayList<String>(); 

        //CE; extends reference, only accepts list of A or its sub classes.
        //List<? extends A> list_4__A_AND_SubClass_A = new ArrayList<Object>();

        //With super keyword we can use the same reference to add objects
        //Any sub class object can be assigned to super class reference (A)                  
        list_4__A_AND_SuperClass_A.add(aObj);
        list_4__A_AND_SuperClass_A.add(bObj); // A aObj = new B();
        //list_4__A_AND_SuperClass_A.add(new Object()); // A aObj != new Object(); 
        //list_4__A_AND_SuperClass_A.add(new String()); CE can't add other type

        //We can't put anything into "? extends" structure. 
        //list_4__A_AND_SubClass_A.add(aObj); compilation error
        //list_4__A_AND_SubClass_A.add(bObj); compilation error
        //list_4__A_AND_SubClass_A.add("");   compilation error

        //The Reason is below        
        //List<Apple> apples = new ArrayList<Apple>();
        //List<? extends Fruit> fruits = apples;
        //fruits.add(new Strawberry()); THIS IS WORNG :)

        //Use the ? extends wildcard if you need to retrieve object from a data structure.
        //Use the ? super wildcard if you need to put objects in a data structure.
        //If you need to do both things, don't use any wildcard.


        //Another Solution
        //We need a strong reference(without wild card) to add objects 
        list_A = (ArrayList<A>) list_4__A_AND_SubClass_A;
        list_A.add(aObj);
        list_A.add(bObj);

        list_B = (List<B>) list_4__A_AND_SubClass_A;
        //list_B.add(aObj); compilation error
        list_B.add(bObj);

        private Map<Class<? extends Animal>, List<? extends Animal>> animalListMap;

        public void registerAnimal(Class<? extends Animal> animalClass, Animal animalObject) {

            if (animalListMap.containsKey(animalClass)) {
                //Append to the existing List
                 /*    The ? extends Animal is a wildcard bounded by the Animal class. So animalListMap.get(animalObject);
                 could return a List<Donkey>, List<Mouse>, List<Pikachu>, assuming Donkey, Mouse, and Pikachu were all sub classes of Animal. 
                 However, with the wildcard, you are telling the compiler that you don't care what the actual type is as long as it is a sub type of Animal.      
                 */   
                //List<? extends Animal> animalList = animalListMap.get(animalObject);
                //animalList.add(animalObject);  //Compilation Error because of List<? extends Animal>
                List<Animal> animalList = animalListMap.get(animalObject);
                animalList.add(animalObject);      


            } 
    }

    }
}

এছাড়াও দেখুন @Dana stackoverflow.com/questions/15255929/...
Kanagavelu Sugumar

জেনেরিক ক্লাস ধরনের উপর আমার উত্তর stackoverflow.com/questions/462297/how-to-use-classt-in-java/...
Kanagavelu Sugumar

1
কোড সহ ভাল ব্যাখ্যা। আপনি যদি কোড ব্লকের বাইরে কোডে মন্তব্য ব্যবহার করেন তবে এটি দেখার জন্য আরও ভাল এবং আরও পঠনযোগ্য।
প্রভু

3

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

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


1

আপনার প্যারেন্ট ক্লাস এবং চাইল্ড ক্লাস পিতামাতাদের কাছ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত। এখন, <? পিতামাতাকে প্রসারিত করে> - এটি প্যারেন্ট ক্লাসকে গ্রহণ করে বা চাইল্ড ক্লাস <? সুপার প্যারেন্ট> - এটি প্যারেন্ট ক্লাস বা গ্র্যান্ডপ্যারেন্ট ক্লাস গ্রহণ করে

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