জাভাতে জেনেরিক অ্যারে প্রকার তৈরি করতে না পারার কারণ কী?


273

জাভা আমাদের কী করতে দেয় না তার কারণ কী

private T[] elements = new T[initialCapacity];

আমি বুঝতে পারি। নেট আমাদেরকে এটি করতে দেয়নি, যেমন। নেট হিসাবে আপনার কাছে এমন মানের ধরণ রয়েছে যা রান-টাইমে বিভিন্ন আকারের হতে পারে, তবে জাভাতে সমস্ত ধরণের টি অবজেক্ট রেফারেন্স হবে, এইভাবে একই আকারের ( আমি ভুল হলে শুধরে).

কারণ কি?


29
আপনি কি বিষয়ে কথা হয়? আপনি নেট। নেট এ একেবারে করতে পারেন। - আমি এখানে জাভাতে কেন এটি করতে পারি না তা জানার চেষ্টা করছি।
BrainSlugs83

@ BrainSlugs83 - দয়া করে কিছু কোড উদাহরণ বা টিউটোরিয়ালের লিঙ্ক যুক্ত করুন যা এটি দেখায়।
মাস্টারজয়ে


1
@ মাস্টারজয়ে 2 ওপির প্রশ্নের উপরের কোডটি আমি কী উল্লেখ করছি। এটি সি # তে দুর্দান্ত কাজ করে তবে জাভাতে নয়। - প্রশ্নটি বলে যে এটি দুটিতেই কাজ করে না, যা ভুল। - এটি নিয়ে আরও আলোচনা করার কোনও মূল্য নেই তা নিশ্চিত।
BrainSlugs83

উত্তর:


204

এটি কারণ জাভার অ্যারেগুলিতে (জেনেরিকের বিপরীতে) রানটাইমগুলিতে এর উপাদানগুলির ধরণের তথ্য রয়েছে। সুতরাং অ্যারে তৈরি করার সময় আপনাকে অবশ্যই উপাদানটির প্রকারটি জানতে হবে। যেহেতু আপনি Tরানটাইম কী তা জানেন না তাই আপনি অ্যারে তৈরি করতে পারবেন না।


29
তবে ইরেজরের কী হবে? কেন এটি প্রযোজ্য নয়?
কিউস - মনিকা

14
তাহলে কীভাবে ArrayList <SomeType>এটি করা যায়?
থাম্বজ

10
@ থাম্বজ: মানে new ArrayList<SomeType>()? জেনেরিক টাইপগুলিতে রানটাইমে টাইপ প্যারামিটার থাকে না। টাইপ প্যারামিটার তৈরিতে ব্যবহৃত হয় না। সেখানে দ্বারা উত্পন্ন কোডে কোন পার্থক্য নেই new ArrayList<SomeType>()বা new ArrayList<String>()বা new ArrayList()এ সব।
নিউএ্যাক্যাক্ট ২

8
আমি এর ArrayList<T>সাথে কীভাবে কাজ করে সে সম্পর্কে আরও জিজ্ঞাসা করছিলাম private T[] myArray। কোডের কোথাও কোথাও এটির জেনেরিক প্রকার টি এর অ্যারে থাকতে হবে, তবে কীভাবে?
থাম্বজ

21
@ থম্বজ: এটিতে রানটাইম টাইপের কোনও অ্যারে নেই T[]। এটি রানটাইম টাইপের একটি অ্যারে রয়েছে Object[], এবং এর মধ্যে 1) সোর্স কোডটিতে একটি ভেরিয়েবল রয়েছে Object[](এটি সর্বশেষ ওরাকল জাভা উত্সে এটি কীভাবে হয়); বা 2) সোর্স কোডে টাইপের একটি পরিবর্তনশীল রয়েছে T[], যা মিথ্যা, তবে Tশ্রেণীর ক্ষেত্রের ভিতরে মুছে যাওয়ার কারণে সমস্যা সৃষ্টি করে না ।
নিউএ্যাক্যাক্ট

137

উদ্ধৃতি:

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

class Box<T> {
    final T x;
    Box(T x) {
        this.x = x;
    }
}

