'ই', 'টি' এবং '' এর মধ্যে পার্থক্য কী? জাভা জেনেরিকের জন্য?


261

আমি জাভা কোড জুড়ে এসেছি:

public interface Foo<E> {}

public interface Bar<T> {}

public interface Zar<?> {}

উপরোক্ত তিনটির মধ্যে পার্থক্য কী এবং তারা জাভাতে এই ধরণের শ্রেণি বা ইন্টারফেসের ঘোষণাকে কী বলে?


1
আমার সন্দেহ আছে যে সেখানে কোনও পার্থক্য আছে। আমি অনুমান করি যে এই ধরণের পরামিতিটির কেবল একটি নাম। এবং শেষটি কি বৈধ?
কোডসইনচওস

উত্তর:


231

ঠিক আছে প্রথম দুটির মধ্যে কোনও পার্থক্য নেই - তারা কেবলমাত্র পরামিতি ( Eবা T) টাইপের জন্য আলাদা আলাদা নাম ব্যবহার করছে ।

তৃতীয়টি বৈধ ঘোষণা নয় - ?একটি ওয়াইল্ডকার্ড হিসাবে ব্যবহৃত হয় যা কোনও প্রকারের যুক্তি সরবরাহ করার সময় ব্যবহৃত হয় , উদাহরণস্বরূপ এর List<?> foo = ...অর্থ এটি fooকোনও ধরণের একটি তালিকা বোঝায়, তবে আমরা কী জানি না।

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


1
দেখে মনে হচ্ছে পিডিএফটির লিঙ্কটি নষ্ট হয়ে গেছে। আমি এখানে অনুলিপি হিসাবে উপস্থিত হিসাবে খুঁজে পেয়েছি , তবে আমি 100% নির্দিষ্ট হতে পারছি না যেহেতু আমি জানি না যে আসলটি দেখতে কেমন।
জন

2
@ জন: হ্যাঁ, এটাই। এর মধ্যে একটি লিঙ্ক সম্পাদনা করবে, তা সে হোক না ও ওরাকল এক ...
জন স্কিটি

টি, ই এবং অন্য কিছু আছে কি? জেনেরিক ব্যবহার করা হয়? যদি তা হয় তবে তারা কী এবং তাদের অর্থ কী?
sofs1

1
@ সফস 1: এর জন্য বিশেষ কিছু নেই Tএবং E- তারা কেবল শনাক্তকারী। আপনি KeyValuePair<K, V>উদাহরণস্বরূপ লিখতে পারে । ?যদিও এর বিশেষ অর্থ রয়েছে।
জন স্কিটি

215

এটি অন্য যে কোনও কিছুর চেয়ে বেশি কনভেনশন।

  • T একটি টাইপ হতে বোঝানো হয়
  • Eএকটি উপাদান হিসাবে বোঝানো হয় ( List<E>: উপাদানগুলির একটি তালিকা)
  • Kকী (একটিতে Map<K,V>)
  • V মান (ফেরতের মান বা ম্যাপযুক্ত মান হিসাবে)

তারা সম্পূর্ণরূপে বিনিময়যোগ্য (তবুও একই ঘোষণায় দ্বন্দ্ব)।


20
<> এর মধ্যে বর্ণটি কেবল একটি নাম। আপনার উত্তরে আপনি যা বর্ণনা করছেন তা কেবল কনভেনশন are এমনকি এটি একটি একক, বড়-বড় অক্ষর হতে হবে না; আপনি নিজের পছন্দ মতো যে কোনও নাম ব্যবহার করতে পারেন, যেমন আপনি ক্লাস, ভেরিয়েবল ইত্যাদি দিতে পারেন আপনার পছন্দ মতো কোনও নাম দিন।
জেস্পার

আরও নিখুঁত এবং সুস্পষ্ট বর্ণনা এই নিবন্ধে পাওয়া যাবে oracle.com/technetwork/articles/java/…
fgul

6
আপনি প্রশ্ন চিহ্নটি ব্যাখ্যা করেন নি। Downvoted।
shinzou

129

পূর্ববর্তী উত্তরগুলি টাইপ প্যারামিটারগুলি (টি, ই, ইত্যাদি) ব্যাখ্যা করে তবে ওয়াইল্ডকার্ড, "?" বা তাদের মধ্যে পার্থক্য ব্যাখ্যা করে না, তাই আমি এটিকে সম্বোধন করব।

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

ওয়াইল্ডকার্ড সবসময় কোণ বন্ধনীগুলির মধ্যে আসে এবং এটি কেবল জেনেরিক ধরণের প্রসঙ্গে থাকে:

public void foo(List<?> listOfAnyType) {...}  // pass a List of any type

না

public <?> ? bar(? someType) {...}  // error. Must use type params here

অথবা

public class MyGeneric ? {      // error
    public ? getFoo() { ... }   // error
    ...
}

এটি আরও বিভ্রান্ত হয় যেখানে তারা ওভারল্যাপ করে। উদাহরণ স্বরূপ:

List<T> fooList;  // A list which will be of type T, when T is chosen.
                  // Requires T was defined above in this scope
List<?> barList;  // A list of some type, decided elsewhere. You can do
                  // this anywhere, no T required.

পদ্ধতির সংজ্ঞা দিয়ে কী সম্ভব তা নিয়ে প্রচুর ওভারল্যাপ রয়েছে। নিম্নলিখিতটি ক্রিয়ামূলকভাবে অভিন্ন:

public <T> void foo(List<T> listOfT) {...}
public void bar(List<?> listOfSomething)  {...}

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

টাইপ প্যারামে একাধিক বাউন্ডিং ক্লাস থাকতে পারে; ওয়াইল্ডকার্ড পারবেন না:

public class Foo <T extends Comparable<T> & Cloneable> {...}

ওয়াইল্ডকার্ডের নিম্ন সীমানা থাকতে পারে; টাইপ প্যারামগুলি:

public void bar(List<? super Integer> list) {...}

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

public void foo(List<? extends Number> numbers) {...}

আপনি একটি পাস করতে পারেন List<Integer>, List<Float>, List<Byte>, ইত্যাদি জন্য numbers। টাইপ বাউন্ডিং ছাড়া এটি কাজ করবে না - জেনারিকগুলি ঠিক এটি।

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

public static <T extends Number> void adder(T elem, List<? super Number> numberSuper) {
    numberSuper.add(elem);
}

numberSuperসংখ্যার একটি তালিকা বা কোনও সংখ্যার সুপার টাইপ (উদাঃ List<Object>) elemহতে পারে এবং অবশ্যই সংখ্যা বা কোনও উপ- টাইপ হতে হবে। সমস্ত .add()আবদ্ধকরণের সাথে, সংকলকটি নিশ্চিত হতে পারে যে এটি টাইপসেফ is


"সর্বজনীন শূন্য ফু (তালিকা <? সংখ্যা> সংখ্যাগুলি প্রসারিত করে) {...}" "বর্ধিত" "সুপার" হওয়া উচিত?
1a1a11a

1
না। উদাহরণটির মূল বিষয়টি এমন একটি স্বাক্ষর দেখানো যা বহুবিধভাবে সংখ্যার একটি তালিকা এবং সংখ্যার উপ-প্রকারকে সমর্থন করে। এই জন্য, আপনি "প্রসারিত" ব্যবহার করুন। অর্থাৎ, "আমাকে সংখ্যার একটি তালিকা বা নম্বর প্রসারিত যে কোনও কিছু পাস করুন " (তালিকা <Integer>, তালিকা <ফ্ল্যাট> যাই হোক না কেন)। এর মতো একটি পদ্ধতি তালিকার মাধ্যমে পুনরাবৃত্তি হতে পারে এবং প্রতিটি উপাদানগুলির জন্য, "e", এক্সিকিউট করে, যেমন, e.floatValue () ( আপনি সংখ্যার কী উপ-টাইপ (এক্সটেনশন) পাস করেন তা বিবেচ্য নয় - আপনি সর্বদা ".floatValue ()" করতে সক্ষম হবেন, কারণ .floatValue () সংখ্যার একটি পদ্ধতি।
হক্কে পার্কার

আপনার শেষ উদাহরণে, "তালিকা <? সুপার নম্বর>" কেবল "তালিকা <নাম্বার>" হতে পারে কারণ পদ্ধতিটি আরও সাধারণ কিছু দেয় না allow
জেসারাহ

@ জেসারাহ না। হতে পারে আমার উদাহরণটি অস্পষ্ট, তবে আমি উদাহরণে উল্লেখ করেছি যে অ্যাড্ডার () একটি তালিকা নিতে পারে <অবজেক্ট> (অবজেক্ট সংখ্যার একটি সুপারক্লাস)। আপনি যদি এটি এটি করতে সক্ষম হন তবে এটির "তালিকা <? সুপার নম্বর>" স্বাক্ষর থাকতে হবে must ঠিক এখানেই "সুপার" এর পয়েন্ট।
হক্কে পার্কার

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

27

একটি ধরণের ভেরিয়েবল, <T> আপনার নির্ধারিত যেকোন অ-আদিম প্রকার হতে পারে: যে কোনও শ্রেণির প্রকার, কোনও ইন্টারফেস প্রকার, যে কোনও অ্যারের প্রকার বা অন্য কোনও ধরণের ভেরিয়েবল।

সর্বাধিক ব্যবহৃত ধরণের পরামিতিগুলির নাম:

  • ই - উপাদান (জাভা সংগ্রহ ফ্রেমওয়ার্ক দ্বারা ব্যাপকভাবে ব্যবহৃত)
  • কে - কী
  • এন - সংখ্যা
  • টি - টাইপ
  • ভি - মান

জাভা 7 এ এটির মতো ইনস্ট্যান্ট করার অনুমতি রয়েছে:

Foo<String, Integer> foo = new Foo<>(); // Java 7
Foo<String, Integer> foo = new Foo<String, Integer>(); // Java 6

3

সর্বাধিক ব্যবহৃত ধরণের পরামিতিগুলির নাম:

E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types

আপনি জাভা এসই এপিআই জুড়ে ব্যবহৃত এই নামগুলি দেখতে পাবেন


2

সংকলক প্রতিটি ওয়াইল্ডকার্ডের জন্য একটি ক্যাপচার তৈরি করবে (উদাহরণস্বরূপ, তালিকায় প্রশ্ন চিহ্ন) যখন এটি কোনও ফাংশন করে:

foo(List<?> list) {
    list.put(list.get()) // ERROR: capture and Object are not identical type.
}

তবে ভি এর মতো জেনেরিক টাইপ ঠিক হয়ে যাবে এবং এটিকে একটি জেনেরিক পদ্ধতি তৈরি করা হবে :

<V>void foo(List<V> list) {
    list.put(list.get())
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.