একটি কাঁচা টাইপ কি এবং কেন আমরা এটি ব্যবহার করা উচিত নয়?


662

প্রশ্নাবলী:

  • জাভাতে কাঁচা প্রকারগুলি কী কী এবং কেন আমি প্রায়শই শুনতে পাই যে সেগুলি নতুন কোডে ব্যবহার করা উচিত নয়?
  • আমরা যদি কাঁচা ধরণের ব্যবহার করতে না পারি তবে বিকল্পটি কী এবং এটি কীভাবে আরও ভাল?

জাভা টিউটোরিয়ালগুলি এখনও জকমবোবক্স ব্যবহার করে যা এই সতর্কতার কারণ হয়ে দাঁড়িয়েছে। কম্বোবক্সের কোন সংস্করণ এই সতর্কতাটির কারণ হবে না? docs.oracle.com/javase/tutorial/uiswing/components/…
সুপারস্টার

1
নোট করুন যে কাঁচা প্রকারের অস্তিত্বের কারণ জাভা ১.৪ এবং তার থেকে পুরোনোের সাথে পিছনের সামঞ্জস্যের জন্য, যার জেনারিক মোটেই নেই।
জেস্পার

উত্তর:


744

কাঁচা ধরণ কী?

জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন নিম্নলিখিতভাবে একটি কাঁচা ধরণের সংজ্ঞা দেয় :

জেএলএস 4.8 কাঁচা প্রকার

একটি কাঁচা টাইপ এর মধ্যে একটি হিসাবে সংজ্ঞায়িত করা হয়:

  • একটি রেফারেন্স টাইপ যা জেনেরিক টাইপ ডিক্লেয়ারেশনের নামটি সহসঙ্গত প্রকার আর্গুমেন্ট তালিকা ছাড়াই গঠিত হয়।

  • একটি অ্যারের প্রকার যার উপাদান ধরণের কাঁচা টাইপ।

  • staticকাঁচা ধরণের একটি অ- সদস্য প্রকার Rযা সুপারক্লাস বা সুপারিনটারফেস থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় না R

উদাহরণস্বরূপ এখানে উদাহরণ দেওয়া হল:

public class MyType<E> {
    class Inner { }
    static class Nested { }

    public static void main(String[] args) {
        MyType mt;          // warning: MyType is a raw type
        MyType.Inner inn;   // warning: MyType.Inner is a raw type

        MyType.Nested nest; // no warning: not parameterized type
        MyType<Object> mt1; // no warning: type parameter given
        MyType<?> mt2;      // no warning: type parameter given (wildcard OK!)
    }
}

এখানে, MyType<E>একটি প্যারামিটারাইজড টাইপ ( জেএলএস 4.5 )। এই ধরনের প্রচ্ছন্নভাবে MyTypeসংক্ষিপ্তসার হিসাবে উল্লেখ করা সাধারণ , তবে প্রযুক্তিগতভাবে নামটি MyType<E>

mtউপরের সংজ্ঞাটিতে প্রথম বুলেট পয়েন্ট দ্বারা একটি কাঁচা ধরণের (এবং সংকলন সতর্কতা উত্পন্ন করে) রয়েছে; innতৃতীয় বুলেট পয়েন্ট দ্বারা একটি কাঁচা টাইপ আছে।

MyType.Nestedস্থিতিমাপ কর ধরন, নয় যদিও এটি একটি স্থিতিমাপ টাইপ একজন সদস্য ধরনের MyType<E>, এটা কারণ static

mt1, এবং mt2উভয়ই প্রকৃত ধরণের পরামিতিগুলির সাথে ঘোষিত হয়, তাই তারা কাঁচা ধরণের নয়।


কাঁচা ধরণের সম্পর্কে এত বিশেষ কী?

মূলত, কাঁচা ধরণগুলি জেনেরিকের প্রচলনের আগে যেমন ছিল তেমন আচরণ করে। এটি হ'ল সংকলন-সময় নীচে সম্পূর্ণ আইনী।

List names = new ArrayList(); // warning: raw type!
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // not a compilation error!

উপরের কোডটি ঠিকঠাক চলতে পারে তবে মনে করুন আপনার নিম্নলিখিতগুলিও রয়েছে:

for (Object o : names) {
    String name = (String) o;
    System.out.println(name);
} // throws ClassCastException!
  //    java.lang.Boolean cannot be cast to java.lang.String

রান-টাইমে এখন আমরা সমস্যায় পড়ি, কারণ namesএমন কিছু রয়েছে যা একটি নয় instanceof String

সম্ভবত, যদি তুমি চাও namesশুধুমাত্র ধারণ String, আপনি পারে সম্ভবত এখনও একটি কাঁচা টাইপ ব্যবহার এবং নিজে যে পরীক্ষা add নিজেকে, এবং তারপর নিজে নিক্ষেপ করার Stringথেকে প্রতিটি আইটেম namesআরও ভাল , যদিও কোনও কাঁচা ধরণের ব্যবহার না করা এবং জাভা জেনেরিকের শক্তিকে কাজে লাগিয়ে সংকলকটি আপনার জন্য সমস্ত কাজ করতে দেয়।

List<String> names = new ArrayList<String>();
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // compilation error!

অবশ্যই, আপনি যদি কোনওটিকেnames অনুমতি দিতে চান Boolean, তবে আপনি এটি হিসাবে এটি ঘোষণা করতে পারেন List<Object> namesএবং উপরের কোডটি সংকলন করবে।