class Loophole {
    public static void main(String[] args) {
        Box<String>[] bsa = new Box<String>[3];
        Object[] oa = bsa;
        oa[0] = new Box<Integer>(3); // error not caught by array store check
        String s = bsa[0].x; // BOOM!
    }
}

বাঘের জন্য প্রত্যাখ্যান করা স্ট্যাটিকালি নিরাপদ অ্যারে (ওরফে ভারিয়েন্স) বুট ব্যবহার করে আমরা এই সমস্যাটি সমাধান করার প্রস্তাব দিয়েছিলাম।

- গিটার

(আমি বিশ্বাস করি এটি নিল গেরোটার , তবে নিশ্চিত নয়)

এটি এখানে প্রসঙ্গে দেখুন: http://forums.sun.com/thread.jspa?threadID=457033&forumID=316


3
মনে রাখবেন যে উত্তরটি আমার নয় বলেই আমি এটিকে সিডাব্লু করে দিয়েছি।
বার্ট কায়ার্স

10
এটি কেন টাইপসেফ না হতে পারে তা ব্যাখ্যা করে। তবে সুরক্ষার প্রকারের বিষয়গুলি সংকলক দ্বারা সতর্ক করতে পারে। আসল বিষয়টি হ'ল এটি করা সম্ভবও নয়, প্রায় একই কারণে আপনি করতে পারেন না কেন new T()। জাভাতে প্রতিটি অ্যারে, ডিজাইন অনুসারে এর T.classভিতরে উপাদান উপাদান (যেমন ) সঞ্চয় করে ; অতএব এই জাতীয় অ্যারে তৈরি করতে আপনার রান টাইমে টি ক্লাসের প্রয়োজন।
newacct

2
আপনি এখনও এটি ব্যবহার করতে পারেন new Box<?>[n]যা কখনও কখনও পর্যাপ্ত হতে পারে যদিও এটি আপনার উদাহরণে সহায়তা করে না।
বার্তোসক ক্লিমেক

1
@ বার্টকায়ার্স আমি এটি পেলাম না ... এটি এখনও সংকলন করে না (জাভা -8): Box<String>[] bsa = new Box<String>[3];জাভা -8 এবং এর কিছু পরিবর্তন হয়েছে কি আমি ধরে নিয়েছি?
ইউজিন

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

47

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

চারপাশের সাধারণ কাজগুলি নিম্নরূপ।

T[] ts = new T[n];

এর সাথে প্রতিস্থাপিত হয়েছে (ধরে নেওয়া টি অবজেক্টটি প্রসারিত করে অন্য শ্রেণীর নয়)

T[] ts = (T[]) new Object[n];

আমি প্রথম উদাহরণটি পছন্দ করি, তবে আরও একাডেমিক প্রকারগুলি দ্বিতীয়টিকে পছন্দ করে বলে মনে হয় বা কেবল এটি সম্পর্কে চিন্তা না করা পছন্দ করে।

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

দ্রষ্টব্য: সংগ্রহের পাঠাগার নিজেই সতর্কতা ছাড়াই সংকলন না করায় এটি একটি কারণ। যদি আপনি এই ব্যবহারের ক্ষেত্রে সতর্কতা ছাড়াই সমর্থন করতে না পারেন তবে কিছু জেনেরিক মডেল আইএমএইচওর সাথে মূলত ভেঙে গেছে।


