তালিকা, তালিকা <?>, তালিকা <T>, তালিকা <E>, এবং তালিকা <অবজেক্ট> এর মধ্যে পার্থক্য


194

মধ্যে পার্থক্য কি কি List, List<?>, List<T>, List<E>, এবং List<Object>?

1. তালিকা

List: এটি একটি কাঁচা টাইপ, অতএব নয় typesafe। কাস্টিং খারাপ হলে এটি কেবল রানটাইম ত্রুটি তৈরি করবে। কাস্ট খারাপ হলে আমরা একটি সংকলন সময় ত্রুটি চাই। ব্যবহার করার জন্য প্রস্তাবিত নয়।

2. তালিকা <?>

List<?>আনবাউন্ডেড ওয়াইল্ডকার্ড is তবে আমি নিশ্চিত নই এটি কিসের জন্য? আমি List<?>ইস্যু ছাড়াই মুদ্রণ করতে পারি :

public static void test(List<?> list){
    System.out.println(list);   // Works
}

আমি কেন আইটেম যুক্ত করতে পারি না List<?>?

public static void test(List<?> list){
    list.add(new Long(2));     // Error
    list.add("2");             // Error
    System.out.println(list);
}

3. তালিকা <টি>

public static void test(List<T> list){   // T cannot be resolved
    System.out.println(list);
}

আমি এই বাক্যবিন্যাস বুঝতে পারি না। আমি এরকম কিছু দেখেছি এবং এটি কাজ করে:

public <T> T[] toArray(T[] a){
    return a;   
}

কখনও কখনও, আমি দেখতে <T>, বা <E>, বা <U>, <T,E>। এগুলি কি সব একই বা তারা আলাদা কিছু উপস্থাপন করে?

4. তালিকা <অবজেক্ট>

এটি ত্রুটিটি দেয় " test(List<Object>)তর্কটির জন্য পদ্ধতিটি প্রযোজ্য নয় List<String>":

public static void test(List<Object> list){
    System.out.println(list);
}

যদি আমি এই তারপর চেষ্টা আমি পেয়েছিলাম "থেকে নিক্ষেপ করা যাবে না List<String>করার List<Object>":

test((List<Object>) names);

আমি দ্বিধান্বিত. Stringএকটি সাবক্লাস হয় Object, তাহলে কেন List<String>একটি সাবক্লাস নয় List<Object>?

উত্তর:


77

1) সঠিক

২) আপনি সেইটিকে "কেবল পঠনযোগ্য" তালিকা হিসাবে ভাবতে পারেন, যেখানে আপনি আইটেমগুলির ধরণের বিষয়ে চিন্তা করেন না eg উদাহরণস্বরূপ তালিকার দৈর্ঘ্য ফিরিয়ে দেওয়ার পদ্ধতি ব্যবহার করুন used

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

4) আপনি কমলা এবং আপেল মিশ্রিত করতে পারবেন না। আপনি যদি স্ট্রিং তালিকার এমন কোনও পদ্ধতিতে পাস করতে পারেন যা অবজেক্ট তালিকার প্রত্যাশা করে তবে আপনি আপনার স্ট্রিং তালিকায় একটি অবজেক্ট যুক্ত করতে সক্ষম হবেন। (এবং সমস্ত বস্তু স্ট্রিং নয়)


2
কেবলমাত্র পঠিত তালিকার জন্য +1 2। এটিকে প্রদর্শনের জন্য আমি কিছু কোড লিখি 2। tyvm
থাং ফাম

লোকেরা কেন ব্যবহার করবে List<Object>?
থাং ফাম

3
এটি এমন একটি তালিকা তৈরির উপায় যা কোনও ধরণের আইটেম গ্রহণ করে, আপনি খুব কমই এটি ব্যবহার করেন।
কাজ

আসলে আমি মনে করি না যে এখনই আপনার কোনও পরিচয়দানকারী না থাকতে পারে বলে কেউ এটিকে ব্যবহার করবে।
if_zero_equals_one