আরো দেখুন


<Object>টাইপ পরামিতি হিসাবে কোনও কাঁচা টাইপ কীভাবে আলাদা ?

কার্যকর জাভা 2 য় সংস্করণ, আইটেম 23 এর একটি উদ্ধৃতি নিম্নরূপ : নতুন কোডে কাঁচা ধরণের ব্যবহার করবেন না :

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

পয়েন্টটি বর্ণনা করার জন্য, নিম্নলিখিত পদ্ধতিটি বিবেচনা করুন যা একটি নেয় List<Object>এবং সংযোজন করে new Object()

void appendNewObject(List<Object> list) {
   list.add(new Object());
}

জাভার জেনারিকস অবিস্মরণীয়। এ List<String>একটি নয় List<Object>, সুতরাং নিম্নলিখিতগুলি একটি সংকলক সতর্কতা তৈরি করবে:

List<String> names = new ArrayList<String>();
appendNewObject(names); // compilation error!

যদি আপনি appendNewObjectকোনও কাঁচা ধরণের Listপ্যারামিটার হিসাবে নেওয়ার কথা ঘোষণা করেন , তবে এটি সংকলন করবে এবং আপনি জেনেরিক থেকে যে ধরণের সুরক্ষা পেয়েছেন তা হারাবেন।

আরো দেখুন


<?>টাইপ প্যারামিটার হিসাবে কোনও কাঁচা টাইপ কীভাবে আলাদা ?

List<Object>, List<String>ইত্যাদি সবই রয়েছে List<?>তাই কেবল এটির Listপরিবর্তে কেবল এটি বলার জন্য লোভনীয় হতে পারে । তবে, একটি বড় পার্থক্য রয়েছে: যেহেতু List<E>কেবলমাত্র একটি সংজ্ঞা দেয় add(E)আপনি একটিতে কেবল কোনও স্বেচ্ছাচারিত বস্তু যুক্ত করতে পারবেন না List<?>। অন্যদিকে, যেহেতু কাঁচা টাইপের Listধরণের সুরক্ষা নেই, আপনি এটিকে addকেবল কোনও কিছু করতে পারেন List

পূর্ববর্তী স্নিপেটের নিম্নলিখিত পরিবর্তনের বিষয়টি বিবেচনা করুন:

static void appendNewObject(List<?> list) {
    list.add(new Object()); // compilation error!
}
//...

List<String> names = new ArrayList<String>();
appendNewObject(names); // this part is fine!

সংকলকটি আপনাকে সম্ভাব্যতার ধরণের ইনগ্রিয়ারিয়েন্স লঙ্ঘন থেকে রক্ষা করার এক দুর্দান্ত কাজ করেছে List<?>! আপনি যদি প্যারামিটারটিকে কাঁচা প্রকার হিসাবে ঘোষণা করে থাকেন List listতবে কোডটি সংকলন করে, এবং আপনি প্রকারের আক্রমণকারীটি লঙ্ঘন করেছেন List<String> names


একটি কাঁচা টাইপ সেই ধরণের মুছে ফেলা হয়

জেএলএসে ফিরে যান 4.8:

এটা একটা ধরন হিসেবে ব্যবহার করা সম্ভব ইরেজিওর স্থিতিমাপ কর টাইপ বা একটি অ্যারের রযেছে যাদের উপাদান ধরনের একটি স্থিতিমাপ টাইপ হয় ইরেজিওর করুন। এ জাতীয় প্রকারকে কাঁচা টাইপ বলে

[...]

একটি কাঁচা ধরণের সুপারক্লাসগুলি (যথাক্রমে সুপারিনটারফেস) হ'ল জেনেরিক ধরণের যে কোনও প্যারামিটারাইজেশনগুলির সুপারক্লাসগুলি (সুপারিনটারফেসগুলি) মুছে ফেলা হয়।

কোনও নির্মাণকারীর ধরণ, উদাহরণ পদ্ধতি, বা staticকোনও কাঁচা প্রকারের ক্ষেত্রবিহীন ক্ষেত্র Cযা এর সুপারক্লাস বা সুপারিনটারফেসগুলি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় না তা হ'ল কাঁচা টাইপ যা সম্পর্কিত জেনেরিক ঘোষণায় এর ধরণের মুছে যাওয়ার সাথে সম্পর্কিত C

সহজ কথায়, যখন কোনও কাঁচা প্রকার ব্যবহৃত হয়, তখন কনস্ট্রাক্টর, উদাহরণ পদ্ধতি এবং ক্ষেত্রবিহীন staticক্ষেত্রগুলিও মুছে ফেলা হয়

নিম্নলিখিত উদাহরণটি ধরুন:

class MyType<E> {
    List<String> getNames() {
        return Arrays.asList("John", "Mary");
    }

    public static void main(String[] args) {
        MyType rawType = new MyType();
        // unchecked warning!
        // required: List<String> found: List
        List<String> names = rawType.getNames();
        // compilation error!
        // incompatible types: Object cannot be converted to String
        for (String str : rawType.getNames())
            System.out.print(str);
    }
}

যখন আমরা কাঁচা ব্যবহার করি MyType, getNamesপাশাপাশি মুছে যায়, যাতে এটি কোনও কাঁচা ফেরত দেয় List!

জেএলএস 4.6 নিম্নলিখিতগুলি ব্যাখ্যা করে চলেছে:

টাইপ ইরেজর কোনও কনস্ট্রাক্টর বা পদ্ধতির স্বাক্ষরকে এমন একটি স্বাক্ষরে মানচিত্র করে যার কোনও প্যারামিটারাইজড প্রকার বা টাইপ ভেরিয়েবল নেই। একটি কন্সট্রাকটর বা পদ্ধতি স্বাক্ষর ইরেজিওর sনামেই গঠিত একটি স্বাক্ষর হয় sএবং দেওয়া সমস্ত ফর্ম্যাল প্যারামিটার ধরনের erasures s

পদ্ধতি বা নির্মাণকারীর স্বাক্ষর মুছে ফেলা হলে কোনও পদ্ধতির রিটার্ন টাইপ এবং জেনেরিক পদ্ধতি বা কনস্ট্রাক্টরের টাইপ পরামিতিগুলিও মুছে ফেলা হয়।

জেনেরিক পদ্ধতির স্বাক্ষরের মুছে ফেলার কোনও ধরণের পরামিতি নেই।

নিম্নলিখিত বাগের প্রতিবেদনে মরিজিও সিমাদামোর, একটি সংকলক দেব, এবং জেএলএস-এর অন্যতম লেখক অ্যালেক্স বাকলির কিছু ধারণা রয়েছে, কেন এই ধরণের আচরণটি হওয়া উচিত: https://bugs.openjdk.java.net/browse / জেডিকে-6400০০১৯৯ । (সংক্ষেপে, এটি স্পেসিফিকেশনকে সহজ করে তোলে))


যদি এটি অনিরাপদ থাকে তবে কেন এটি কোনও কাঁচা ধরণের ব্যবহারের অনুমতি দেওয়া হচ্ছে?

এখানে জেএলএস ৪.৮ এর আরও একটি উদ্ধৃতি দেওয়া হয়েছে:

লিগ্যাসি কোডের সামঞ্জস্যের জন্য ছাড় হিসাবে কেবল কাঁচা ধরণের ব্যবহার অনুমোদিত। জাভা প্রোগ্রামিং ল্যাঙ্গুয়েজে উদারতার প্রবর্তনের পরে রচিত কোডে কাঁচা প্রকারের ব্যবহার দৃ strongly়ভাবে নিরুৎসাহিত। সম্ভবত জাভা প্রোগ্রামিং ভাষার ভবিষ্যতের সংস্করণগুলি কাঁচা ধরণের ব্যবহারকে অস্বীকার করবে।

কার্যকর জাভা 2 য় সংস্করণে এটি যুক্ত করার জন্য রয়েছে:

আপনি যে কাঁচা ধরণের ব্যবহার করবেন না তা দেওয়া হয়েছে, ভাষা ডিজাইনাররা কেন তাদের অনুমতি দিলেন? সামঞ্জস্যতা প্রদান।

জেনারিকস চালু হওয়ার সময় জাভা প্ল্যাটফর্মটি তার দ্বিতীয় দশকে প্রবেশ করতে চলেছিল, এবং প্রচুর পরিমাণে জাভা কোড উপস্থিত ছিল যা জেনেরিকগুলি ব্যবহার করে না। এটি সমালোচনা হিসাবে বিবেচিত হয়েছিল যে এই সমস্ত কোডটি জেনেরিকগুলি ব্যবহার করে এমন নতুন কোডের সাথে আইনী এবং আন্তঃব্যবসায়ী থেকে যায়। প্যারামিটারাইজড ধরণের উদাহরণগুলি সাধারণ পদ্ধতির সাথে ব্যবহারের জন্য তৈরি করা হয়েছে এবং এর বিপরীতে প্যারামিটারাইজড প্রকারের উদাহরণগুলি বৈধ হতে হয়েছিল। এই প্রয়োজনীয়তা, মাইগ্রেশন সামঞ্জস্য হিসাবে পরিচিত , কাঁচা ধরণের সমর্থন করার সিদ্ধান্ত নিয়েছে।

সংক্ষেপে, কাঁচা প্রকারগুলি নতুন কোডে কখনও ব্যবহার করা উচিত নয়। আপনার সর্বদা পরামিতিযুক্ত ধরণের ব্যবহার করা উচিত


কোন ব্যতিক্রম আছে?

দুর্ভাগ্যক্রমে, জাভা জেনেরিকগুলি অ-সংশোধিত, এমন দুটি ব্যতিক্রম রয়েছে যেখানে নতুন কোডে কাঁচা প্রকারগুলি ব্যবহার করা উচিত:

  • ক্লাস আক্ষরিক, যেমন List.class, নাList<String>.class
  • instanceofঅপারেন্ড, যেমন o instanceof Set, নাo instanceof Set<String>

আরো দেখুন


16
"জাভা জেনেরিকগুলি নন-রিফাইড হয়" এর অর্থ কী?
কার্ল জি

7
দ্বিতীয় ব্যতিক্রমের জন্য, সিনট্যাক্সটি o instanceof Set<?>কাঁচা টাইপ এড়ানোর জন্যও অনুমোদিত (যদিও এটি কেবল এই ক্ষেত্রে মাত্রাতিরিক্ত)।
পল বেলোরা