6
দ্বিতীয়টি সম্পর্কে আপনাকে সাবধানতা অবলম্বন করতে হবে। যদি আপনি এমনভাবে তৈরি করা অ্যারেটি প্রত্যাশিত কারও কাছে ফিরে যান, বলুন, ক String[](বা আপনি যদি এটি এমন কোনও ক্ষেত্রে সংরক্ষণ করেন যা সর্বজনীনভাবে T[]প্রাপ্য access
newacct

4
আমি এই উত্তরটি নীচে ভোট দিয়েছি কারণ আপনার পছন্দের উদাহরণটি জাভাতে অনুমোদিত নয় এবং আপনার দ্বিতীয় উদাহরণটি ক্লাসকাস্ট এক্সেক্সশন ফেলতে পারে
জোসে রবার্তো আরাজো

5
@ জোসেরোবার্তোআরাজোজোয়ারিয়র এটি একেবারে পরিষ্কার যে প্রথম উদাহরণটি দ্বিতীয় উদাহরণের সাথে প্রতিস্থাপন করা দরকার। দ্বিতীয় উদাহরণটি কেন ক্লাসকাস্টএক্সসেপশন ফেলতে পারে তা ব্যাখ্যা করার জন্য এটি আপনার পক্ষে আরও সহায়ক হবে কারণ এটি সবার কাছে স্পষ্ট হবে না।
পিটার লরি

3
@PeterLawrey আমি একটি স্ব-উত্তরে প্রশ্ন দেখাচ্ছে কেন নির্মিত T[] ts = (T[]) new Object[n];: একটি খারাপ ধারণা stackoverflow.com/questions/21577493/...
হোসে রবার্তো Araujo জুনিয়র

1
@ মারকো টপলনিককে আমি ইতিমধ্যে বলেছি একই জিনিসটি ব্যাখ্যা করার জন্য আপনার সমস্ত মন্তব্যের জবাব দেওয়ার জন্য আমাকে একটি পদক দেওয়া উচিত, আমার মূল কারণ থেকে যে একমাত্র পরিবর্তন হয়েছিল তা হ'ল আমি যদিও তিনি বলেছিলেন যে T[] ts = new T[n];এটি একটি বৈধ উদাহরণ ছিল। আমি ভোটটি রাখব কারণ উনার উত্তরটি অন্যান্য দেবদেবীদের কাছে সমস্যা এবং বিভ্রান্তি সৃষ্টি করতে পারে এবং এটি বিষয়বস্তুও নয়। এছাড়াও, আমি এই সম্পর্কে মন্তব্য বন্ধ করব।
জোসে রবার্তো আরাজো জনিয়ার

38

অ্যারেগুলি কোভেরিয়েন্ট

অ্যারেগুলি সমবায়িক হিসাবে বলা হয় যার মূলত এর অর্থ যে, জাভা এর সাব-টাইপিং বিধিগুলি দেওয়া হলে টাইপের একটি অ্যারেতে টাইপের T[]উপাদান Tবা কোনও উপ- টাইপ থাকতে পারে T। এই ক্ষেত্রে

Number[] numbers = new Number[3];
numbers[0] = newInteger(10);
numbers[1] = newDouble(3.14);
numbers[2] = newByte(0);

কিন্তু না শুধুমাত্র জাভা রাজ্যের subtyping বিধি জারি করে যে একটি অ্যারের যে S[]অ্যারের একটি উপপ্রকার হয় T[]যদি Sএকটি উপপ্রকার হয় Tতাই ভালো কিছু এছাড়াও বৈধ:

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

কারণ জাভাতে সাব টাইপিং নিয়ম অনুসারে, একটি অ্যারে একটি অ্যারের Integer[]একটি উপপ্রকার, Number[]কারণ পূর্ণসংখ্যার সংখ্যার একটি উপ টাইপ pe

তবে এই সাব-টাইপিং নিয়মটি একটি আকর্ষণীয় প্রশ্নকে ডেকে আনতে পারে: আমরা যদি এটি করার চেষ্টা করি তবে কী হবে?

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

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

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

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

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

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

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

আসুন এখন নীচের অনিরাপদ কোডটি বিবেচনা করুন:

List<Integer> myInts = newArrayList<Integer>();
myInts.add(1);
myInts.add(2);
List<Number> myNums = myInts; //compiler error
myNums.add(3.14); //heap polution

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

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

যেমনটি, আমরা বলি যে জেনেরিক প্রকারগুলি পুনরায় সংশোধনযোগ্য নয়, যেহেতু রান সময়ে আমরা জেনেরিক ধরণের প্রকৃত প্রকৃতি নির্ধারণ করতে পারি না।

আমি এই উত্তরের কয়েকটি অংশ এড়িয়ে গেছি আপনি এখানে পুরো নিবন্ধটি পড়তে পারেন: https://dzone.com/articles/covariance- এবং- নিয়ন্ত্রণ


32

এটি অসম্ভব হওয়ার কারণটি হ'ল জাভা তার জেনারিকগুলি নির্ভুলভাবে সংকলক স্তরের উপর প্রয়োগ করে এবং প্রতিটি শ্রেণীর জন্য এখানে কেবল একটি শ্রেণির ফাইল উত্পন্ন হয়। একে টাইপ ইরেজোর বলা হয় ।

রানটাইম এ, সংকলিত বর্গকে তার সমস্ত ব্যবহার একই বাইকোডের সাথে পরিচালনা করতে হবে। সুতরাং, new T[capacity]কোন ধরণের ইনস্ট্যান্ট করা দরকার তা একেবারেই ধারণা নেই absolutely


17

উত্তরটি ইতিমধ্যে দেওয়া হয়েছিল তবে আপনার যদি ইতিমধ্যে টি এর একটি ইনস্ট্যান্স থাকে তবে আপনি এটি করতে পারেন:

T t; //Assuming you already have this object instantiated or given by parameter.
int length;
T[] ts = (T[]) Array.newInstance(t.getClass(), length);

আশা করি, আমি সাহায্য করতে পারি, ফেরডি ২265


1
এটি একটি দুর্দান্ত সমাধান। তবে এটি চেক না করা সতর্কতাগুলি (অবজেক্ট থেকে টি [] তে কাস্ট করা হবে)। আরেকটি "ধীর" কিন্তু "সতর্কবার্তা-মুক্ত" সমাধান হতে হবে: T[] ts = t.clone(); for (int i=0; i<ts.length; i++) ts[i] = null;
মিডনাইট

1
উপরন্তু, আমরা যা রেখেছি তা যদি হয় T[] tতবে তা হবে (T[]) Array.newInstance(t.getClass().getComponentType(), length);। আমি কিছু সময় ব্যয় করেছি getComponentType()। আশা করি এটি অন্যকে সহায়তা করবে।
মিডনাইট

1
@ মিডনাইট t.clone()ফিরে আসবে না T[]। কারণ tএই উত্তরে অ্যারে নয়।
xmen

6

মূল কারণটি জাভাতে অ্যারেগুলি কোভেরিয়েন্ট হওয়ার কারণে।

এখানে একটি ভাল ওভারভিউ আছে


আমি দেখতে পাচ্ছি না যে আপনি "নতুন টি [5]" এমনকি আক্রমণকারী অ্যারে দিয়ে কীভাবে সমর্থন করতে পারেন।
দিমিত্রিস আন্দ্রেউ

2
@ ডিমিত্রিসআন্দ্রিও ওয়েল, পুরো জিনিসটি জাভা ডিজাইনের ত্রুটিগুলির একটি কৌতুক। এটি সমস্ত অ্যারে কোভেরিয়েন্স দিয়ে শুরু হয়েছিল। তারপরে, একবার আপনার অ্যারে কোভেরিয়েন্স হয়ে গেলে আপনি এটিকে কাস্ট String[]করতে Objectএবং সঞ্চয় করতে পারেন Integer। সুতরাং তখন তাদের অ্যারে স্টোরগুলির জন্য রানটাইম টাইপ চেক যুক্ত করতে হয়েছিল ( ArrayStoreException) কারণ সমস্যাটি সংকলন-সময়ে ধরা পড়েনি। (অন্যথায়, Integerআসলে একটি আটকে যেতে পারে String[]এবং আপনি এটি পুনরুদ্ধার করার চেষ্টা করার সময় একটি ত্রুটি পাবেন, যা ভয়াবহ হবে)) ...
র‌্যাডন রোসবারো