1
@if_zero_equals_one হ্যাঁ, তবে আপনি তখন একটি সংকলক সতর্কতা পেয়ে যাবেন (এটি সতর্ক করে বলবে যে আপনি কাঁচা ধরণের ব্যবহার করছেন) এবং আপনি কখনও সতর্কতা সহ আপনার কোডটি সংকলন করতে চান না।
কাজ

26

শেষ অংশের জন্য: স্ট্রিং যদিও অবজেক্টের একটি উপসেট, তবে তালিকা <স্ট্রিং> তালিকা <ওজেক্ট> থেকে উত্তরাধিকার সূত্রে প্রাপ্ত নয়।


11
খুব ভাল পয়েন্ট; অনেকে ধরে নেন যে ক্লাস সি ক্লাস পি থেকে উত্তরাধিকার সূত্রে, সেই তালিকা <সি> তালিকা <পি> থেকেও উত্তরাধিকার সূত্রে প্রাপ্ত। আপনি যেমন উল্লেখ করেছেন এটি ক্ষেত্রে নয়। কারণটি হ'ল যদি আমরা তালিকা <স্ট্রিং> থেকে তালিকা <অবজেক্ট> এ কাস্ট করতে পারি, তবে আমরা উপাদানগুলিকে সেই তালিকায় রাখতে পারি, সুতরাং উপাদানটি পুনরুদ্ধারের চেষ্টা করার সময় তালিকা <স্ট্রিং> এর মূল চুক্তি লঙ্ঘন করে।
পিটার

2
+1 টি। পাশাপাশি ভাল পয়েন্ট। তাহলে লোকেরা কেন ব্যবহার করবে List<Object>?
থাং ফাম

9
তালিকা << বিষয়> বিভিন্ন শ্রেণীর অবজেক্টের একটি তালিকা সঞ্চয় করতে ব্যবহার করা যেতে পারে।
ফারশিদ যাকের

20

স্বরলিপিটির List<?>অর্থ "কোনও কিছুর একটি তালিকা (তবে আমি কী বলছি না)"। যেহেতু কোড testতালিকার যে কোনও ধরণের অবজেক্টের জন্য কাজ করে, এটি একটি আনুষ্ঠানিক পদ্ধতি প্যারামিটার হিসাবে কাজ করে।

কোনও প্রকারের প্যারামিটার ব্যবহার করার জন্য (আপনার পয়েন্ট 3 এর মতো), টাইপ প্যারামিটারটি ঘোষণা করা দরকার। তার জন্য জাভা সিনট্যাক্সটি <T>ফাংশনের সামনে রাখা হয়। পদ্ধতির শরীরে নামগুলি ব্যবহার করার আগে এটি কোনও পদ্ধতিতে আনুষ্ঠানিক প্যারামিটারের নামগুলি ঘোষণার সাথে হুবহু মিল।

List<Object>একটি গ্রহণ না করার বিষয়ে List<String>, এটি বোঝায় যে কারণ Stringএটি নয় Object; এটি একটি সাবক্লাস Object। স্থির ঘোষণা করা হয় public static void test(List<? extends Object> set) ...। তবে তারপরেই extends Objectতা অনর্থক, কারণ প্রত্যেকে প্রত্যক্ষ বা পরোক্ষভাবে প্রতিটি শ্রেণি প্রসারিত হয় Object


লোকেরা কেন ব্যবহার করবে List<Object>?
থাং ফাম

10
আমি মনে করি "কোনও List<?>কিছুর একটি তালিকা" এর জন্য আরও ভাল অর্থ, যেহেতু তালিকাটি কিছু নির্দিষ্ট তবে অজানা ধরণের। List<Object>সত্যই এটি "যে কোনও কিছুর একটি তালিকা" হবে কারণ এটি আসলে কিছু থাকতে পারে।
কলিনড