1
কাঁচা প্রকারগুলি খুব ব্যবহারযোগ্য এবং একটি শিমের জন্য জেএনডিআই লুকআপের ক্ষেত্রে বয়লারপ্লেট কোড হ্রাস করে যা একটি ইন্টারফেস প্রসারিত করে। এটি nপ্রতিটি কার্যকরকারী শ্রেণীর জন্য অভিন্ন কোড সহ দূরবর্তী মটরশুটি লেখার প্রয়োজনীয়তার সমাধান করে ।
djmj

8
"অ-সংশোধিত" বলার আর একটি উপায় যা সেগুলি মুছে ফেলা হয়েছে। সংকলক জেনেরিক পরামিতিগুলি কী তা জানে তবে সেই তথ্যটি উত্পন্ন বাইকোডে প্রেরণ করা হয় না। জেএলএসের প্রয়োজন যে শ্রেণীর আক্ষরিকের কোনও ধরণের পরামিতি নেই।
এরিক জি। হ্যাগ্রস্টম

2
পছন্দ করুন আমি আনুষ্ঠানিকভাবে এটি মানে না , কারণ শ্রেণীর আক্ষরিক ঠিক হিসাবে সংজ্ঞায়িত TypeName.class, যেখানে TypeNameএকটি সরল সনাক্তকারী ( জেএলএস )) অনুমানমূলকভাবে কথা বললে, আমি অনুমান করি এটি সত্যিই হতে পারে। একটি সূত্র হিসাবে, List<String>.classবৈকল্পিক যা জেএলএস বিশেষত একটি সংকলক ত্রুটি বলে।
রেডিওডেফ

62

জাভাতে কাঁচা প্রকারগুলি কী কী এবং কেন আমি প্রায়শই শুনতে পাই যে সেগুলি নতুন কোডে ব্যবহার করা উচিত নয়?

কাঁচা প্রকারভেদ জাভা ভাষার প্রাচীন ইতিহাস। শুরুর দিকে সেখানে ছিল Collectionsএবং তারা Objectsকিছুই বেশি কিছু কম রাখেনি। পছন্দসই ধরণের Collectionsথেকে প্রয়োজনীয় ক্যাসেটের প্রতিটি ক্রিয়াকলাপ Object

List aList = new ArrayList();
String s = "Hello World!";
aList.add(s);
String c = (String)aList.get(0);

এটি বেশিরভাগ সময় কাজ করার সময়, ত্রুটিগুলি ঘটেছে

List aNumberList = new ArrayList();
String one = "1";//Number one
aNumberList.add(one);
Integer iOne = (Integer)aNumberList.get(0);//Insert ClassCastException here

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

List<String> aNumberList = new ArrayList<String>();
aNumberList.add("one");
Integer iOne = aNumberList.get(0);//Compile time error
String sOne = aNumberList.get(0);//works fine

তুলনার জন্য:

// Old style collections now known as raw types
List aList = new ArrayList(); //Could contain anything
// New style collections with Generics
List<String> aList = new ArrayList<String>(); //Contains only Strings

তুলনামূলক ইন্টারফেস আরও জটিল:

//raw, not type save can compare with Other classes
class MyCompareAble implements CompareAble
{
   int id;
   public int compareTo(Object other)
   {return this.id - ((MyCompareAble)other).id;}
}
//Generic
class MyCompareAble implements CompareAble<MyCompareAble>
{
   int id;
   public int compareTo(MyCompareAble other)
   {return this.id - other.id;}
}

নোট করুন যে কাঁচা প্রকারের সাথে CompareAbleইন্টারফেসটি প্রয়োগ করা অসম্ভব compareTo(MyCompareAble)। কেন আপনি এগুলি ব্যবহার করবেন না:

  • কোনওতে Objectসঞ্চিত যে কোনও Collectionএটি ব্যবহারের আগে কাস্ট করতে হবে
  • জেনেরিকগুলি ব্যবহার করে সময় পরীক্ষাগুলি সংকলন সক্ষম করে
  • কাঁচা প্রকারের ব্যবহার প্রতিটি মান হিসাবে সংরক্ষণ করা সমান Object

সংকলকটি কী করে: জেনেরিক্স পশ্চাদপটে সামঞ্জস্যপূর্ণ, তারা কাঁচা ধরণের মতো একই জাভা ক্লাস ব্যবহার করে। যাদুটি বেশিরভাগ সংকলনের সময়ে ঘটে।

List<String> someStrings = new ArrayList<String>();
someStrings.add("one");
String one = someStrings.get(0);

হিসাবে সংকলিত হবে:

List someStrings = new ArrayList();
someStrings.add("one"); 
String one = (String)someStrings.get(0);

আপনি যদি সরাসরি কাঁচা প্রকারগুলি ব্যবহার করেন তবে আপনি একই কোডটি লিখবেন। ভেবেছি আমি CompareAbleইন্টারফেসের সাথে কী ঘটে তা নিশ্চিত নই , আমি অনুমান করি যে এটি দুটি compareToফাংশন তৈরি করে, একটি হ'ল একটি MyCompareAbleএবং অন্যটি গ্রহণ করে Objectএবং এটি কাস্ট করার পরে প্রথমটিতে পৌঁছে দেয়।

কাঁচা ধরণের বিকল্পগুলি কী: জেনেরিকগুলি ব্যবহার করুন


30

একটি কাঁচা টাইপ কোনও প্রকার আর্গুমেন্ট ছাড়াই জেনেরিক শ্রেণি বা ইন্টারফেসের নাম। উদাহরণস্বরূপ, জেনেরিক বক্স শ্রেণি দেওয়া:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