2
@ ডিমিট্রিসআন্দ্রেউ ... তারপরে, একবার আপনি যখন খুব বেশি শোনার সংকলন-সময় চেকের জায়গায় একটি রানটাইম চেক স্থাপন করেন, আপনি মুছে ফেলা টাইপ করুন (একটি দুর্ভাগ্য ডিজাইনের ত্রুটি - কেবল পশ্চাদপদ সামঞ্জস্যের জন্য অন্তর্ভুক্ত)। প্রকার মুছে ফেলার অর্থ আপনি জেনেরিক ধরণের জন্য রানটাইম টাইপ চেক করতে পারবেন না । সুতরাং, অ্যারে স্টোরেজ ধরণের সমস্যা এড়াতে আপনার কেবল জেনেরিক অ্যারে থাকতে পারে না। যদি তারা প্রথমে অ্যারেগুলিকে আক্রমণকারী করে তোলে তবে আমরা ক্ষয়ের সমস্ত ঘটনা না চালিয়ে কেবল কম্পাইল-টাইম টাইপ চেকগুলি করতে পারি।
র‌্যাডন রোসবারো

… আমি মন্তব্যের জন্য পাঁচ মিনিটের সম্পাদনার সময় সন্ধান করেছি। Objectহওয়া উচিত ছিল Object[]আমার প্রথম মন্তব্যে।
রেডন রোসবারো