1
@ কলিনডি - আমি "যে কোনও একটি জিনিস" অর্থে "কিছু" বোঝাতে চাইছি। তবে আপনি ঠিক বলেছেন; এর অর্থ, "কোনও কিছুর একটি তালিকা, তবে আমি আপনাকে কী বলব না"।
টেড হপ

@ কলিন্ড এর অর্থ তিনি কেন তাঁর কথার পুনরাবৃত্তি করলেন? হ্যাঁ এটি একটু ভিন্ন শব্দ দিয়ে লেখা হয়েছিল, তবে অর্থটি একই ...
ব্যবহারকার 25

14

আপনি যে কারণে কাস্ট করতে পারবেন না List<String>তা List<Object>হ'ল এটি আপনাকে প্রতিবন্ধকতাগুলির লঙ্ঘন করার অনুমতি দেয় List<String>

নিম্নলিখিত পরিস্থিতিটি সম্পর্কে ভাবুন: আমার যদি List<String>এটি থাকে তবে এটিতে কেবল ধরণের জিনিস থাকতে পারে বলে মনে করা হয় String। (যা একটি finalশ্রেণি)

যদি আমি এটিকে কাস্ট করতে পারি List<Object>, তবে এটি আমাকে Objectসেই তালিকায় যুক্ত করতে দেয় , সুতরাং এর মূল চুক্তি লঙ্ঘন করে List<String>

সুতরাং, সাধারণভাবে, শ্রেণি বর্গ Cথেকে উত্তরাধিকার সূত্রে হয় P, আপনি GenericType<C>এটি উত্তরাধিকার সূত্রেও বলতে পারবেন না GenericType<P>

এনবি আমি ইতিমধ্যে পূর্বের উত্তরে এই বিষয়ে মন্তব্য করেছি তবে এটিতে আরও প্রসারিত করতে চেয়েছিলাম।


ভাল, আমি আপনার মন্তব্য এবং আপনার উত্তর উভয়ই আপলোড করি, কারণ এটি খুব ভাল ব্যাখ্যা। এখন লোকেরা কোথায় এবং কেন ব্যবহার করবে List<Object>?
থাং ফাম

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

5

আমি জাভা পাজলার পড়ার পরামর্শ দেব। এটি উত্তরাধিকার, জেনেরিক্স, বিমূর্তি এবং ওয়াইল্ডকার্ডগুলি খুব ভাল ঘোষণায় ব্যাখ্যা করে। http://www.javapuzzlers.com/


5

আসুন জাভা ইতিহাসের প্রসঙ্গে তাদের সম্পর্কে কথা বলি;

  1. List:

তালিকার অর্থ এটি যে কোনও অবজেক্টকে অন্তর্ভুক্ত করতে পারে। জাভা 5.0 এর আগে তালিকা প্রকাশে ছিল; পিছনে সামঞ্জস্যের জন্য জাভা 5.0 তালিকা চালু করেছে।

List list=new  ArrayList();
list.add(anyObject);
  1. List<?>:

?অর্থ অজানা কোনও বস্তু নয়; ওয়াইল্ডকার্ড ?ভূমিকা জেনেরিক টাইপ দ্বারা নির্মিত সমস্যা সমাধানের জন্য; দেখতে ওয়াইল্ডকার্ড ; তবে এটি আরও একটি সমস্যা সৃষ্টি করে:

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
  1. List< T> List< E>

আপনার প্রকল্প লিবে কোনও টি বা ই টাইপ নয় এর ভিত্তিতে জেনেরিক ঘোষণা la

  1. List< Object> জেনেরিক পরামিতি মানে।

5

আপনার তৃতীয় বিন্দুতে, "টি" সমাধান করা যাচ্ছে না কারণ এটি ঘোষিত হয়নি, সাধারণত আপনি যখন জেনেরিক শ্রেণি ঘোষণা করেন তখন আপনি "টি" বাউন্ড টাইপ প্যারামিটারের নাম হিসাবে ব্যবহার করতে পারেন , ওরাকেলের টিউটোরিয়াল সহ অনেক অনলাইন উদাহরণ "টি" হিসাবে ব্যবহার করে টাইপ প্যারামিটারের নাম, উদাহরণস্বরূপ বলুন, আপনি যেমন শ্রেণি ঘোষণা করেন:

public class FooHandler<T>
{
   public void operateOnFoo(T foo) { /*some foo handling code here*/}

}

আপনি বলছেন যে FooHandler's operateOnFooপদ্ধতিটি "টি" টাইপের একটি পরিবর্তনশীল প্রত্যাশা করে যা ক্লাস ঘোষণায় নিজেই ঘোষিত হয়, এটি মাথায় রেখে আপনি পরে অন্য পদ্ধতি যুক্ত করতে পারেন

public void operateOnFoos(List<T> foos)

সমস্ত ক্ষেত্রে T, E বা U সেখানে টাইপ প্যারামিটারের সমস্ত সনাক্তকারী রয়েছে, আপনার একাধিক ধরণের পরামিতি থাকতে পারে যা সিনট্যাক্স ব্যবহার করে

public class MyClass<Atype,AnotherType> {}

আপনার সামনের পনিন্টে যদিও কার্যকরভাবে স্টিং একটি সাব-অবজেক্টের অবজেক্ট, জেনেরিক ক্লাসে এ জাতীয় কোনও সম্পর্ক নেই, সেগুলির List<String>একটি সাব টাইপ নয় List<Object>তারা সংকলক দৃষ্টিকোণ থেকে দুটি ডিফেরেন্ট প্রকার, এটি এই ব্লগের এন্ট্রিতে সবচেয়ে ভাল ব্যাখ্যা করা হয়েছে


5

তত্ত্ব

String[] নিক্ষেপ করা যেতে পারে Object[]

কিন্তু

List<String>কাস্ট করা যাবে না List<Object>

অনুশীলন করা

তালিকার জন্য এটি এর চেয়ে সূক্ষ্ম, কারণ সংকলন সময়ে কোনও পদ্ধতিতে তালিকা পরামিতি প্রেরণ করা হয় তা পরীক্ষা করা হয় না। পদ্ধতির সংজ্ঞা পাশাপাশি বলতে পারে List<?>- সংকলকের দৃষ্টিকোণ থেকে এটি সমতুল্য। এই কারণেই ওপির উদাহরণ # 2 রানটাইম ত্রুটিগুলি সঙ্কলন করে না gives

যদি আপনি List<Object>কোনও পদ্ধতিতে পাস করা কোনও প্যারামিটারটি যত্ন সহকারে পরিচালনা করেন তবে আপনি তালিকার কোনও উপাদানটিতে কোনও প্রকারের পরীক্ষা করতে বাধ্য করবেন না, তবে আপনি নিজের পদ্ধতিটি ব্যবহার করে সংজ্ঞায়িত করতে পারেন তবে কলিং কোড থেকে List<Object>কোনও List<String>পরামিতি গ্রহণ করবেন ।

উ: সুতরাং এই কোডটি সংকলন বা রানটাইম ত্রুটিগুলি দেবে না এবং বাস্তবে (এবং সম্ভবত আশ্চর্যরকম?) কাজ করবে:

public static void main(String[] args) {
    List argsList = new ArrayList<String>();
    argsList.addAll(Arrays.asList(args));
    test(argsList);  // The object passed here is a List<String>
}

public static void test(List<Object> set) {
    List<Object> params = new ArrayList<>();  // This is a List<Object>
    params.addAll(set);       // Each String in set can be added to List<Object>
    params.add(new Long(2));  // A Long can be added to List<Object>
    System.out.println(params);
}

বি। এই কোডটি একটি রানটাইম ত্রুটি দেবে:

public static void main(String[] args) {
    List argsList = new ArrayList<String>();
    argsList.addAll(Arrays.asList(args));
    test1(argsList);
    test2(argsList);
}

