প্রশ্নাবলী:
- জাভাতে কাঁচা প্রকারগুলি কী কী এবং কেন আমি প্রায়শই শুনতে পাই যে সেগুলি নতুন কোডে ব্যবহার করা উচিত নয়?
- আমরা যদি কাঁচা ধরণের ব্যবহার করতে না পারি তবে বিকল্পটি কী এবং এটি কীভাবে আরও ভাল?
উত্তর:
জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন নিম্নলিখিতভাবে একটি কাঁচা ধরণের সংজ্ঞা দেয় :
একটি কাঁচা টাইপ এর মধ্যে একটি হিসাবে সংজ্ঞায়িত করা হয়:
একটি রেফারেন্স টাইপ যা জেনেরিক টাইপ ডিক্লেয়ারেশনের নামটি সহসঙ্গত প্রকার আর্গুমেন্ট তালিকা ছাড়াই গঠিত হয়।
একটি অ্যারের প্রকার যার উপাদান ধরণের কাঁচা টাইপ।
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
এবং দেওয়া সমস্ত ফর্ম্যাল প্যারামিটার ধরনের erasuress
।পদ্ধতি বা নির্মাণকারীর স্বাক্ষর মুছে ফেলা হলে কোনও পদ্ধতির রিটার্ন টাইপ এবং জেনেরিক পদ্ধতি বা কনস্ট্রাক্টরের টাইপ পরামিতিগুলিও মুছে ফেলা হয়।
জেনেরিক পদ্ধতির স্বাক্ষরের মুছে ফেলার কোনও ধরণের পরামিতি নেই।
নিম্নলিখিত বাগের প্রতিবেদনে মরিজিও সিমাদামোর, একটি সংকলক দেব, এবং জেএলএস-এর অন্যতম লেখক অ্যালেক্স বাকলির কিছু ধারণা রয়েছে, কেন এই ধরণের আচরণটি হওয়া উচিত: https://bugs.openjdk.java.net/browse / জেডিকে-6400০০১৯৯ । (সংক্ষেপে, এটি স্পেসিফিকেশনকে সহজ করে তোলে))
এখানে জেএলএস ৪.৮ এর আরও একটি উদ্ধৃতি দেওয়া হয়েছে:
লিগ্যাসি কোডের সামঞ্জস্যের জন্য ছাড় হিসাবে কেবল কাঁচা ধরণের ব্যবহার অনুমোদিত। জাভা প্রোগ্রামিং ল্যাঙ্গুয়েজে উদারতার প্রবর্তনের পরে রচিত কোডে কাঁচা প্রকারের ব্যবহার দৃ strongly়ভাবে নিরুৎসাহিত। সম্ভবত জাভা প্রোগ্রামিং ভাষার ভবিষ্যতের সংস্করণগুলি কাঁচা ধরণের ব্যবহারকে অস্বীকার করবে।
কার্যকর জাভা 2 য় সংস্করণে এটি যুক্ত করার জন্য রয়েছে:
আপনি যে কাঁচা ধরণের ব্যবহার করবেন না তা দেওয়া হয়েছে, ভাষা ডিজাইনাররা কেন তাদের অনুমতি দিলেন? সামঞ্জস্যতা প্রদান।
জেনারিকস চালু হওয়ার সময় জাভা প্ল্যাটফর্মটি তার দ্বিতীয় দশকে প্রবেশ করতে চলেছিল, এবং প্রচুর পরিমাণে জাভা কোড উপস্থিত ছিল যা জেনেরিকগুলি ব্যবহার করে না। এটি সমালোচনা হিসাবে বিবেচিত হয়েছিল যে এই সমস্ত কোডটি জেনেরিকগুলি ব্যবহার করে এমন নতুন কোডের সাথে আইনী এবং আন্তঃব্যবসায়ী থেকে যায়। প্যারামিটারাইজড ধরণের উদাহরণগুলি সাধারণ পদ্ধতির সাথে ব্যবহারের জন্য তৈরি করা হয়েছে এবং এর বিপরীতে প্যারামিটারাইজড প্রকারের উদাহরণগুলি বৈধ হতে হয়েছিল। এই প্রয়োজনীয়তা, মাইগ্রেশন সামঞ্জস্য হিসাবে পরিচিত , কাঁচা ধরণের সমর্থন করার সিদ্ধান্ত নিয়েছে।
সংক্ষেপে, কাঁচা প্রকারগুলি নতুন কোডে কখনও ব্যবহার করা উচিত নয়। আপনার সর্বদা পরামিতিযুক্ত ধরণের ব্যবহার করা উচিত ।
দুর্ভাগ্যক্রমে, জাভা জেনেরিকগুলি অ-সংশোধিত, এমন দুটি ব্যতিক্রম রয়েছে যেখানে নতুন কোডে কাঁচা প্রকারগুলি ব্যবহার করা উচিত:
List.class
, নাList<String>.class
instanceof
অপারেন্ড, যেমন o instanceof Set
, নাo instanceof Set<String>
o instanceof Set<?>
কাঁচা টাইপ এড়ানোর জন্যও অনুমোদিত (যদিও এটি কেবল এই ক্ষেত্রে মাত্রাতিরিক্ত)।
n
প্রতিটি কার্যকরকারী শ্রেণীর জন্য অভিন্ন কোড সহ দূরবর্তী মটরশুটি লেখার প্রয়োজনীয়তার সমাধান করে ।
TypeName.class
, যেখানে TypeName
একটি সরল সনাক্তকারী ( জেএলএস )) অনুমানমূলকভাবে কথা বললে, আমি অনুমান করি এটি সত্যিই হতে পারে। একটি সূত্র হিসাবে, List<String>.class
বৈকল্পিক যা জেএলএস বিশেষত একটি সংকলক ত্রুটি বলে।
জাভাতে কাঁচা প্রকারগুলি কী কী এবং কেন আমি প্রায়শই শুনতে পাই যে সেগুলি নতুন কোডে ব্যবহার করা উচিত নয়?
কাঁচা প্রকারভেদ জাভা ভাষার প্রাচীন ইতিহাস। শুরুর দিকে সেখানে ছিল 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
এবং এটি কাস্ট করার পরে প্রথমটিতে পৌঁছে দেয়।
কাঁচা ধরণের বিকল্পগুলি কী: জেনেরিকগুলি ব্যবহার করুন
একটি কাঁচা টাইপ কোনও প্রকার আর্গুমেন্ট ছাড়াই জেনেরিক শ্রেণি বা ইন্টারফেসের নাম। উদাহরণস্বরূপ, জেনেরিক বক্স শ্রেণি দেওয়া:
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
সিনট্যাক্সের সাথে অপরিচিত থাকেন তবে টীকা দেখুন।
আসল উত্স: জাভা টিউটোরিয়ালস
জাভাতে একটি "কাঁচা" টাইপ একটি শ্রেণি যা অ-জেনেরিক এবং টাইপ-নিরাপদ জেনেরিক ধরণের পরামিতিগুলির পরিবর্তে "কাঁচা" অবজেক্টগুলির সাথে সম্পর্কিত।
উদাহরণস্বরূপ, জাভা জেনেরিকগুলি উপলভ্য হওয়ার আগে আপনি এটি সংগ্রহের ক্লাস ব্যবহার করতেন:
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);
লক্ষ্য করুন যে জেনেরিকের সাথে আপনাকে গেট কল থেকে আগত বস্তুটি কাস্ট করতে হবে না, সংগ্রহটি কেবল মাইবজেক্টের সাথে কাজ করার জন্য পূর্বনির্ধারিত। এই সত্যটি জেনেরিকের মূল চালিকা ফ্যাক্টর। এটি রানটাইম ত্রুটির উত্সকে এমন কিছুতে পরিবর্তন করে যা সংকলনের সময় পরীক্ষা করা যায়।
?
এখনও সুরক্ষা উপলব্ধ করা হয়। আমি আমার উত্তরে এটি coveredেকে রেখেছি।
private static List<String> list = new ArrayList<String>();
আপনার টাইপ-প্যারামিটার নির্দিষ্ট করা উচিত।
সতর্কতাটি পরামর্শ দেয় যে জেনেরিক্সকে সমর্থন করার জন্য সংজ্ঞায়িত ধরণগুলি তাদের কাঁচা ফর্মটি ব্যবহার না করে প্যারামিটারাইজ করা উচিত।
List
সমর্থন জেনেরিক্স হিসেবে সংজ্ঞায়িত করা হয়: public class List<E>
। এটি অনেক ধরণের-নিরাপদ ক্রিয়াকলাপের অনুমতি দেয়, যা সংকলন-সময় পরীক্ষা করা হয়।
private static List<String> list = new ArrayList<>();
কাঁচা টাইপ কী এবং আমি কেন প্রায়ই শুনতে পাই যে সেগুলি নতুন কোডে ব্যবহার করা উচিত নয়?
একটি "কাঁচা টাইপ" হ'ল জেনেরিক ক্লাসের প্যারামিটারাইজড টাইপ (গুলি) এর জন্য টাইপ আর্গুমেন্ট (গুলি) নির্দিষ্ট না করে ব্যবহার List
করা হয় , যেমন পরিবর্তে ব্যবহার করাList<String>
। জেনারিকগুলি যখন জাভাতে প্রবর্তিত হয়েছিল, জেনেরিকগুলি ব্যবহার করতে বেশ কয়েকটি ক্লাস আপডেট করা হয়েছিল। এই শ্রেণিটিকে "কাঁচা টাইপ" হিসাবে ব্যবহার করুন (কোনও ধরণের আর্গুমেন্ট নির্দিষ্ট না করে) লিগ্যাসি কোডটি এখনও সংকলনের অনুমতি দিয়েছে।
"কাঁচা প্রকারগুলি" পিছনের সামঞ্জস্যের জন্য ব্যবহৃত হয়। নতুন কোডে তাদের ব্যবহারের পরামর্শ দেওয়া হয় না কারণ জেনেরিক ক্লাসটি একটি প্রকার যুক্তি সহ ব্যবহার করা শক্তিশালী টাইপিংয়ের অনুমতি দেয়, যার ফলে কোড বোধগম্যতা উন্নত হতে পারে এবং এর আগে সম্ভাব্য সমস্যাগুলি ধরা পড়তে পারে।
আমরা যদি কাঁচা ধরণের ব্যবহার করতে না পারি তবে বিকল্পটি কী এবং এটি কীভাবে আরও ভাল?
পছন্দসই বিকল্পটি হ'ল জেনেরিক ক্লাসগুলি উদ্দেশ্য হিসাবে ব্যবহার করা - একটি উপযুক্ত ধরণের আর্গুমেন্ট (যেমন List<String>
) সহ। এটি প্রোগ্রামারকে আরও নির্দিষ্টভাবে প্রকার নির্দিষ্ট করতে, ভেরিয়েবল বা ডেটা স্ট্রাকচারের উদ্দেশ্যে ব্যবহার সম্পর্কে ভবিষ্যতের রক্ষণাবেক্ষণকারীদের আরও অর্থ বোঝায় এবং এটি সংকলককে আরও ভাল টাইপ-সুরক্ষা প্রয়োগের অনুমতি দেয়। এই সুবিধাগুলি একসাথে কোডের মান উন্নত করতে পারে এবং কিছু কোডিং ত্রুটির প্রবর্তন রোধ করতে সহায়তা করে।
উদাহরণস্বরূপ, এমন একটি পদ্ধতির জন্য যেখানে প্রোগ্রামার 'নাম' নামক একটি তালিকা ভেরিয়েবলটি নিশ্চিত করতে চায় কেবল স্ট্রিংস রয়েছে:
List<String> names = new ArrayList<String>();
names.add("John"); // OK
names.add(new Integer(1)); // compile error
polygenelubricants
থেকে "কাঁচা টাইপ" রেফারেন্সগুলি আমার নিজের উত্তরে অনুলিপি করার জন্য প্রলুব্ধ হয়েছি তবে আমি মনে করি আমি সেগুলি তার নিজের উত্তরটিতে ব্যবহারের জন্য রেখে দেব।
সংকলকটি আপনি এটি লিখতে চান:
private static List<String> list = new ArrayList<String>();
কারণ অন্যথায়, আপনি নিজের পছন্দ মতো যে কোনও ধরণের যোগ করতে পারেন list
, ইনস্ট্যান্টেশনটিকে new ArrayList<String>()
অর্থহীন হিসাবে তৈরি করে । জাভা জেনেরিকগুলি কেবল একটি সংকলন-সময় বৈশিষ্ট্য, তাই তৈরি করা কোনও বস্তু new ArrayList<String>()
আনন্দের সাথে গ্রহণ করবে Integer
বা JFrame
"কাঁচা টাইপ" এর কোনও রেফারেন্স হিসাবে নির্ধারিত হলে উপাদানগুলি List
- নিজেই কোন ধরণের কী ধারণ করতে হবে সে সম্পর্কে কিছুই জানে না, কেবল সংকলক তা করে।
এখানে আমি একাধিক কেস বিবেচনা করছি যার মাধ্যমে আপনি ধারণাটি পরিষ্কার করতে পারবেন
1. ArrayList<String> arr = new ArrayList<String>();
2. ArrayList<String> arr = new ArrayList();
3. ArrayList arr = new ArrayList<String>();
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)
এই ক্ষেত্রে 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
।
এই ক্ষেত্রে ArrayList arr
একটি কাঁচা টাইপ রয়েছে কিন্তু আপনার অবজেক্ট new ArrayList<String>();
কঠোর প্রকার।
arr.add("hello");
arr.add(23); //compiles fine but raise the warning.
এটি এতে কোনও ধরণের অবজেক্ট যুক্ত করবে কারণ arr
এটি একটি কাঁচা টাইপ।
সতর্কতা : - একটি
Strict
টাইপ অবজেক্ট একটিraw
প্রকারভেদযোগ্য চলকের সাথে উল্লেখ করা হয়।
জেনেরিক টাইপ ব্যবহার করার সময় একটি কাঁচা- টাইপ টাইপ প্যারামিটারের অভাব ।
কাঁচা-টাইপ হয়েছে কারণ এটি পারে ঢোকাতে মত, রানটাইম ত্রুটি হতে ব্যবহার করা উচিত নয় double
কি হতে অনুমিত ছিল মধ্যে Set
এর int
গুলি।
Set set = new HashSet();
set.add(3.45); //ok
যখন থেকে জিনিসটি পুনরুদ্ধার করবেন তখন Set
আপনি জানেন না যে কী আসছে coming আসুন ধরে নেওয়া যাক আপনি এটির সমস্ত প্রত্যাশা করছেন int
, আপনি এটি কাস্ট করছেন Integer
; রানটাইম এ ব্যতিক্রম যখন double
3.45 বরাবর আসে।
আপনার সাথে কোনও প্রকারের প্যারামিটার যুক্ত হওয়ার সাথে সাথে Set
আপনি একবারে একটি সংকলন ত্রুটি পাবেন। এই প্রিপ্রিমটিভ ত্রুটিটি রানটাইম চলাকালীন কোনও কিছু আপ করার আগে সমস্যাটি ঠিক করতে দেয় (এইভাবে সময় এবং প্রচেষ্টায় সঞ্চয় করা)।
Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.
এখানে আর একটি মামলা রয়েছে যেখানে কাঁচা প্রকারগুলি আপনাকে কামড় দেবে:
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
)।
কি বলছে যে আপনার list
একটিList
অনির্দিষ্ট বিষয়। যে জাভা জানেন না তালিকার ভিতরে কি ধরণের অবজেক্ট রয়েছে। তারপরে আপনি যখন তালিকার পুনরাবৃত্তি করতে চান তখন আপনাকে প্রতিটি উপাদানটি কাস্ট করতে হবে, সেই উপাদানটির বৈশিষ্ট্যগুলিতে অ্যাক্সেস করতে সক্ষম হতে (এই ক্ষেত্রে স্ট্রিং)।
সাধারণভাবে সংগ্রহগুলি প্যারামিট্রাইজ করার জন্য একটি ভাল ধারণা, সুতরাং আপনার রূপান্তর সমস্যা নেই, আপনি কেবলমাত্র প্যারামিট্রাইজড ধরণের উপাদান যুক্ত করতে সক্ষম হবেন এবং আপনার সম্পাদক আপনাকে নির্বাচন করার জন্য অ্যাপ্রোপিয়েট পদ্ধতিগুলি সরবরাহ করবেন।
private static List<String> list = new ArrayList<String>();
একটি কাঁচা টাইপ কোনও প্রকার আর্গুমেন্ট ছাড়াই জেনেরিক শ্রেণি বা ইন্টারফেসের নাম। উদাহরণস্বরূপ, জেনেরিক বক্স শ্রেণি দেওয়া:
public class Box<T> {
public void set(T t) { /* ... */ }
// ...
}
একটি প্যারামিটারাইজড ধরণের বক্স তৈরি করতে, আপনি ফর্মাল টাইপ প্যারামিটার টি এর জন্য একটি প্রকৃত টাইপ যুক্তি সরবরাহ করেন:
Box<Integer> intBox = new Box<>();
যদি প্রকৃত ধরণের যুক্তি বাদ দেওয়া হয় তবে আপনি একটি কাঁচা ধরণের বাক্স তৈরি করুন:
Box rawBox = new Box();
কাঁচা ধরনের এড়িয়ে চলুন
কাঁচা টাইপগুলি কোনও ধরণের পরামিতি নির্দিষ্ট না করে জেনেরিক প্রকারটি ব্যবহার করে।
উদাহরণস্বরূপ ,
একটি তালিকা একটি কাঁচা টাইপ, যখন 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
কিছু নমুনা অনুশীলন করার পরে এবং ঠিক একই ধরণের পাজলেটের পরে আমি এই পৃষ্ঠাটি পেয়েছি।
============== আমি এই কোডটি থেকে নমুনা হিসাবে সরবরাহ করেছিলাম =================
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 ঘন্টা সময় নিয়েছিল ...
কাঁচা প্রকারগুলি ঠিক থাকে যখন আপনি যা প্রকাশ করতে চান তা প্রকাশ করে।
উদাহরণস্বরূপ, একটি ডিসরিয়ালাইজেশন ফাংশনটি একটি ফেরত দিতে পারে List
তবে এটি তালিকার উপাদানটির ধরণটি জানে না। তাই List
উপযুক্ত রিটার্ন টাইপ এখানে।