একটি প্যারামিটারাইজড ধরণের তৈরি করতে Box<T>, আপনি ফর্মাল টাইপ প্যারামিটারের জন্য একটি প্রকৃত টাইপ যুক্তি সরবরাহ করেন T:

Box<Integer> intBox = new Box<>();

যদি প্রকৃত প্রকারের যুক্তি বাদ দেওয়া হয় তবে আপনি একটি কাঁচা ধরণের তৈরি করুন Box<T>:

Box rawBox = new Box();

সুতরাং, Boxজেনেরিক ধরণের কাঁচা টাইপ Box<T>। তবে একটি নন-জেনেরিক ক্লাস বা ইন্টারফেস টাইপ কোনও কাঁচা টাইপ নয়।

কাঁচা ধরণের লিগ্যাসি কোডে প্রদর্শিত হয় কারণ প্রচুর এপিআই ক্লাস (যেমন সংগ্রহ শ্রেণি) জেডিকে 5.0 এর আগে জেনেরিক ছিল না। কাঁচা ধরণের ব্যবহার করার সময়, আপনি মূলত প্রাক-জেনেরিক আচরণ পান - একটি Boxআপনাকে দেয় Object। পশ্চাদপদ সামঞ্জস্যের জন্য, এর কাঁচা প্রকারে একটি প্যারামিটারাইজড টাইপ নির্ধারিত অনুমোদিত:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;               // OK

তবে আপনি যদি কোনও প্যারামিটারাইজড টাইপের কোনও কাঁচা টাইপ বরাদ্দ করেন তবে আপনি একটি সতর্কতা পাবেন:

Box rawBox = new Box();           // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox;     // warning: unchecked conversion

আপনি যদি সম্পর্কিত জেনেরিক ধরণে সংজ্ঞায়িত জেনেরিক পদ্ধতিগুলি শুরু করতে কোনও কাঁচা টাইপ ব্যবহার করেন তবে আপনি একটি সতর্কতাও পাবেন:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8);  // warning: unchecked invocation to set(T)

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

প্রকার ক্ষয়কারী বিভাগে জাভা সংকলক কীভাবে কাঁচা ধরণের ব্যবহার করে সে সম্পর্কে আরও তথ্য রয়েছে।

চেক করা ত্রুটি বার্তা

পূর্বে উল্লিখিত হিসাবে, জেনেরিক কোডের সাথে উত্তরাধিকারের কোডটি মিশ্রণের সময়, আপনি নিম্নলিখিতগুলির মতো সতর্কতা বার্তাগুলির মুখোমুখি হতে পারেন:

দ্রষ্টব্য: উদাহরণ.জভা চেক করা বা অনিরাপদ অপারেশনগুলি ব্যবহার করে।

দ্রষ্টব্য: -স্লিন্টের সাথে পুনরায় কম্পাইল করুন: বিশদগুলির জন্য চেক করা হয়নি।

কোনও পুরানো এপিআই ব্যবহার করার সময় এটি ঘটতে পারে যা নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

public class WarningDemo {
    public static void main(String[] args){
        Box<Integer> bi;
        bi = createBox();
    }

    static Box createBox(){
        return new Box();
    }
}

"চেক না করা" শব্দটির অর্থ হ'ল সংকলকটির কাছে টাইপ সুরক্ষা নিশ্চিত করার জন্য প্রয়োজনীয় সমস্ত প্রকারের চেক সম্পাদন করার জন্য পর্যাপ্ত ধরনের তথ্য নেই। "চেক না করা" সতর্কতা ডিফল্টরূপে অক্ষম করা হয়েছে, যদিও সংকলক একটি ইঙ্গিত দেয়। সমস্ত "চেক না করা" সতর্কতাগুলি দেখতে -Xlint: চেক না করে পুনরায় কম্পাইল করুন।

পূর্ববর্তী উদাহরণটি -Llint এর সাথে পুনরায় রচনা করা: চেক করা ছাড়াই নিম্নলিখিত অতিরিক্ত তথ্যটি প্রকাশ করে:

WarningDemo.java:4: warning: [unchecked] unchecked conversion
found   : Box
required: Box<java.lang.Integer>
        bi = createBox();
                      ^
1 warning

চেক না করা সতর্কতাগুলি পুরোপুরি অক্ষম করতে, -Xlint: -চেক করা পতাকা ব্যবহার করুন। @SuppressWarnings("unchecked")টীকা অবারিত সতর্কবার্তা শুষে নেবে। আপনি যদি @SuppressWarningsসিনট্যাক্সের সাথে অপরিচিত থাকেন তবে টীকা দেখুন।

আসল উত্স: জাভা টিউটোরিয়ালস


21

জাভাতে একটি "কাঁচা" টাইপ একটি শ্রেণি যা অ-জেনেরিক এবং টাইপ-নিরাপদ জেনেরিক ধরণের পরামিতিগুলির পরিবর্তে "কাঁচা" অবজেক্টগুলির সাথে সম্পর্কিত।

উদাহরণস্বরূপ, জাভা জেনেরিকগুলি উপলভ্য হওয়ার আগে আপনি এটি সংগ্রহের ক্লাস ব্যবহার করতেন:

LinkedList list = new LinkedList();
list.add(new MyObject());
MyObject myObject = (MyObject)list.get(0);