3

আমি উত্তর পরোক্ষভাবে প্রদত্ত পছন্দ Gafter । যাইহোক, আমি প্রস্তাব এটি ভুল। আমি গিটারের কোডটি একটু বদলেছি। এটি সংকলন করে এবং এটি কিছুক্ষণের জন্য ছুটে যায় তারপরে এটি বোমা ফাটিয়ে দেয় যেখানে গিটারের পূর্বাভাস করেছিল

class Box<T> {

    final T x;

    Box(T x) {
        this.x = x;
    }
}

class Loophole {

    public static <T> T[] array(final T... values) {
        return (values);
    }

    public static void main(String[] args) {

        Box<String> a = new Box("Hello");
        Box<String> b = new Box("World");
        Box<String> c = new Box("!!!!!!!!!!!");
        Box<String>[] bsa = array(a, b, c);
        System.out.println("I created an array of generics.");

        Object[] oa = bsa;
        oa[0] = new Box<Integer>(3);
        System.out.println("error not caught by array store check");

        try {
            String s = bsa[0].x;
        } catch (ClassCastException cause) {
            System.out.println("BOOM!");
            cause.printStackTrace();
        }
    }
}

আউটপুট হয়

I created an array of generics.
error not caught by array store check
BOOM!
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at Loophole.main(Box.java:26)

সুতরাং এটি আমার কাছে উপস্থিত হয়ে আপনি জাভাতে জেনেরিক অ্যারে প্রকার তৈরি করতে পারেন। আমি কি ভুল বুঝেছি?


আপনার উদাহরণটি আমি যা চেয়েছি তার চেয়ে আলাদা। আপনি যা বর্ণনা করেছেন তা হ'ল অ্যারে কোভেরিয়েন্সের বিপদ। এটি পরীক্ষা করে দেখুন (। নেট: ব্লগস.এমএসএনএন / বি / এরিক্লিপার্ট / অর্চিভ / ২০০7 /০ ////২ )
11:30 এ ইলিজিয়াম গ্রাস করেছে

আশা করি আপনি সংকলক থেকে টাইপ-সুরক্ষা সতর্কতা পেয়েছেন, হ্যাঁ?
ম্যাট ম্যাকহেনরি

1
হ্যাঁ, আমি একটি টাইপ-সুরক্ষা সতর্কতা পেয়েছি। হ্যাঁ, আমি দেখতে পাচ্ছি যে আমার উদাহরণটি প্রশ্নের প্রতিক্রিয়াশীল নয়।
এমুরি

আসলে আপনি a, b, c এর opিপি সূচনা করার কারণে একাধিক সতর্কতা পান। এছাড়াও, এটি সুপরিচিত এবং মূল গ্রন্থাগারকে প্রভাবিত করে, যেমন <T> java.util.Arrays.asList (টি ...)। আপনি যদি টি এর জন্য কোনও অ-পুনঃ-সংশোধনযোগ্য টাইপ পাস করেন তবে আপনি একটি সতর্কতা পেয়েছেন (কারণ তৈরি করা অ্যারেটির কোডের ভান করার চেয়ে কম সুনির্দিষ্ট টাইপ রয়েছে) এবং এটি অত্যন্ত কুৎসিত। এই পদ্ধতিটির লেখক যদি সতর্কতাটি পেয়ে থাকেন তবে ব্যবহারের সাইটে তা ছড়িয়ে দেওয়ার পরিবর্তে, যদি পদ্ধতিটি নিজেই নিরাপদ থাকে তবে এটি ব্যবহারকারীর কাছে অ্যারেটি প্রকাশ করে না।
দিমিত্রিস আন্দ্রেউ

