java - অ্যারেলিস্ট. টু অ্যারে জাভা জেনারিকস()



arrays generics (6)

আমি করতে পারি এবং মাঝে মাঝে অ্যারে তৈরি করার পরিবর্তে একটি আইট্রেটর ব্যবহার করব তবে এটি আমার কাছে সর্বদা অদ্ভুত বলে মনে হয়েছিল। কেন (এক্স) পদ্ধতিটি জানে যে এটি কীভাবে ফিরে আসছে, তবে অরেটে () থেকে অবজেক্টের ডিফল্ট? এটি নকশা করার অর্ধেক পথের মতো তারা সিদ্ধান্ত নিয়েছে যে এখানে এটির দরকার নেই ??

যেহেতু প্রশ্নের উদ্দেশ্যটি কেবল toArray() সাথে toArray() ব্যবহার করার বিষয়ে নয় বরং toArray() শ্রেণিতে পদ্ধতিগুলির নকশা বোঝার বিষয়ে নয়, তাই আমি যুক্ত করতে চাই:

ArrayList একটি জেনেরিক শ্রেণি যেমন এটি ঘোষিত হয়

public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

যা ক্লাসের মধ্যে public E get(int index) মতো জেনেরিক পদ্ধতি ব্যবহার সম্ভব করে তোলে।

তবে toArray() মতো কোনও পদ্ধতি যদি E না করে E[] ফেরত না থাকে তবে জিনিসগুলি কিছুটা জটিল হয়ে toArray() শুরু করে। public <E> E[] toArray() মতো একটি স্বাক্ষর সরবরাহ করা সম্ভব হবে না কারণ জেনেরিক অ্যারে তৈরি করা সম্ভব নয়।

অ্যারে তৈরির সময় রানটাইম হয় এবং টাইপ ইরেজরের কারণে, জাভা রানটাইমের E দ্বারা প্রতিনিধিত্ব করা টাইপের কোনও নির্দিষ্ট তথ্য নেই। এখনকার একমাত্র কাজটি হ'ল পদ্ধতিতে প্যারামিটার হিসাবে প্রয়োজনীয় প্রকারটি পাস করা এবং সেইজন্য স্বাক্ষরটি public <T> T[] toArray(T[] a) যেখানে ক্লায়েন্টরা প্রয়োজনীয় প্রকারটি পাস করতে বাধ্য হয়।

তবে অন্যদিকে, এটি public E get(int index) কারণ আপনি যদি পদ্ধতির বাস্তবায়নের দিকে লক্ষ্য করেন তবে আপনি দেখতে পাবেন যে পদ্ধতিটি নির্দিষ্ট বস্তুর জন্য একই বস্তুর অ্যারে ব্যবহার করে যদিও সূচক, এটি E

E elementData(int index) {
    return (E) elementData[index];
}

এটি জাভা সংকলক যা সংকলন সময়ে ইটির সাথে Object সাথে প্রতিস্থাপন করে

https://src-bin.com

বলুন যে আপনি নীচে হিসাবে একটি অ্যারেলিস্ট সংজ্ঞায়িত করেছেন:

ArrayList<String> someData = new ArrayList<>();

আপনার কোডটিতে পরে, জেনেরিকের কারণে আপনি এটি বলতে পারেন:

String someLine = someData.get(0);

এবং সংকলকটি পুরোপুরি জানে যে এটি একটি স্ট্রিং পাবে। ইয়া জেনেরিকস! তবে এটি ব্যর্থ হবে:

String[] arrayOfData = someData.toArray();

toArray() অ্যারে toArray() সর্বদা অবজেক্টগুলির একটি অ্যারে ফিরিয়ে দেবে, সংজ্ঞায়িত toArray() নয়। কেন get(x) পদ্ধতিটি জানে যে এটি কীভাবে ফিরে আসছে, তবে toArray() থেকে অবজেক্টের ডিফল্ট?


Answer #1

আপনাকে প্রথমে যা বুঝতে হবে তা হ'ল ArrayList নিজের Object একটি অ্যারে

   transient Object[] elementData;

যখন T[] ব্যর্থ হওয়ার কারণ নিয়ে আসে, এটি কারণ আপনি Class<T> ব্যতীত জেনেরিক ধরণের অ্যারে পেতে পারেন না এবং এটি জাভার ধরণের মুছার কারণ রয়েছে ( আরও ব্যাখ্যা রয়েছে এবং কীভাবে এটি তৈরি করতে হয় ) । এবং স্তূপের array[] তার ধরণটি গতিশীলরূপে জানে এবং আপনি String[] তে String[] কাস্ট করতে পারবেন না। একই কারণে, আপনি Object[] কে T[] তে কাস্ট করতে পারবেন না।

   int[] ints = new int[3];
   String[] strings = (String[]) ints;//java: incompatible types: int[] cannot be converted to java.lang.String[]

   public <T> T[] a() {
      Object[] objects = new Object[3];
      return (T[])objects;
   }
   //ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
   Integer[] a = new LearnArray().<Integer>a();

তবে আপনি array যা রেখেছেন তা হ'ল কোন প্রকারের E (যা সংকলক দ্বারা পরীক্ষা করা হয়), তাই আপনি এটি কেবল E কাস্ট করতে পারেন যা নিরাপদ এবং সঠিক।

  return (E) elementData[index];

সংক্ষেপে, আপনি কাস্ট দ্বারা যা নেই তা পেতে পারেন না। আপনার কেবল Object[] , সুতরাং toArray() স্রেফ Object[] ফিরিয়ে দিতে পারে (অন্যথায়, আপনাকে এটিকে একটি Class<T> দিতে হবে Class<T> এই ধরণের সাথে একটি নতুন অ্যারে তৈরি করতে)। আপনি ArrayList<E> E রাখলেন ArrayList<E> , আপনি get() সহ একটি E পেতে পারেন।