আপনি যখন তালিকাতে আপনার অবজেক্ট যুক্ত করবেন তখন এটি কোন ধরণের অবজেক্টের বিষয় তা বিবেচ্য নয় এবং আপনি তালিকা থেকে এলে আপনার স্পষ্টভাবে এটি প্রত্যাশা করা ধরণে কাস্ট করতে হবে।

জেনেরিকগুলি ব্যবহার করে আপনি "অজানা" ফ্যাক্টরটি সরিয়ে ফেলবেন, কারণ আপনাকে অবশ্যই স্পষ্ট করে নির্দিষ্ট করতে হবে যে তালিকায় কোন ধরণের অবজেক্টগুলি যেতে পারে:

LinkedList<MyObject> list = new LinkedList<MyObject>();
list.add(new MyObject());
MyObject myObject = list.get(0);

লক্ষ্য করুন যে জেনেরিকের সাথে আপনাকে গেট কল থেকে আগত বস্তুটি কাস্ট করতে হবে না, সংগ্রহটি কেবল মাইবজেক্টের সাথে কাজ করার জন্য পূর্বনির্ধারিত। এই সত্যটি জেনেরিকের মূল চালিকা ফ্যাক্টর। এটি রানটাইম ত্রুটির উত্সকে এমন কিছুতে পরিবর্তন করে যা সংকলনের সময় পরীক্ষা করা যায়।


3
আরও সুনির্দিষ্টভাবে বলা যায়, একটি জেনেরিক ধরণের জন্য কেবলমাত্র টাইপ পরামিতিগুলি বাদ দিলে আপনি একটি কাঁচা টাইপ পান। কাঁচা ধরণের প্রকৃতপক্ষে কেবল পিছনের সামঞ্জস্য বৈশিষ্ট্য ছিল এবং সম্ভাব্যভাবে অপসারণের অধীন। আপনি কি ব্যবহার করে অনুরূপ আচরণ পেতে পারেন? ওয়াইল্ডকার্ড পরামিতি।
জন ফ্ল্যাটনেস

@ জেরোক্রেটস: একই রকম তবে ভিন্ন! ব্যবহার করে ?এখনও সুরক্ষা উপলব্ধ করা হয়। আমি আমার উত্তরে এটি coveredেকে রেখেছি।
বহুবিশ্লেষকারী

19
 private static List<String> list = new ArrayList<String>();

আপনার টাইপ-প্যারামিটার নির্দিষ্ট করা উচিত।

সতর্কতাটি পরামর্শ দেয় যে জেনেরিক্সকে সমর্থন করার জন্য সংজ্ঞায়িত ধরণগুলি তাদের কাঁচা ফর্মটি ব্যবহার না করে প্যারামিটারাইজ করা উচিত।

Listসমর্থন জেনেরিক্স হিসেবে সংজ্ঞায়িত করা হয়: public class List<E>। এটি অনেক ধরণের-নিরাপদ ক্রিয়াকলাপের অনুমতি দেয়, যা সংকলন-সময় পরীক্ষা করা হয়।


3
এখন জাভা -private static List<String> list = new ArrayList<>();
ইয়ার ক্যাম্পবেল

14

কাঁচা টাইপ কী এবং আমি কেন প্রায়ই শুনতে পাই যে সেগুলি নতুন কোডে ব্যবহার করা উচিত নয়?

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

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

আমরা যদি কাঁচা ধরণের ব্যবহার করতে না পারি তবে বিকল্পটি কী এবং এটি কীভাবে আরও ভাল?

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

উদাহরণস্বরূপ, এমন একটি পদ্ধতির জন্য যেখানে প্রোগ্রামার 'নাম' নামক একটি তালিকা ভেরিয়েবলটি নিশ্চিত করতে চায় কেবল স্ট্রিংস রয়েছে:

List<String> names = new ArrayList<String>();
names.add("John");          // OK
names.add(new Integer(1));  // compile error

1
আহ, স্ট্যাকওভারফ্লো / প্রশ্ন / 2770111/…polygenelubricants থেকে "কাঁচা টাইপ" রেফারেন্সগুলি আমার নিজের উত্তরে অনুলিপি করার জন্য প্রলুব্ধ হয়েছি তবে আমি মনে করি আমি সেগুলি তার নিজের উত্তরটিতে ব্যবহারের জন্য রেখে দেব।
বার্ট এফ

1
হ্যাঁ, আমি মূলত অনুলিপিটি-অনুলিপি করে আছি that সেগমেন্টটি লোকেরা যেখানেই স্ট্যাকওভারফ্লোতে কাঁচা ধরণের ব্যবহার করে এবং অবশেষে সিদ্ধান্ত নিয়েছে যে এখন থেকে কেবল একটি প্রশ্ন করা উচিত। আমি আশা করি এটি সম্প্রদায়ের জন্য একটি ভাল অবদান।
বহুবিশ্লেষকারী

1
@ পোলিজেলব্রিকেন্টস আমি লক্ষ্য করেছি - আমরা একই প্রশ্নগুলির কয়েকটি হিট করেছি :-)
বার্ট এফ

1
@ ha9u63ar: আসলেই। সাধারণভাবে সংক্ষিপ্ত এবং সহজ উত্তরগুলি কমপক্ষে দীর্ঘ এবং স্বীকৃত উত্তরগুলির মতো ভাল।
ডিসপ্লেনাম

"শক্তিশালী সাইপিং" কী?
carloswm85

12

সংকলকটি আপনি এটি লিখতে চান:

private static List<String> list = new ArrayList<String>();

