আমি কীভাবে তালিকাতে যুক্ত করতে পারি? সংখ্যা> তথ্য কাঠামো প্রসারিত?


152

আমার একটি তালিকা রয়েছে যা এইভাবে ঘোষণা করা হয়েছে:

 List<? extends Number> foo3 = new ArrayList<Integer>();

আমি foo3 এ 3 যোগ করার চেষ্টা করেছি। তবে আমি এর মতো একটি ত্রুটি বার্তা পাই:

The method add(capture#1-of ? extends Number) in the type List<capture#1-of ?
extends Number> is not applicable for the arguments (ExtendsNumber)

61
নোট যে এর List<? extends Number>অর্থ এই নয় যে "বিভিন্ন ধরণের অবজেক্টের তালিকা, যার সবগুলিই প্রসারিত হয় Number"। এর অর্থ " প্রসারিত একক ধরণের অবজেক্টের তালিকা Number"।
পাভেল মিনায়েভ

1
আপনি আরও ভালভাবে PECS বিধি পরীক্ষা করুন, প্রযোজক প্রসারিত করেন, গ্রাহক সুপার। stackoverflow.com/questions/2723397/...
noego

উত্তর:


302

দুঃখিত, কিন্তু আপনি পারবেন না।

ওয়াইল্ডকার্ড ঘোষণার List<? extends Number> foo3অর্থ হল যে চলকটি foo3কোনও ধরণের পরিবারের (কোনও নির্দিষ্ট ধরণের কোনও মানের চেয়ে) কোনও মান ধরে রাখতে পারে। এর অর্থ হ'ল এগুলির যে কোনও একটি আইনী দায়িত্ব:

List<? extends Number> foo3 = new ArrayList<Number>;  // Number "extends" Number
List<? extends Number> foo3 = new ArrayList<Integer>; // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>;  // Double extends Number

সুতরাং, এটি প্রদত্ত, List foo3উপরের সম্ভাব্য ArrayListকার্যভারের কোনওটির পরে আপনি কোন ধরণের অবজেক্টটি যুক্ত করতে পারবেন তা বৈধ হবে :

  • আপনি এ যুক্ত করতে পারবেন না Integerকারণ foo3এটিতে নির্দেশ করা যেতে পারে List<Double>
  • আপনি একটি যুক্ত করতে পারবেন না Doubleকারণ foo3এটিতে নির্দেশ করা হতে পারে List<Integer>
  • আপনি একটি যুক্ত করতে পারবেন না Numberকারণ foo3এটিতে নির্দেশ করা হতে পারে List<Integer>

আপনি এতে কোনও পদ যুক্ত List<? extends T>করতে পারবেন না কারণ Listএটি কী ধরণের সত্যই আপনি দেখিয়ে দিচ্ছেন তা আপনি গ্যারান্টি দিতে পারবেন না, সুতরাং আপনি গ্যারান্টি দিতে পারবেন না যে সেই বস্তুটি এতে অনুমোদিত List। একমাত্র "গ্যারান্টি" হ'ল আপনি কেবল এটি থেকে পড়তে পারেন এবং আপনি একটি Tবা সাবক্লাস পাবেন T

বিপরীত যুক্তি প্রয়োগ করা হয় super, যেমন List<? super T>। এগুলি আইনী:

List<? super Number> foo3 = new ArrayList<Number>; // Number is a "super" of Number
List<? super Number> foo3 = new ArrayList<Object>; // Object is a "super" of Number

আপনি টি (উদাহরণস্বরূপ Number) থেকে নির্দিষ্ট টাইপটি পড়তে পারবেন না List<? super T>কারণ Listএটি কী ধরণের সত্যিই নির্দেশ করছে তা আপনি গ্যারান্টি দিতে পারবেন না । আপনার কাছে কেবল "গ্যারান্টি" হ'ল আপনি তালিকার অখণ্ডতা লঙ্ঘন না করে প্রকারের T(বা কোনও সাবক্লাস T) মান যোগ করতে সক্ষম হন।


এর নিখুঁত উদাহরণ হ'ল এর স্বাক্ষর Collections.copy():

public static <T> void copy(List<? super T> dest,List<? extends T> src)

লক্ষ করুন যে srcতালিকা বিবরণী extendsআমাকে সম্পর্কিত তালিকা প্রকারের পরিবারের কাছ থেকে যে কোনও তালিকা পাস করার অনুমতি দেওয়ার জন্য কীভাবে ব্যবহার করে এবং এটি গ্যারান্টি দেয় যে এটি টি জাতীয় টি বা টি এর উপক্লাসের মান তৈরি করে But তবে আপনি srcতালিকায় যুক্ত করতে পারবেন না ।

destতালিকা ঘোষণা ব্যবহারসমূহ superআমাকে সংশ্লিষ্ট তালিকা ধরনের পরিবার থেকে কোন তালিকা পাস করার অনুমতি এবং এখনও আমি যে তালিকায় একটি নির্দিষ্ট ধরনের টি মান লিখতে পারেন গ্যারান্টি। তবে তালিকা থেকে পড়লে নির্দিষ্ট ধরণের টি এর মান পড়ার গ্যারান্টি দেওয়া যায় না।

এখন, জেনেরিক ওয়াইল্ডকার্ডসকে ধন্যবাদ, আমি এই একক পদ্ধতিতে এই কলগুলির যে কোনওটি করতে পারি:

// copy(dest, src)
Collections.copy(new ArrayList<Number>(), new ArrayList<Number());
Collections.copy(new ArrayList<Number>(), new ArrayList<Integer());
Collections.copy(new ArrayList<Object>(), new ArrayList<Number>());
Collections.copy(new ArrayList<Object>(), new ArrayList<Double());

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

  List<Number> listNumber_ListNumber  = new ArrayList<Number>();
//List<Number> listNumber_ListInteger = new ArrayList<Integer>();                    // error - can assign only exactly <Number>
//List<Number> listNumber_ListDouble  = new ArrayList<Double>();                     // error - can assign only exactly <Number>

  List<? extends Number> listExtendsNumber_ListNumber  = new ArrayList<Number>();
  List<? extends Number> listExtendsNumber_ListInteger = new ArrayList<Integer>();
  List<? extends Number> listExtendsNumber_ListDouble  = new ArrayList<Double>();

  List<? super Number> listSuperNumber_ListNumber  = new ArrayList<Number>();
//List<? super Number> listSuperNumber_ListInteger = new ArrayList<Integer>();      // error - Integer is not superclass of Number
//List<? super Number> listSuperNumber_ListDouble  = new ArrayList<Double>();       // error - Double is not superclass of Number


//List<Integer> listInteger_ListNumber  = new ArrayList<Number>();                  // error - can assign only exactly <Integer>
  List<Integer> listInteger_ListInteger = new ArrayList<Integer>();
//List<Integer> listInteger_ListDouble  = new ArrayList<Double>();                  // error - can assign only exactly <Integer>

//List<? extends Integer> listExtendsInteger_ListNumber  = new ArrayList<Number>(); // error - Number is not a subclass of Integer
  List<? extends Integer> listExtendsInteger_ListInteger = new ArrayList<Integer>();
//List<? extends Integer> listExtendsInteger_ListDouble  = new ArrayList<Double>(); // error - Double is not a subclass of Integer

  List<? super Integer> listSuperInteger_ListNumber  = new ArrayList<Number>();
  List<? super Integer> listSuperInteger_ListInteger = new ArrayList<Integer>();
//List<? super Integer> listSuperInteger_ListDouble  = new ArrayList<Double>();     // error - Double is not a superclass of Integer


  listNumber_ListNumber.add(3);             // ok - allowed to add Integer to exactly List<Number>

  // These next 3 are compile errors for the same reason:
  // You don't know what kind of List<T> is really
  // being referenced - it may not be able to hold an Integer.
  // You can't add anything (not Object, Number, Integer,
  // nor Double) to List<? extends Number>      
//listExtendsNumber_ListNumber.add(3);     // error - can't add Integer to *possible* List<Double>, even though it is really List<Number>
//listExtendsNumber_ListInteger.add(3);    // error - can't add Integer to *possible* List<Double>, even though it is really List<Integer>
//listExtendsNumber_ListDouble.add(3);     // error - can't add Integer to *possible* List<Double>, especially since it is really List<Double>

  listSuperNumber_ListNumber.add(3);       // ok - allowed to add Integer to List<Number> or List<Object>

  listInteger_ListInteger.add(3);          // ok - allowed to add Integer to exactly List<Integer> (duh)

  // This fails for same reason above - you can't
  // guarantee what kind of List the var is really
  // pointing to
//listExtendsInteger_ListInteger.add(3);   // error - can't add Integer to *possible* List<X> that is only allowed to hold X's

  listSuperInteger_ListNumber.add(3);      // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object>
  listSuperInteger_ListInteger.add(3);     // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object>

11
আমাদের কেন `তালিকা <এর মতো একটি বাক্য লেখার অনুমতি দেওয়া হচ্ছে? সংখ্যা প্রসারিত করে> foo3 = নতুন অ্যারেলিস্ট <Integer> (); we যদি আমরা এই তালিকায় আরও একটি উপাদান না পারি?
অমিত কুমার গুপ্ত

7
@ আর্টিক্যাল স্ট্যাক: তালিকার সাথে যোগ করা কেবলমাত্র দরকারী জিনিস নয়। একবার একটি তালিকা পপুলেটে গেলে তালিকা থেকে পড়া কার্যকর হতে পারে। জেনেরিক ওয়াইল্ডকার্ডগুলি লিখিত কোডের জন্য মঞ্জুরি দেয় যা তালিকার পরিবারের জন্য সাধারণভাবে কাজ করে, উদাহরণস্বরূপ তালিকা <ইন্টিজার> বা তালিকা <ডাবল> উভয়ের পক্ষে কাজ করে। উদাহরণস্বরূপ, কালেকশন কপি () এর স্বাক্ষরটি দেখুন। src Listযুক্তি ব্যবহার extendssrc তালিকা থেকে পড়তে, যখন dest Listযুক্তি ব্যবহার superDEST লিস্টে লিখতে। এই এক পদ্ধতি যা থেকে কপি করতে পারেন List<Integer>বা List<Double>মধ্যে List<Number>অথবা List<Object>
বার্ট এফ

বার্ট এফ, দেরিতে মন্তব্যের জন্য দুঃখিত। আপনার প্যাসেজে কোনও টাইপো আছে, "টাইপের টি (বা টি এর উপক্লাস) যুক্ত করতে" পড়া উচিত (বা টি এর সুপারক্লাস)?
আবর্ত

হ্যাঁ, আমি এটি খুব দেখেছি @ ভার্টেক্স আমি নিশ্চিত না যে এটি সঠিক কিনা বা আমি এটি ভুল পড়েছি।
Ungeheuer

1
@ ভার্টেক্স - or subclass of Tসঠিক। উদাহরণস্বরূপ, আমি এতে একটি Object(সুপারক্লাস Number) যুক্ত করতে পারছি না List<? super Number> foo3কারণ foo3এটি বরাদ্দ করা List<? super Number> foo3 = new ArrayList<Number>হতে পারে : (যার মধ্যে কেবলমাত্র Numberবা সাবক্লাস থাকতে পারে Number)। <? super Number>ধরনের বোঝায় List<>যে নির্ধারিত করা যেতে পারে গুলি foo3না যে জিনিস যোগ করা যেতে পারে / পড়া তা থেকে ধরণের -। যে ধরণের জিনিসগুলি থেকে যুক্ত / সরানো যায় foo3সেগুলি অবশ্যই এমন জিনিস হতে পারে যা নির্ধারিত হতে পারে এমন যে কোনও ধরণের থেকে যুক্ত / সরানো List<>যেতে পারে foo3
বার্ট এফ

17

আপনি (অনিরাপদ জাল ছাড়া) পারবেন না। আপনি কেবল তাদের কাছ থেকে পড়তে পারেন।

সমস্যাটি হ'ল আপনি জানেন না যে তালিকার তালিকাটি হ'ল কী। এটি সংখ্যার যে কোনও সাবক্লাসের একটি তালিকা হতে পারে, সুতরাং আপনি যখন এটিতে কোনও উপাদান রাখার চেষ্টা করবেন তখন আপনি জানেন না যে উপাদানটি তালিকায় আসলে খাপ খায়।

উদাহরণস্বরূপ তালিকাটি গুলিগুলির একটি তালিকা হতে পারে Byte, সুতরাং এটিতে এটি রাখা একটি ত্রুটি Floatহবে।


2

"তালিকা '<'? সংখ্যাটি প্রসারিত> আসলে একটি উপরের বাউন্ড ওয়াইল্ডকার্ড!

উপরের সীমারেখাযুক্ত ওয়াইল্ডকার্ড বলছে যে নম্বর বা সংখ্যা নিজেই প্রসারিত যে কোনও শ্রেণিই আনুষ্ঠানিক প্যারামিটার ধরণ হিসাবে ব্যবহার করা যেতে পারে: সমস্যাটি জেমা থেকে জানে না যে লিস্টটি আসলে কী ধরণের তা আসলে জানেন না । এটি একটি নির্ভুল এবং অনন্য প্রকার হতে হবে। আমি আসা করি এটা সাহায্য করবে :)



1

আমি এখানে উত্তরগুলি পড়ার পরেও আমার কাছে বিভ্রান্তির সৃষ্টি হয়েছে, যতক্ষণ না পাভেল মিনায়েভের মন্তব্যটি পেয়েছি:

<লস্ট নোট করুন? প্রসারিত সংখ্যা> এর অর্থ হ'ল "বিভিন্ন ধরণের অবজেক্টের তালিকা, এর সবগুলিই সংখ্যা প্রসারিত করে"। এর অর্থ "একক ধরণের অবজেক্টের তালিকা যা সংখ্যা প্রসারিত করে"

এর পরে আমি বার্টএফের দুর্দান্ত ব্যাখ্যাটি বুঝতে সক্ষম হয়েছি। তালিকা <? সংখ্যা বৃদ্ধি মানে? কোন প্রকার ব্যাপ্ত নম্বর (পূর্ণসংখ্যা, ডাবল, ইত্যাদি) এবং হতে পারে তার clearified না ঘোষণায় (তালিকা <? নম্বর প্রসারিত> তালিকা) যে তাদের মধ্যে এটা, তাই যখন তোমার দর্শন লগ করা অ্যাড পদ্ধতি ব্যবহার ওয়ানা তার জানা যায় না যদি ইনপুট একই ধরণের বা না; টাইপ আসলে কি?

সুতরাং তালিকার উপাদানসমূহ <? সংখ্যা বাড়ায়> নির্মাণের সময় কেবল সেট করা যেতে পারে।

এটিও নোট করুন: আমরা যখন টেমপ্লেটগুলি ব্যবহার করি তখন আমরা কম্পাইলারকে বলি যে আমরা কী ধরণের সাথে গণ্ডগোল করছি। টি উদাহরণস্বরূপ আমাদের জন্য এই ধরণের ধারণ করে, কিন্তু না ? একই কাজ করে

আমি বলতে চাই .. এটি ব্যাখ্যা / শেখার নোংরাগুলির মধ্যে একটি


-1

যেখানে 'অবজেক্ট' থেকে তালিকা প্রসারিত করা যায়, আপনি list.add ব্যবহার করতে পারেন এবং যখন ব্যবহার করতে চান list.get কেবলমাত্র আপনার অবজেক্টে অবজেক্টটি কাস্ট করা প্রয়োজন;

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