{{ ... }}
জাভাতে ডাবল ব্রেস প্রারম্ভিককরণ সিনট্যাক্স ( ) কী?
{{ ... }}
জাভাতে ডাবল ব্রেস প্রারম্ভিককরণ সিনট্যাক্স ( ) কী?
উত্তর:
ডাবল ব্রেস সূচনাটি নির্দিষ্ট শ্রেণি ( বাহ্যিক ধনুর্বন্ধনী) থেকে প্রাপ্ত একটি বেনাম শ্রেণি তৈরি করে এবং সেই শ্রেণীর ( অভ্যন্তরীণ ধনুর্বন্ধনী) মধ্যে একটি প্রাথমিক ব্লক সরবরাহ করে । যেমন
new ArrayList<Integer>() {{
add(1);
add(2);
}};
নোট করুন যে এই ডাবল ব্রেস সূচনাটি ব্যবহারের একটি প্রভাব হ'ল আপনি বেনামে অভ্যন্তরীণ ক্লাস তৈরি করছেন। তৈরি শ্রেণীর this
আশেপাশের বাইরের শ্রেণীর অন্তর্নিহিত পয়েন্টার রয়েছে। সাধারণত কোনও সমস্যা না হলেও এটি কিছু পরিস্থিতিতে যেমন শৃঙ্খলাবদ্ধ বা আবর্জনা সংগ্রহের সময় শোকের কারণ হতে পারে এবং এটি সম্পর্কে সচেতন হওয়াও মূল্যবান।
প্রতিবার কেউ ডাবল ব্রেস সূচনা ব্যবহার করলে, একটি বিড়ালছানা মারা যায়।
সিনট্যাক্সটি বরং অস্বাভাবিক এবং সত্যই মূ .় নয় (স্বাদ বিতর্কযোগ্য, অবশ্যই) বাদে আপনি নিজের প্রয়োগে অপ্রয়োজনীয়ভাবে দুটি তাত্পর্যপূর্ণ সমস্যা তৈরি করছেন, যা আমি সম্প্রতি এখানে আরও বিস্তারিতভাবে ব্লগ করেছি ।
প্রতিবার আপনি ডাবল ব্রেস প্রারম্ভিক ব্যবহারটি ব্যবহার করে একটি নতুন ক্লাস তৈরি করা হয়। যেমন এই উদাহরণ:
Map source = new HashMap(){{
put("firstName", "John");
put("lastName", "Smith");
put("organizations", new HashMap(){{
put("0", new HashMap(){{
put("id", "1234");
}});
put("abc", new HashMap(){{
put("id", "5678");
}});
}});
}};
... এই ক্লাস উত্পাদন করবে:
Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class
এটি আপনার ক্লাসলোডারের পক্ষে বেশ কিছুটা ওভারহেড - কিছুই নয়! অবশ্যই একবার ব্যবহার করলে অবশ্যই খুব বেশি আদিতে সময় লাগবে না। তবে আপনি যদি আপনার এন্টারপ্রাইজ অ্যাপ্লিকেশন জুড়ে এই 20'000 বার করেন ... কেবলমাত্র "সিনট্যাক্স চিনির" জন্য এই সমস্ত গাদা স্মৃতি?
আপনি যদি উপরের কোডটি গ্রহণ করেন এবং কোনও মানচিত্র থেকে সেই মানচিত্রটি ফিরিয়ে দেন, তবে সেই পদ্ধতির কলকারীরা নিঃসন্দেহে খুব ভারী সংস্থান ধরে থাকতে পারে যা আবর্জনা সংগ্রহ করা যায় না। নিম্নলিখিত উদাহরণ বিবেচনা করুন:
public class ReallyHeavyObject {
// Just to illustrate...
private int[] tonsOfValues;
private Resource[] tonsOfResources;
// This method almost does nothing
public Map quickHarmlessMethod() {
Map source = new HashMap(){{
put("firstName", "John");
put("lastName", "Smith");
put("organizations", new HashMap(){{
put("0", new HashMap(){{
put("id", "1234");
}});
put("abc", new HashMap(){{
put("id", "5678");
}});
}});
}};
return source;
}
}
প্রত্যাবর্তিতগুলিতে Map
এখন সংলগ্ন দৃষ্টান্তের একটি রেফারেন্স থাকবে ReallyHeavyObject
। আপনি সম্ভবত এটি ঝুঁকি নিতে চান না:
Http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/ থেকে চিত্র
আপনার আসল প্রশ্নের উত্তর দেওয়ার জন্য, লোকেরা এই সিনট্যাক্সটি ব্যবহার করে ব্যবহার করছে যে জাভাতে মানচিত্রের আক্ষরিক মতো কিছু রয়েছে, বিদ্যমান অ্যারে লিটারেলের মতো:
String[] array = { "John", "Doe" };
Map map = new HashMap() {{ put("John", "Doe"); }};
কিছু লোকেরা এটিকে সিন্ট্যাক্টিক্যালি উদ্দীপক বলে মনে করতে পারেন।
{{...}}
এবং static
ক্ষেত্র হিসাবে ঘোষণা করা হয় , কোনও সম্ভাব্য মেমরি ফাঁস হওয়া উচিত নয়, কেবল একটি বেনাম শ্রেণি এবং কোনও বদ্ধ দৃষ্টান্তের রেফারেন্স নেই, তাই না?
Map.of()
সে উদ্দেশ্যে রয়েছে, তাই
ReallyHeavyObject
। এছাড়াও, বেনামে অভ্যন্তরীণ ক্লাসগুলি ক্লাস বডির অভ্যন্তরে ব্যবহৃত সমস্ত স্থানীয় ভেরিয়েবলগুলি ক্যাপচার করে, তাই আপনি যদি এই প্যাটার্ন সহ সংগ্রহ বা মানচিত্রের সূচনা করতে কেবল ধ্রুবকই ব্যবহার না করেন তবে অভ্যন্তরীণ শ্রেণীর দৃষ্টান্তগুলি সমস্তগুলি ক্যাপচার করবে এবং প্রকৃতপক্ষে সরিয়ে দেওয়ার পরেও সেগুলি রেফারেন্স করতে থাকবে actually সংগ্রহ বা মানচিত্র। সুতরাং এই ক্ষেত্রে, এই দৃষ্টান্তগুলি কেবল রেফারেন্সগুলির জন্য দ্বিগুণ প্রয়োজনীয় মেমরির প্রয়োজন হয় না, তবে সেই ক্ষেত্রে আরও একটি মেমরি ফাঁস হয়।
উদাহরণ স্বরূপ:
public class TestHashMap {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<String,String>(){
{
put("1", "ONE");
}{
put("2", "TWO");
}{
put("3", "THREE");
}
};
Set<String> keySet = map.keySet();
for (String string : keySet) {
System.out.println(string+" ->"+map.get(string));
}
}
}
কিভাবে এটা কাজ করে
প্রথম ধনুর্বন্ধনী একটি নতুন বেনামি অভ্যন্তর শ্রেণি তৈরি করে। এই অভ্যন্তরীণ ক্লাসগুলি তাদের পিতামাতার শ্রেণীর আচরণ অ্যাক্সেস করতে সক্ষম। সুতরাং, আমাদের ক্ষেত্রে, আমরা আসলে হ্যাশসেট বর্গের একটি সাবক্লাস তৈরি করছি, সুতরাং এই অভ্যন্তর শ্রেণিটি পুট () পদ্ধতিটি ব্যবহার করতে সক্ষম।
এবং দ্বিতীয় ধনুর্বন্ধনী সেট উদাহরণস্বরূপ ছাড়া কিছুই নয়। যদি আপনি মূল জাভা ধারণাগুলি মনে করিয়ে দেন তবে স্ট্রাক্টের মতো অনুরূপ বন্ধনীগুলির কারণে আপনি সহজেই স্ট্যান্ট ইনিশিয়ালাইজারগুলির সাথে ইনস্ট্যান্স ইনিশিয়ালার ব্লকগুলি সংযুক্ত করতে পারেন। কেবলমাত্র পার্থক্য হ'ল স্থির কীওয়ার্ডের সাথে স্ট্যাটিক ইনিশিয়ালাইজার যুক্ত করা হয় এবং এটি কেবল একবার চালানো হয়; আপনি কতগুলি বস্তু তৈরি করেন তা বিবেচনাধীন।
ডাবল ব্রেস প্রারম্ভিককরণের একটি মজাদার অ্যাপ্লিকেশনটির জন্য, জাভাতে ডেমথির অ্যারে দেখুন ।
একটি অংশ
private static class IndustrialRaverMonkey
extends Creature.Base {{
life = 46;
strength = 35;
charisma = 91;
weapon = 2;
}}
private static class DwarvenAngel
extends Creature.Base {{
life = 540;
strength = 6;
charisma = 144;
weapon = 50;
}}
এবং এখন, BattleOfGrottoOfSausageSmells
এবং চঙ্কু বেকন জন্য প্রস্তুত থাকুন !
আমি মনে করি যে এটি চাপ দেওয়া গুরুত্বপূর্ণ যে জাভাতে "ডাবল ব্রেস সূচনা" নামে কোনও জিনিস নেই । ওরাকল ওয়েব সাইটে এই শব্দটি নেই। এই উদাহরণে দুটি বৈশিষ্ট্য একসাথে ব্যবহৃত হয়: বেনাম শ্রেণি এবং প্রারম্ভকালীন ব্লক। মনে হচ্ছে পুরানো ইনিশিয়াল ব্লকটি বিকাশকারীরা ভুলে গেছে এবং এই বিষয়ে কিছু বিভ্রান্তি সৃষ্টি করে। ওরাকল ডক্স থেকে উদ্ধৃতি :
উদাহরণস্বরূপ ভেরিয়েবলের জন্য ইনিশিয়ালার ব্লকগুলি দেখতে স্থির ইনিশিয়ালাইজার ব্লকের মতো দেখতে, তবে স্ট্যাটিক কীওয়ার্ড ছাড়াই:
{
// whatever code is needed for initialization goes here
}
1- ডাবল ধনুর্বন্ধনী বলে কোনও জিনিস নেই:
আমি উল্লেখ করতে চাই যে ডাবল ব্রেস আরম্ভের মতো কোনও জিনিস নেই। কেবলমাত্র সাধারণ traditionalতিহ্যবাহী একটি ব্রেস আরম্ভের ব্লক রয়েছে। দ্বিতীয় ধনুর্বন্ধনী ব্লকের আরম্ভের সাথে কোনও সম্পর্ক নেই। উত্তরগুলি বলে যে এই দুটি ধনুর্বন্ধনী কিছু কিছু সূচনা করে তবে এটি এর মতো নয়।
2- এটি কেবল বেনামে ক্লাস সম্পর্কে নয় তবে সমস্ত শ্রেণীর:
প্রায় সব উত্তরই বেনামে বেনামে অভ্যন্তরীণ ক্লাস তৈরি করার সময় এটি ব্যবহৃত জিনিস talk আমি মনে করি যে উত্তরগুলি পড়া লোকেরা এই ধারণাটি পেয়ে যাবে যে বেনামি অন্তর্গত শ্রেণি তৈরি করার সময় এটি কেবল ব্যবহৃত হয়। তবে এটি সকল শ্রেণিতে ব্যবহৃত হয়। এই উত্তরগুলি দেখে মনে হচ্ছে এটি বেনাম শ্রেণীর জন্য উত্সর্গ করা কিছু ব্র্যান্ড নতুন বিশেষ বৈশিষ্ট্য এবং আমি মনে করি এটি বিভ্রান্তিকর।
3- উদ্দেশ্য কেবল একে অপরের পরে বন্ধনী স্থাপন করা, নতুন ধারণা নয়:
আরও এগিয়ে গিয়ে, এই প্রশ্নটি পরিস্থিতি সম্পর্কে কথা বলে যখন দ্বিতীয় খোলার বন্ধনীটি প্রথম খোলার বন্ধনীটির ঠিক পরে। সাধারণত যখন সাধারণ শ্রেণিতে ব্যবহৃত হয় তখন দুটি ধনুর্বন্ধনীগুলির মধ্যে কিছু কোড থাকে তবে এটি সম্পূর্ণ একই জিনিস। সুতরাং এটি বন্ধনী স্থাপনের বিষয়। সুতরাং আমি মনে করি আমাদের বলা উচিত নয় যে এটি কিছু নতুন আকর্ষণীয় জিনিস, কারণ এটি এমন জিনিস যা আমরা সবাই জানি, তবে বন্ধনীগুলির মধ্যে কিছু কোড দিয়ে লিখেছি। আমাদের "ডাবল ব্রেস সূচনা" নামে নতুন ধারণা তৈরি করা উচিত নয়।
4- নেস্টেড বেনামে ক্লাস তৈরি করা দুটি ধনুর্বন্ধনী সঙ্গে কিছুই করার নেই:
আমি একটি যুক্তি সঙ্গে একমত নই যে আপনি অনেক বেনামী ক্লাস তৈরি করেন। আপনি এগুলি তৈরি করছেন না কারণ একটি সূচনাটি ব্লক করেছে, কেবল কারণ আপনি এগুলি তৈরি করেছেন। এমনকি যদি আপনি দুটি ধনুর্বন্ধনী প্রারম্ভিক ব্যবহার না করেন তবে এগুলি তৈরি করা হবে যাতে সমস্যাগুলি আরম্ভ না করেও দেখা দেয় ... সূচনাটি প্রাথমিক উপাদানটি তৈরি করে না এমন উপাদানটি নয়।
অতিরিক্তভাবে আমাদের এই অস্তিত্বের জিনিসটি "ডাবল ব্রেস সূচনা" বা এমনকি একটি সাধারণ বন্ধনী সূচনা দ্বারা ব্যবহার করে তৈরি সমস্যা সম্পর্কে কথা বলা উচিত নয়, কারণ বর্ণিত সমস্যাগুলি কেবল বেনাম শ্রেণি তৈরি করার কারণে বিদ্যমান তাই এটির মূল প্রশ্নের সাথে কোনও সম্পর্ক নেই। তবে সমস্ত উত্তর পাঠকদের এই ধারণা দেয় যে বেনামে শ্রেণি তৈরি করা দোষ নয়, বরং এই "দুর্বল সূক্ষ্মকরণ" নামে পরিচিত এই দুষ্ট (অস্তিত্বহীন) জিনিস।
ডাবল ব্রেস প্রারম্ভিককরণের সমস্ত নেতিবাচক প্রভাব এড়াতে যেমন:
পরবর্তী জিনিসগুলি করুন:
উদাহরণ:
public class MyClass {
public static class Builder {
public int first = -1 ;
public double second = Double.NaN;
public String third = null ;
public MyClass create() {
return new MyClass(first, second, third);
}
}
protected final int first ;
protected final double second;
protected final String third ;
protected MyClass(
int first ,
double second,
String third
) {
this.first = first ;
this.second= second;
this.third = third ;
}
public int first () { return first ; }
public double second() { return second; }
public String third () { return third ; }
}
ব্যবহার:
MyClass my = new MyClass.Builder(){{ first = 1; third = "3"; }}.create();
সুবিধাদি:
অসুবিধা:
এবং, ফলস্বরূপ, আমাদের কাছে সর্বদা সহজ জাভা বিল্ডার প্যাটার্ন রয়েছে।
গিথুবে সমস্ত নমুনা দেখুন: জাভা-এসএফ-বিল্ডার-সাধারণ-উদাহরণ
এটি - অন্যান্য ব্যবহারগুলির মধ্যে - সংগ্রহগুলি আরম্ভ করার জন্য একটি শর্টকাট। আরও জানুন ...
সংগ্রহটি আরম্ভ করার জন্য আপনি কিছু জাভা বিবৃতি লুপ হিসাবে রাখতে পারেন:
List<Character> characters = new ArrayList<Character>() {
{
for (char c = 'A'; c <= 'E'; c++) add(c);
}
};
Random rnd = new Random();
List<Integer> integers = new ArrayList<Integer>() {
{
while (size() < 10) add(rnd.nextInt(1_000_000));
}
};
@ লুকাস ইডার দ্বারা নির্দেশিত হিসাবে সংগ্রহের দ্বৈত ধনুর্বন্ধনী শুরু করা এড়াতে হবে।
এটি একটি বেনামে অভ্যন্তরীণ শ্রেণি তৈরি করে এবং যেহেতু সমস্ত অভ্যন্তরীণ ক্লাসগুলি প্যারেন্ট উদাহরণের সাথে এটি রেফারেন্স রাখে - এবং 99% সম্ভবত - আবশ্যক আবর্জনা সংগ্রহকে আটকাতে যদি এই সংগ্রহের বিষয়গুলি কেবলমাত্র ঘোষণার চেয়ে আরও বেশি বস্তু দ্বারা রেফারেন্স করা হয়।
জাভা 9 সুবিধার পদ্ধতি চালু করেছে List.of
, Set.of
এবং Map.of
, যা পরিবর্তে ব্যবহার করা উচিত। তারা ডাবল-ব্রেস প্রারম্ভকালের চেয়ে দ্রুত এবং আরও দক্ষ।
প্রথম ধনুর্বন্ধনী একটি নতুন বেনাম শ্রেণি তৈরি করে এবং দ্বিতীয় ধনুর্বন্ধনী স্ট্যাটিক ব্লকের মতো একটি সূচনা আরম্ভকারী তৈরি করে।
অন্যরা যেমন উল্লেখ করেছে, এটি ব্যবহার করা নিরাপদ নয়।
তবে সংগ্রহ শুরু করার জন্য আপনি এই বিকল্পটি সর্বদা ব্যবহার করতে পারেন।
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> list = List.of("A", "B", "C");
এটি ফ্ল্যাশ এবং ভিবিএসক্রিপ্টে কী-ওয়ার্ডের সাথে জনপ্রিয় তাই কার্যকর হবে। এটি কী this
এবং কী কিছুই পরিবর্তন করার একটি পদ্ধতি ।
this
। সিনট্যাক্সটি কেবল একটি বেনাম শ্রেণি তৈরি করে (যাতে কোনও নতুন রেফারেন্স শ্রেণীর this
অবজেক্টের সাথে সম্পর্কিত কোনও রেফারেন্স ), এবং তারপরে {...}
নতুন তৈরি হওয়া উদাহরণটি আরম্ভ করার জন্য একটি ইনিশিয়াল ব্লক ব্যবহার করে ।