কারণ অন্যথায়, আপনি নিজের পছন্দ মতো যে কোনও ধরণের যোগ করতে পারেন list, ইনস্ট্যান্টেশনটিকে new ArrayList<String>()অর্থহীন হিসাবে তৈরি করে । জাভা জেনেরিকগুলি কেবল একটি সংকলন-সময় বৈশিষ্ট্য, তাই তৈরি করা কোনও বস্তু new ArrayList<String>()আনন্দের সাথে গ্রহণ করবে Integerবা JFrame"কাঁচা টাইপ" এর কোনও রেফারেন্স হিসাবে নির্ধারিত হলে উপাদানগুলি List- নিজেই কোন ধরণের কী ধারণ করতে হবে সে সম্পর্কে কিছুই জানে না, কেবল সংকলক তা করে।


12

এখানে আমি একাধিক কেস বিবেচনা করছি যার মাধ্যমে আপনি ধারণাটি পরিষ্কার করতে পারবেন

1. ArrayList<String> arr = new ArrayList<String>();
2. ArrayList<String> arr = new ArrayList();
3. ArrayList arr = new ArrayList<String>();

মামলা 1

ArrayList<String> arrএটি ArrayListটাইপ সহ একটি রেফারেন্স ভেরিয়েবল যা টাইপের Stringকোনও ArralyListঅবজেক্টের সাথে সম্পর্কিত String। এর অর্থ এটি কেবল স্ট্রিং টাইপ অবজেক্টকে ধারণ করতে পারে।

এটি Stringকোনও কাঁচা টাইপ না করার পক্ষে কঠোর , এটি কোনও সতর্কতা কখনই উত্থাপন করবে না।

    arr.add("hello");// alone statement will compile successfully and no warning.

    arr.add(23);  //prone to compile time error.
     //error: no suitable method found for add(int)

মামলা 2

এই ক্ষেত্রে ArrayList<String> arrএকটি কঠোর প্রকারের তবে আপনার অবজেক্টটি new ArrayList();একটি কাঁচা প্রকার।

    arr.add("hello"); //alone this compile but raise the warning.
    arr.add(23);  //again prone to compile time error.
    //error: no suitable method found for add(int)

এখানে arrএকটি কঠোর প্রকার। সুতরাং, এটি যুক্ত করার সময় এটি সংকলনের সময় ত্রুটি বাড়িয়ে তুলবে integer

সতর্কতা : - একটি Rawপ্রকারের অবজেক্টটি একটি Strictপ্রকারের রেফারেন্সড ভেরিয়েবলের সাথে উল্লেখ করা হয় ArrayList

মামলা 3

এই ক্ষেত্রে ArrayList arrএকটি কাঁচা টাইপ রয়েছে কিন্তু আপনার অবজেক্ট new ArrayList<String>();কঠোর প্রকার।

    arr.add("hello");  
    arr.add(23);  //compiles fine but raise the warning.

এটি এতে কোনও ধরণের অবজেক্ট যুক্ত করবে কারণ arrএটি একটি কাঁচা টাইপ।

সতর্কতা : - একটি Strictটাইপ অবজেক্ট একটি rawপ্রকারভেদযোগ্য চলকের সাথে উল্লেখ করা হয়।


8

জেনেরিক টাইপ ব্যবহার করার সময় একটি কাঁচা- টাইপ টাইপ প্যারামিটারের অভাব ।

কাঁচা-টাইপ হয়েছে কারণ এটি পারে ঢোকাতে মত, রানটাইম ত্রুটি হতে ব্যবহার করা উচিত নয় doubleকি হতে অনুমিত ছিল মধ্যে Setএর intগুলি।

Set set = new HashSet();
set.add(3.45); //ok

যখন থেকে জিনিসটি পুনরুদ্ধার করবেন তখন Setআপনি জানেন না যে কী আসছে coming আসুন ধরে নেওয়া যাক আপনি এটির সমস্ত প্রত্যাশা করছেন int, আপনি এটি কাস্ট করছেন Integer; রানটাইম এ ব্যতিক্রম যখন double3.45 বরাবর আসে।

আপনার সাথে কোনও প্রকারের প্যারামিটার যুক্ত হওয়ার সাথে সাথে Setআপনি একবারে একটি সংকলন ত্রুটি পাবেন। এই প্রিপ্রিমটিভ ত্রুটিটি রানটাইম চলাকালীন কোনও কিছু আপ করার আগে সমস্যাটি ঠিক করতে দেয় (এইভাবে সময় এবং প্রচেষ্টায় সঞ্চয় করা)।

Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.

7

এখানে আর একটি মামলা রয়েছে যেখানে কাঁচা প্রকারগুলি আপনাকে কামড় দেবে:

public class StrangeClass<T> {
  @SuppressWarnings("unchecked")
  public <X> X getSomethingElse() {
    return (X)"Testing something else!";
  }

  public static void main(String[] args) {
    final StrangeClass<String> withGeneric    = new StrangeClass<>();
    final StrangeClass         withoutGeneric = new StrangeClass();
    final String               value1,
                               value2;

    // Compiles
    value1 = withGeneric.getSomethingElse();

    // Produces compile error:
    // incompatible types: java.lang.Object cannot be converted to java.lang.String
    value2 = withoutGeneric.getSomethingElse();
  }
}