1
আপনি এখানে জেনেরিক অ্যারে তৈরি করেন নি। সংকলকটি আপনার জন্য একটি (অ-জেনারিক) অ্যারে তৈরি করেছে।
newacct

2

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

আমি আমার নিজের লিঙ্কযুক্ত তালিকা তৈরি করার চেষ্টা করছি, সুতরাং নিম্নলিখিত কোডটি আমার পক্ষে কাজ করেছে:

package myList;
import java.lang.reflect.Array;

public class MyList<TYPE>  {

    private Node<TYPE> header = null;

    public void clear() {   header = null;  }

    public void add(TYPE t) {   header = new Node<TYPE>(t,header);    }

    public TYPE get(int position) {  return getNode(position).getObject();  }

    @SuppressWarnings("unchecked")
    public TYPE[] toArray() {       
        TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());        
        for(int i=0 ; i<size() ; i++)   result[i] = get(i); 
        return result;
    }


    public int size(){
         int i = 0;   
         Node<TYPE> current = header;
         while(current != null) {   
           current = current.getNext();
           i++;
        }
        return i;
    }  

ToArray () পদ্ধতিতে আমার জন্য জেনেরিক ধরণের অ্যারে তৈরির উপায় রয়েছে:

TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());    

2

আমার ক্ষেত্রে, আমি কেবল স্ট্যাকের একটি অ্যারে চেয়েছিলাম, এরকম কিছু:

Stack<SomeType>[] stacks = new Stack<SomeType>[2];

যেহেতু এটি সম্ভব ছিল না, তাই আমি নিম্নলিখিতটি একটি কাজের হিসাবে ব্যবহার করেছি:

  1. স্ট্যাকের চারপাশে একটি অ-জেনেরিক মোড়কের ক্লাস তৈরি করেছে (মাইস্ট্যাক বলুন)
  2. মাইস্ট্যাক [] স্ট্যাকস = নতুন মাইস্ট্যাক [2] পুরোপুরি ভালভাবে কাজ করেছে

কুরুচিপূর্ণ, তবে জাভা খুশি।

দ্রষ্টব্য: প্রশ্নের মন্তব্যে BrainSlugs83 দ্বারা উল্লিখিত হিসাবে .NET এ জেনেরিকের অ্যারে রাখা সম্পূর্ণ সম্ভব


2

ওরাকল টিউটোরিয়াল থেকে :

আপনি প্যারামিটারাইজড ধরণের অ্যারে তৈরি করতে পারবেন না। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি সংকলন করে না:

List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error

নিম্নলিখিত ধরণের কোডটি ব্যাখ্যা করে যখন বিভিন্ন ধরণের অ্যারেতে প্রবেশ করা হয় তখন কী ঘটে:

Object[] strings = new String[2];
strings[0] = "hi";   // OK
strings[1] = 100;    // An ArrayStoreException is thrown.

আপনি যদি জেনেরিক তালিকার সাথে একই জিনিস ব্যবহার করে থাকেন তবে সমস্যা হবে:

Object[] stringLists = new List<String>[];  // compiler error, but pretend it's allowed
stringLists[0] = new ArrayList<String>();   // OK
stringLists[1] = new ArrayList<Integer>();  // An ArrayStoreException should be thrown,
                                            // but the runtime can't detect it.

যদি প্যারামিটারাইজড তালিকার অ্যারেগুলিকে অনুমতি দেওয়া হয় তবে পূর্ববর্তী কোড পছন্দসই অ্যারেস্টোরএক্সসেপশন ফেলতে ব্যর্থ হবে।

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


0

অবশ্যই এটির চারপাশে অবশ্যই একটি ভাল উপায় থাকতে পারে (সম্ভবত প্রতিচ্ছবি ব্যবহার করে), কারণ আমার কাছে মনে হয় ঠিক এটি ArrayList.toArray(T[] a)ঘটে। আমি উদ্ধৃতি:

public <T> T[] toArray(T[] a)