public static void test1(List<Object> set) {
    List<Object> params = set;  // Surprise!  Runtime error
}

public static void test2(List<Object> set) {
    set.add(new Long(2));       // Also a runtime error
}

সি। এই কোডটি একটি রানটাইম ত্রুটি দেবে ( java.lang.ArrayStoreException: java.util.Collections$UnmodifiableRandomAccessList Object[]):

public static void main(String[] args) {
    test(args);
}

public static void test(Object[] set) {
    Object[] params = set;    // This is OK even at runtime
    params[0] = new Long(2);  // Surprise!  Runtime error
}

বিতে, সংকলনের সময় প্যারামিটারটি setটাইপ Listকরা হয় না : সংকলক এটি হিসাবে দেখায় List<?>। একটি রানটাইম ত্রুটি রয়েছে কারণ রানটাইমের সময়, setআসল বস্তুটি পাস হয়ে যায় main()এবং এটি একটি List<String>। এ-তে List<String>কাস্ট করা যাবে না List<Object>

সি তে, প্যারামিটারটির setএকটি প্রয়োজন Object[]String[]প্যারামিটার হিসাবে যখন কোনও অবজেক্টের সাথে ডাকা হয় তখন কোনও সংকলন ত্রুটি এবং কোনও রানটাইম ত্রুটি নেই । কারণ String[]কাস্ট Object[]। তবে প্রাপ্ত প্রকৃত অবজেক্টটি test()একটি String[], এটি পরিবর্তিত হয়নি didn't সুতরাং paramsবস্তুটিও একটি হয়ে যায় String[]। এবং এর 0 এর এলিমেন্টকে একটি String[]বরাদ্দ করা যায় না Long!

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


এটা আমি তোমার উদাহরণ হচ্ছে চেষ্টা করেছি না কাজ: List<Object> cannot be applied to List<String>। আপনি এমন পদ্ধতিতে পাস করতে পারবেন নাArrayList<String> যা প্রত্যাশা করে ArrayList<Object>
পার্সসার

ধন্যবাদ, বরং তারিখের শেষের দিকে আমি এটিকে টুইট করলাম যাতে এটি এখন কাজ করে। মূল পরিবর্তনটি ছিল মূল () এ সাধারণভাবে আরগলিস্টগুলি সংজ্ঞায়িত করা।
রেডফেজ

4

সমস্যা 2 ঠিক আছে, কারণ "System.out.println (সেট);" মানে "System.out.println (set.toString ());" সেটটি তালিকার একটি উদাহরণ, সুতরাং সংযোজনকারীরা তালিকাকে কল করবে। স্ট্রিং ();

public static void test(List<?> set){
set.add(new Long(2)); //--> Error  
set.add("2");    //--> Error
System.out.println(set);
} 
Element ? will not promise Long and String, so complier will  not accept Long and String Object

public static void test(List<String> set){
set.add(new Long(2)); //--> Error
set.add("2");    //--> Work
System.out.println(set);
}
Element String promise it a String, so complier will accept String Object

সমস্যা 3: এই চিহ্নগুলি একই, তবে আপনি তাদের আলাদা আলাদা স্পেসিফিকেশন দিতে পারেন। উদাহরণ স্বরূপ:

public <T extends Integer,E extends String> void p(T t, E e) {}

সমস্যা 4: সংগ্রহ প্যারামিটার covariance প্রকারের অনুমতি দেয় না। কিন্তু অ্যারে covariance অনুমতি দেয়।


0

আপনি ঠিক বলেছেন: স্ট্রিং অবজেক্টের একটি উপসেট। স্ট্রিং যেহেতু অবজেক্টের চেয়ে "সুনির্দিষ্ট" তাই আপনার এটি এটিকে System.out.println () এর আর্গুমেন্ট হিসাবে ব্যবহার করার জন্য নিক্ষেপ করা উচিত।

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