গৃহীত উত্তরে যেমন উল্লেখ করা হয়েছে, আপনি কাঁচা টাইপের কোডের মধ্যে জেনেরিকের জন্য সমস্ত সমর্থন হারাবেন। প্রতিটি ধরণের পরামিতি তার মুছে ফেলা হয় (যা উপরোক্ত উদাহরণে ন্যায়সঙ্গত Object)।


5

কি বলছে যে আপনার listএকটিList অনির্দিষ্ট বিষয়। যে জাভা জানেন না তালিকার ভিতরে কি ধরণের অবজেক্ট রয়েছে। তারপরে আপনি যখন তালিকার পুনরাবৃত্তি করতে চান তখন আপনাকে প্রতিটি উপাদানটি কাস্ট করতে হবে, সেই উপাদানটির বৈশিষ্ট্যগুলিতে অ্যাক্সেস করতে সক্ষম হতে (এই ক্ষেত্রে স্ট্রিং)।

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

private static List<String> list = new ArrayList<String>();

4

টিউটোরিয়াল পৃষ্ঠা

একটি কাঁচা টাইপ কোনও প্রকার আর্গুমেন্ট ছাড়াই জেনেরিক শ্রেণি বা ইন্টারফেসের নাম। উদাহরণস্বরূপ, জেনেরিক বক্স শ্রেণি দেওয়া:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

একটি প্যারামিটারাইজড ধরণের বক্স তৈরি করতে, আপনি ফর্মাল টাইপ প্যারামিটার টি এর জন্য একটি প্রকৃত টাইপ যুক্তি সরবরাহ করেন:

Box<Integer> intBox = new Box<>();

যদি প্রকৃত ধরণের যুক্তি বাদ দেওয়া হয় তবে আপনি একটি কাঁচা ধরণের বাক্স তৈরি করুন:

Box rawBox = new Box();

2

কাঁচা ধরনের এড়িয়ে চলুন

কাঁচা টাইপগুলি কোনও ধরণের পরামিতি নির্দিষ্ট না করে জেনেরিক প্রকারটি ব্যবহার করে।

উদাহরণস্বরূপ ,

একটি তালিকা একটি কাঁচা টাইপ, যখন List<String>একটি প্যারামিটারাইজড টাইপ।

জেনারিকগুলি জেডিকে ১.৫ এ প্রবর্তন করা হলে, জাভার পুরানো সংস্করণগুলির সাথে পিছনের দিকে সামঞ্জস্য বজায় রাখতে কাঁচা ধরণেরগুলি বজায় রাখা হয়েছিল। যদিও কাঁচা ধরণের ব্যবহার এখনও সম্ভব,

তাদের এড়ানো উচিত :

  • তাদের সাধারণত ক্যাস্টের প্রয়োজন হয়
  • সেগুলি নিরাপদে টাইপ করা হয় না এবং কিছু গুরুত্বপূর্ণ ধরণের ত্রুটি কেবল রানটাইমের সময় উপস্থিত হয়
  • এগুলি কম ভাবপূর্ণ, এবং প্যারামিটারাইজড ধরণের উদাহরণের মতো স্ব-নথি নয়

    import java.util.*;
    
    public final class AvoidRawTypes {
    
    void withRawType() {
    
        //Raw List doesn't self-document, 
        //doesn't state explicitly what it can contain
    
        List stars = Arrays.asList("Arcturus", "Vega", "Altair");
    
        Iterator iter = stars.iterator();
    
        while (iter.hasNext()) {
    
            String star = (String) iter.next(); //cast needed
    
            log(star);
        }
    
    }
    
    void withParameterizedType() {
    
        List < String > stars = Arrays.asList("Spica", "Regulus", "Antares");
    
        for (String star: stars) {
    
            log(star);
        }
    
    }
    
    private void log(Object message) {
    
        System.out.println(Objects.toString(message));
    
    }
    
    }

রেফারেন্সের জন্য : https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html


1

কিছু নমুনা অনুশীলন করার পরে এবং ঠিক একই ধরণের পাজলেটের পরে আমি এই পৃষ্ঠাটি পেয়েছি।

============== আমি এই কোডটি থেকে নমুনা হিসাবে সরবরাহ করেছিলাম =================

public static void main(String[] args) throws IOException {

    Map wordMap = new HashMap();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator i = wordMap.entrySet().iterator(); i.hasNext();) {
        Map.Entry entry = (Map.Entry) i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

====================== এই কোডটিতে =========================

public static void main(String[] args) throws IOException {
    // replace with TreeMap to get them sorted by name
    Map<String, Integer> wordMap = new HashMap<String, Integer>();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator<Entry<String, Integer>> i = wordMap.entrySet().iterator(); i.hasNext();) {
        Entry<String, Integer> entry =   i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

}

================================================== =============================

এটি আরও নিরাপদ হতে পারে তবে দর্শনের অবতরণ করতে 4 ঘন্টা সময় নিয়েছিল ...


0

কাঁচা প্রকারগুলি ঠিক থাকে যখন আপনি যা প্রকাশ করতে চান তা প্রকাশ করে।

উদাহরণস্বরূপ, একটি ডিসরিয়ালাইজেশন ফাংশনটি একটি ফেরত দিতে পারে Listতবে এটি তালিকার উপাদানটির ধরণটি জানে না। তাই Listউপযুক্ত রিটার্ন টাইপ এখানে।


তুমি ব্যবহার করতে পার ? টাইপ প্যারামিটার হিসাবে
ডানিয়েল কিস

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