সঠিক তালিকায় এই তালিকার সমস্ত উপাদানযুক্ত একটি অ্যারে প্রদান করে; প্রত্যাবর্তিত অ্যারের রানটাইম ধরণটি নির্দিষ্ট অ্যারে হয়। তালিকাটি যদি নির্দিষ্ট অ্যারে অনুসারে ফিট করে তবে তা এতে ফিরে আসে। অন্যথায়, নির্দিষ্ট অ্যারের রানটাইম ধরণের এবং এই তালিকার আকারের সাথে একটি নতুন অ্যারে বরাদ্দ করা হয়।

সুতরাং এটির চারপাশের একটি উপায় হ'ল এই ফাংশনটি ব্যবহার করা অর্থাৎ ArrayListঅ্যারেতে আপনি চান এমন একটি বস্তু তৈরি করুন , তারপরে ব্যবহার করুনtoArray(T[] a) তা তৈরি করুন আসল অ্যারে তৈরি করতে । এটি দ্রুত হবে না, তবে আপনি নিজের প্রয়োজনীয়তা উল্লেখ করেননি।

সুতরাং কেউ কীভাবে toArray(T[] a)বাস্তবায়িত হয় জানেন ?


3
তালিকা.আটোআরে (টি []) কাজ করে কারণ আপনি মূলত রানটাইমগুলিতে এটি উপাদান উপাদান টি দিচ্ছেন (আপনি এটি পছন্দসই অ্যারে টাইপের একটি উদাহরণ দিচ্ছেন, যা থেকে এটি অ্যারে শ্রেণি পেতে পারে এবং তারপরে, উপাদান উপাদান টি )। রানটাইমে প্রকৃত উপাদান টাইপের সাথে, আপনি সর্বদা ব্যবহার করে সেই রানটাইম টাইপের একটি অ্যারে তৈরি করতে পারেন Array.newInstance()। আপনি অনেক প্রশ্নের মধ্যে উল্লিখিত এটি দেখতে পাবেন যা সংকলনের সময় অজানা টাইপের সাহায্যে অ্যারে তৈরি করতে জিজ্ঞাসা করে। তবে ওপি বিশেষত জিজ্ঞাসা করছিল আপনি কেনnew T[] সিনট্যাক্সটি ব্যবহার করতে পারবেন না , যা একটি আলাদা প্রশ্ন
নতুনচ্যাক্ট

0

জেনেরিকগুলি তৈরি করার পরে এটি জাভাতে যুক্ত করা হয়েছিল কারণ এটির ধরণের জটিলতা কারণ জাভাটির মূল নির্মাতারা ভেবেছিলেন যে কোনও অ্যারে তৈরি করার সময় এটি তৈরির ক্ষেত্রে ধরণটি নির্দিষ্ট করা হবে। সুতরাং এটি জেনেরিকের সাথে কাজ করে না তাই আপনাকে E [] অ্যারে = (ই []) নতুন অবজেক্ট [15] করতে হবে; এটি সংকলন করে তবে এটি একটি সতর্কতা দেয়।


0

আমরা যদি জেনেরিক অ্যারেগুলি ইনস্ট্যান্ট করতে না পারি, তবে ভাষাতে জেনেরিক অ্যারে প্রকারগুলি কেন থাকে? বস্তুবিহীন একধরণের কী লাভ?

একমাত্র কারণটি আমি ভাবতে পারি, তা হ'ল ভারারাগস - foo(T...)। অন্যথায় তারা জেনেরিক অ্যারের ধরণগুলি পুরোপুরি স্ক্র্যাব করতে পারত। (ঠিক আছে, তাদের ভারার্গগুলির জন্য সত্যই অ্যারে ব্যবহার করতে হয়নি, যেহেতু 1.5 এর আগে ভারার্গস বিদ্যমান ছিল না That's সম্ভবত এটি অন্য একটি ভুল))

সুতরাং এটি একটি মিথ্যা, আপনি পারেন জেনেরিক অ্যারেগুলি ইনস্ট্যান্ট , ভারার্গসের মাধ্যমে!

অবশ্যই, জেনেরিক অ্যারেগুলির সমস্যাগুলি এখনও বাস্তব, যেমন