Answer #2

আপনি যদি toArray(T[] a) ArrayList<E> শ্রেণীর toArray(T[] a) প্রয়োগের দিকে toArray(T[] a) এটির মতো:

public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

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

public <T> T[] toArray() {
    T[] t = new T[size]; // compilation error
    return Arrays.copyOf(elementData, size, t.getClass());
}

তবে এখানে সমস্যা হ'ল আপনি জাভাতে জেনেরিক অ্যারে তৈরি করতে পারবেন না কারণ সংকলক জানে না যে T কি প্রতিনিধিত্ব করে exactly অন্য কথায় জাভাতে একটি নন-রিফাইফিয়েবল টাইপের অ্যারে ( JLS §4.7 ) তৈরির অনুমতি নেই

অ্যারে স্টোর ব্যতিক্রম ( জেএলএস -10.5 ) এর অন্য একটি গুরুত্বপূর্ণ উক্তি:

যদি অ্যারের অংশের উপাদানটি পুনরুদ্ধারযোগ্য না হয় (§4.7), জাভা ভার্চুয়াল মেশিন পূর্ববর্তী অনুচ্ছেদে বর্ণিত স্টোর চেকটি সম্পাদন করতে পারে না। এই কারণেই একটি অ-সংশোধনযোগ্য উপাদান ধরণের সহ একটি অ্যারে তৈরির এক্সপ্রেশন নিষিদ্ধ করা হয়েছে (.15.10.1)।

এজন্য জাভা toArray(T[] a) ওভারলোডেড সংস্করণ সরবরাহ করেছে।

আমি এটিআর () পদ্ধতিটি এড়াতে লিখব যে এটি E এর অ্যারেটি ফিরিয়ে দেবে tell

সুতরাং toArray() ওভাররাইড করার পরিবর্তে আপনার toArray(T[] a) ব্যবহার করা উচিত।

জাভা ডক থেকে টাইপ পরামিতিগুলির উদাহরণ তৈরি করা যায় না এটি আপনার জন্যও আকর্ষণীয় হতে পারে।


Answer #3

একটি অ্যারের অ্যারের ধরণের চেয়ে আলাদা ধরণের। এটি স্ট্রিং ক্লাসের পরিবর্তে স্ট্রিংআরে ক্লাসের ধরণ।

ধরে নেওয়া, এটি সম্ভব হবে, toArray() কাছে একটি জেনেরিক পদ্ধতিটি toArray() হবে

private <T> T[] toArray() {
    T[] result = new T[length];
    //populate
    return result;
}

সংকলনের সময় টি টাইপটি মুছে যায়। new T[length] কীভাবে প্রতিস্থাপন করা উচিত? জেনেরিক ধরণের তথ্য পাওয়া যায় না।

যদি আপনি ArrayList উত্স কোডটি দেখে থাকেন তবে আপনি এটি দেখতে পাবেন। toArray(T[] a) পদ্ধতিটি প্রদত্ত অ্যারে পূরণ করে (যদি আকারটি মেলে) বা প্যারামিটারের toArray(T[] a) ব্যবহার করে একটি নতুন নতুন অ্যারে তৈরি করে, যা জেনেরিক টাইপ টি এর অ্যারে-টাইপ is


Answer #4

প্রদত্ত (পরিচিত) ধরণের একটি "জেনেরিক" অ্যারে তৈরি করা সম্ভব। সাধারণত আমি আমার কোডে এরকম কিছু ব্যবহার করি।

public static <T> T[] toArray(Class<T> type, ArrayList<T> arrList) {
    if ((arrList == null) || (arrList.size() == 0)) return null;
    Object arr = Array.newInstance(type, arrList.size());
    for (int i=0; i < arrList.size(); i++) Array.set(arr, i, arrList.get(i));
    return (T[])arr;
}

Answer #5

প্রাসঙ্গিক বিষয়টি লক্ষণীয় যে জাভাতে অ্যারেগুলি রানটাইমের সময় তাদের উপাদানগুলির ধরনটি জানে। String[] এবং Integer[] রানটাইমের সময় পৃথক ক্লাস হয় এবং আপনি রানটাইমে তাদের উপাদানগুলির জন্য অ্যারে জিজ্ঞাসা করতে পারেন। সুতরাং, রানটাইমের সময় একটি উপাদান ধরণের প্রয়োজন হয় (হয় new String[...] সাথে সংকলনকালে একটি পুনরায় সংশোধনযোগ্য উপাদান টাইপ হার্ড-কোডিং দ্বারা new String[...] বা অ্যারে তৈরি করতে Array.newInstance() এবং একটি শ্রেণি অবজেক্ট পাস করা))

অন্যদিকে, জেনেরিকগুলিতে টাইপ আর্গুমেন্ট রানটাইমের সময় উপস্থিত নেই। একটি ArrayList<String> এবং একটি ArrayList<Integer> মধ্যে রানটাইমের সময় একেবারেই কোনও পার্থক্য নেই। এটি সব ঠিক ArrayList

আপনি কেবল List<String> একটি List<String> না নিয়ে List<String> পেতে পারেন না এটিই মৌলিক কারণ separately আলাদাভাবে কোনওভাবে উপাদানের ধরণ না করেই আপনাকে উপাদান উপাদান প্রকারের তথ্য থেকে বেরিয়ে আসতে হবে তথ্য। স্পষ্টতই, এটি অসম্ভব।






generics