static <T> T[] foo(T... args){
    return args;
}
static <T> T[] foo2(T a1, T a2){
    return foo(a1, a2);
}

public static void main(String[] args){
    String[] x2 = foo2("a", "b"); // heap pollution!
}

আমরা জেনেরিক অ্যারের বিপদটি প্রকৃতপক্ষে প্রদর্শনের জন্য এই উদাহরণটি ব্যবহার করতে পারি ।

অন্যদিকে, আমরা এক দশক ধরে জেনেরিক ভ্যারাগগুলি ব্যবহার করে আসছি এবং আকাশ এখনও পড়ছে না। সুতরাং আমরা তর্ক করতে পারি যে সমস্যাগুলি অত্যুক্তি করা হচ্ছে; এটি একটি বড় চুক্তি হয় না. যদি সুস্পষ্ট জেনেরিক অ্যারে তৈরির অনুমতি দেওয়া হয় তবে আমাদের এখানে এবং সেখানে বাগ রয়েছে; তবে আমরা মুছে ফেলার সমস্যায় অভ্যস্ত হয়েছি এবং আমরা এটি নিয়ে বেঁচে থাকতে পারি।

এবং আমরা foo2দাবিটি খণ্ডন করতে ইঙ্গিত করতে পারি যে অনুমানটি আমাদের যে সমস্যা থেকে বিরত রাখে বলে দাবি করে সেগুলি থেকে আমাদের দূরে রাখে। তাহলে সূর্যের জন্য আরো সময় এবং সম্পদ ছিল 1.5 , আমি বিশ্বাস করি তারা আরো একটি পরিতৃপ্ত রেজল্যুশন পৌঁছেছেন পারে।


0

অন্যরা ইতিমধ্যে উল্লিখিত হিসাবে, আপনি অবশ্যই কিছু কৌশল দ্বারা তৈরি করতে পারেন ।

তবে এটি প্রস্তাবিত নয়।

কারণ মুছে ফেলা টাইপ এবং আরও গুরুত্বপূর্ণভাবে covarianceকেবল অ্যারে যা কেবলমাত্র একটি সাব টাইপ অ্যারেকে সুপারপাইপ অ্যারে নির্ধারিত করতে পারে, যা আপনাকে রান টাইমের মান ফিরিয়ে আনার চেষ্টা করার সময় স্বচ্ছ টাইপের কাস্ট ব্যবহার করতে বাধ্য করে ClassCastExceptionযা মূল উদ্দেশ্যগুলির মধ্যে একটি is যে জেনেরিকগুলি মুছে ফেলার চেষ্টা করে: সংকলনের সময় শক্তিশালী ধরণের চেক

Object[] stringArray = { "hi", "me" };
stringArray[1] = 1;
String aString = (String) stringArray[1]; // boom! the TypeCastException

কার্যকর জাভা: আইটেম 25 এ আরও একটি সরাসরি উদাহরণ পাওয়া যাবে ।


কোভেরিয়েন্স : এস এর টাইপ [[] এর অ্যারে টি টির একটি উপপ্রকার, যদি এস টি টির একটি উপপ্রকার হয়


0

ক্লাসটি যদি প্যারামিটারাইজড টাইপ হিসাবে ব্যবহার করে তবে এটি টি [T] টাইপের অ্যারে ঘোষণা করতে পারে তবে এটি সরাসরি এই ধরণের অ্যারে ইনস্ট্যান্ট করতে পারে না। পরিবর্তে, একটি সাধারণ পদ্ধতি হ'ল অবজেক্ট [] টাইপের একটি অ্যারে ইনস্ট্যান্ট করা এবং তারপরে টি []] টাইপ করার জন্য সংকীর্ণ কাস্ট তৈরি করা, যা নিম্নলিখিত হিসাবে দেখানো হয়েছে:

  public class Portfolio<T> {
  T[] data;
 public Portfolio(int capacity) {
   data = new T[capacity];                 // illegal; compiler error
   data = (T[]) new Object[capacity];      // legal, but compiler warning
 }
 public T get(int index) { return data[index]; }
 public void set(int index, T element) { data[index] = element; }
}

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