ল্যাম্বডা এক্সপ্রেশনে ব্যবহৃত পরিবর্তনশীল চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত হওয়া উচিত


134

ল্যাম্বডা এক্সপ্রেশনে ব্যবহৃত পরিবর্তনশীল চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত হওয়া উচিত

আমি calTzএটি ব্যবহার করার চেষ্টা করার সময় এই ত্রুটিটি দেখানো হচ্ছে।

private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
    try {
        cal.getComponents().getComponents("VTIMEZONE").forEach(component -> {
            VTimeZone v = (VTimeZone) component;
            v.getTimeZoneId();
            if (calTz == null) {
                calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
            }
        });
    } catch (Exception e) {
        log.warn("Unable to determine ical timezone", e);
    }
    return null;
}

5
আপনি calTzল্যাম্বডা থেকে পরিবর্তন করতে পারবেন না ।
এলিয়ট ফ্রিচ

2
আমি ধরে নিয়েছিলাম এটি জাভা ৮ এর জন্য ঠিক সময়ে সম্পন্ন হয়নি এমন একটি জিনিস But তবে জাভা 8 ছিল 2014 Sc জাভা কি কখনও এই অদ্ভুত সীমাবদ্ধতা দূর করার পরিকল্পনা করে?
গ্লেনপিটারসন

5
এখানে @ এমএসডসটি'র মন্তব্যে আপডেট হওয়া লিঙ্ক।
geisterfurz007

আমি মনে করি আপনি কমপ্লিটেটি ফিউচারকে একটি কর্মফল হিসাবে ব্যবহার করতে পারেন।
ক্রাউলাইন

একটি গুরুত্বপূর্ণ বিষয় আমি পর্যবেক্ষণ করেছি - আপনি স্বাভাবিক ভেরিয়েবলের পরিবর্তে স্থিতিশীল ভেরিয়েবলগুলি ব্যবহার করতে পারেন (এটি আমার ধারণা কার্যকরভাবে চূড়ান্ত করে তোলে)
কাউশাল্রনভ

উত্তর:


68

একটি finalপরিবর্তনশীল মানে এটি কেবল একবারে ইনস্ট্যান্ট করা যেতে পারে। জাভাতে আপনি লাম্বদা এবং বেনামে অভ্যন্তরীণ ক্লাসে নন-ফাইনাল ভেরিয়েবলগুলি ব্যবহার করতে পারবেন না।

পুরানো প্রতিটি লুপের সাথে আপনি নিজের কোডটি রিফ্যাক্টর করতে পারেন:

private TimeZone extractCalendarTimeZoneComponent(Calendar cal,TimeZone calTz) {
    try {
        for(Component component : cal.getComponents().getComponents("VTIMEZONE")) {
        VTimeZone v = (VTimeZone) component;
           v.getTimeZoneId();
           if(calTz==null) {
               calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
           }
        }
    } catch (Exception e) {
        log.warn("Unable to determine ical timezone", e);
    }
    return null;
}

এমনকি আমি এই কোডটির কয়েকটি টুকরোটির বুদ্ধি না পেলেও:

  • আপনি v.getTimeZoneId();তার রিটার্ন মানটি ব্যবহার না করে কল করুন
  • অ্যাসাইনমেন্টের সাথে calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());আপনি মূলত পাস হওয়াটি সংশোধন করবেন না calTzএবং আপনি এই পদ্ধতিতে এটি ব্যবহার করবেন না
  • আপনি সবসময় ফিরবেন null, আপনি voidরিটার্নের ধরণ হিসাবে সেট করবেন না কেন ?

আশা করি এই টিপসটি আপনাকে উন্নত করতে সহায়তা করবে।


আমরা নন ফাইনাল স্ট্যাটিক ভেরিয়েবলগুলি ব্যবহার করতে পারি
নরেন্দ্র জাগি

92

যদিও অন্যান্য উত্তরগুলি প্রয়োজনীয়তা প্রমাণ করে, প্রয়োজনীয়তা কেন বিদ্যমান তা তারা ব্যাখ্যা করে না ।

জেএলএস কেন §15.27.2 এ উল্লেখ করেছে :

কার্যকরভাবে চূড়ান্ত ভেরিয়েবলের সীমাবদ্ধতা স্থানীয় পরিবর্তনশীলগুলির পরিবর্তনশীল-পরিবর্তনগুলিতে অ্যাক্সেসকে নিষিদ্ধ করে, যার ক্যাপচারটি সম্ভবত সম্মতিযুক্ত সমস্যাগুলি প্রবর্তন করবে।

বাগের ঝুঁকি হ্রাস করার জন্য, তারা সিদ্ধান্ত নিয়েছে যে ক্যাপচার করা ভেরিয়েবলগুলি কখনই পরিবর্তিত হবে না।


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

2
কোনও ধারণা কেন এটি কেবল স্থানীয় ভেরিয়েবলগুলিতেই সীমাবদ্ধ, এবং শ্রেণি সদস্যরা নয়? আমি নিজেকে প্রায়শই ক্লাসের সদস্য হিসাবে আমার ভেরিয়েবল ঘোষণা করে সমস্যাটি স্রষ্টা করে দেখতে পাই ...
ডেভিড রেফেলি

4
@ ডেভিডেফেলি ক্লাসের সদস্যরা মেমরির মডেল দ্বারা আচ্ছাদিত / প্রভাবিত, যা অনুসরণ করা হলে ভাগ করে নেওয়ার পরে অনুমানযোগ্য ফলাফল আনতে পারে। যেমন উল্লেখ স্থানীয় ভেরিয়েবল নয়, §17.4.1
ডাইঅক্সিন

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

@JoshM। সি # আপনাকে মিউটেটেবল মান ধরণের তৈরি করতেও মঞ্জুরি দেয় যা লোকে সমস্যাগুলি রোধ করতে এড়ানো পরামর্শ দেয়। জাভা এ জাতীয় নীতিগুলি না থাকার পরিবর্তে এটি সম্পূর্ণরূপে প্রতিরোধের সিদ্ধান্ত নিয়েছে। এটি ব্যবহারকারীর ত্রুটি কমিয়ে দেয় নমনীয়তার মূল্যে। আমি এই বিধিনিষেধের সাথে একমত নই, তবে এটি ন্যায়সঙ্গত। সমান্তরালতার জন্য অ্যাকাউন্টিংয়ের জন্য কম্পাইলারের শেষের দিকে কিছু অতিরিক্ত কাজ করা দরকার, সম্ভবত এটি কারণেই " ক্রস-থ্রেডেড অ্যাক্সেসের সতর্কতা " রুট নেওয়া হয়নি। অনুমানে কাজ করা কোনও বিকাশকারী সম্ভবত এটির জন্য আমাদের একমাত্র নিশ্চিতকরণ।
ডায়াক্সিন

57

ল্যাম্বডা থেকে, আপনি চূড়ান্ত নয় এমন কোনও জিনিসের রেফারেন্স পেতে পারেন না। আপনার ভেরিয়েবলটি ধরে রাখতে আপনাকে লামদার বাইরে থেকে একটি চূড়ান্ত মোড়ক দেওয়ার দরকার to

আমি এই আবরণ হিসাবে চূড়ান্ত 'রেফারেন্স' অবজেক্ট যুক্ত করেছি।

private TimeZone extractCalendarTimeZoneComponent(Calendar cal,TimeZone calTz) {
    final AtomicReference<TimeZone> reference = new AtomicReference<>();

    try {
       cal.getComponents().getComponents("VTIMEZONE").forEach(component->{
        VTimeZone v = (VTimeZone) component;
           v.getTimeZoneId();
           if(reference.get()==null) {
               reference.set(TimeZone.getTimeZone(v.getTimeZoneId().getValue()));
           }
           });
    } catch (Exception e) {
        //log.warn("Unable to determine ical timezone", e);
    }
    return reference.get();
}   

আমি একই বা অনুরূপ পদ্ধতির বিষয়ে ভাবছিলাম - তবে আমি এই উত্তর সম্পর্কে কিছু বিশেষজ্ঞের পরামর্শ / প্রতিক্রিয়া দেখতে চাই?
YoYo

4
এই কোডটি একটি প্রাথমিক মিস করে reference.set(calTz);বা রেফারেন্সটি ব্যবহার করে অবশ্যই তৈরি করা উচিত new AtomicReference<>(calTz), অন্যথায় প্যারামিটার হিসাবে প্রদত্ত নন-নাল টাইমজোনটি হারিয়ে যাবে।
জুলিয়েন ক্রোনেগ

7
এটি প্রথম উত্তর হওয়া উচিত। একটি পারমাণবিক রেফারেন্স (বা অনুরূপ পারমাণবিক___ বর্গ) প্রতিটি সম্ভাব্য পরিস্থিতিতে নিরাপদে এই সীমাবদ্ধতার চারপাশে কাজ করে।
গ্লেনপিটারসন

1
সম্মত, এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। অন্যান্য উত্তরগুলি কীভাবে একটি অ-কার্যকরী প্রোগ্রামিং মডেলের পিছনে পড়ে যায় এবং কেন এটি করা হয়েছিল সে সম্পর্কে দরকারী তথ্য দেয় তবে কীভাবে সমস্যাটি ঘটাতে হবে তা আসলে আপনাকে বলবেন না!
জোনাথন বেন

2
@ গ্লেনপিটারসন এবং এটি একটি ভয়াবহ সিদ্ধান্ত, এটি কেবল এইভাবেই খুব ধীর হয় না, তবে ডকুমেন্টেশন অনুসারে যে পার্শ্ব-প্রতিক্রিয়াযুক্ত সম্পত্তি রয়েছে তা আপনি এড়িয়ে যাচ্ছেন।
ইউজিন

41

জাভা 8 এর একটি নতুন ধারণা রয়েছে "কার্যকরভাবে চূড়ান্ত" ভেরিয়েবল। এর অর্থ হ'ল একটি চূড়ান্ত চূড়ান্ত স্থানীয় পরিবর্তনশীল যার মান আরম্ভের পরে কখনও পরিবর্তিত হয় না তাকে "কার্যকরভাবে চূড়ান্ত" বলা হয়।

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

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

জাভা 8 প্রতিবার কোনও বিকাশকারী ল্যাম্বডা ব্যবহার করে এই পরিবর্তনটি চূড়ান্ত ঘোষণা করার ব্যথা বুঝতে পেরেছিল এবং স্থানীয় ভেরিয়েবলগুলিকে চূড়ান্ত করতে অপ্রয়োজনীয় করে তুলেছে। সুতরাং আপনি যদি বেনামে ক্লাসের নিয়মটি পরিবর্তন করেন না, finalল্যাম্বডাস ব্যবহার করার সময় আপনাকে প্রতিবার কীওয়ার্ডটি লিখতে হবে না ।

আমি একটি ভাল ব্যাখ্যা পাওয়া এখানে


কোড বিন্যাস কেবলমাত্র কোডের জন্য ব্যবহার করা উচিত , সাধারণভাবে প্রযুক্তিগত পদগুলির জন্য নয়। effectively finalকোড নয়, এটি পরিভাষা। কোড-বিন্যাসের জন্য কোড ফর্ম্যাটিং কখন ব্যবহার করা উচিত দেখুন ? উপর মেটা স্ট্যাক ওভারফ্লো
চার্লস ডাফি

(সুতরাং " finalকীওয়ার্ড" হ'ল কোড শব্দ এবং সেভাবে ফর্ম্যাট করার জন্য সঠিক, তবে আপনি কোড হিসাবে বর্ণনার পরিবর্তে বর্ণনামূলকভাবে "চূড়ান্ত" ব্যবহার করেন, পরিবর্তে এটি পরিভাষা হয়)।
চার্লস ডাফি

9

আপনার উদাহরণস্বরূপ, আপনি forEachলামড্বাবাকে একটি সাধারণ forলুপের সাথে প্রতিস্থাপন করতে পারেন এবং যেকোন পরিবর্তনশীল অবাধে পরিবর্তন করতে পারেন। অথবা, সম্ভবত, আপনার কোডটি রিফ্যাক্টর করুন যাতে আপনার কোনও ভেরিয়েবল পরিবর্তন করার প্রয়োজন হয় না। যাইহোক, আমি ত্রুটিটির অর্থ কী এবং কীভাবে এটি ঘিরে কাজ করা যায় তার সম্পূর্ণতার জন্য ব্যাখ্যা করব।

জাভা 8 ভাষা নির্দিষ্টকরণ, .215.27.2 :

যে কোনও স্থানীয় ভেরিয়েবল, আনুষ্ঠানিক প্যারামিটার বা ব্যতিক্রম প্যারামিটার ব্যবহার করা হলেও ল্যাম্বডা এক্সপ্রেশনে ঘোষিত হয়নি তা হয় চূড়ান্তভাবে ঘোষণা করতে হবে বা কার্যকরভাবে চূড়ান্ত হতে হবে ( .14.12.4 ), অথবা একটি সংকলন-সময় ত্রুটি দেখা দেয় যেখানে ব্যবহারের চেষ্টা করা হয়।

মূলত আপনি calTzল্যাম্বডা (বা স্থানীয় / বেনাম শ্রেণীর) থেকে কোনও স্থানীয় ভেরিয়েবল ( এই ক্ষেত্রে) সংশোধন করতে পারবেন না । জাভাতে তা অর্জন করতে আপনাকে ল্যাম্বডা থেকে একটি পরিবর্তনীয় অবজেক্ট ব্যবহার করতে হবে এবং এটিকে (চূড়ান্ত ভেরিয়েবলের মাধ্যমে) পরিবর্তন করতে হবে। এখানে পরিবর্তিত বস্তুর একটি উদাহরণ একটি উপাদানের অ্যারে হবে:

private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
    TimeZone[] result = { null };
    try {
        cal.getComponents().getComponents("VTIMEZONE").forEach(component -> {
            ...
            result[0] = ...;
            ...
        }
    } catch (Exception e) {
        log.warn("Unable to determine ical timezone", e);
    }
    return result[0];
}

আরেকটি উপায় হ'ল কোনও বস্তুর ক্ষেত্র ব্যবহার করা। উদাহরণস্বরূপ MyObj ফলাফল = নতুন MyObj (); ...; ফলাফল.টাইমজোন = ...; ....; রিটার্ন রেজাল্ট.টাইমজোন; যদিও নোট করুন, এটি উপরে বর্ণিত হিসাবে, এটি আপনাকে থ্রেড-সুরক্ষা সমস্যাগুলিতে প্রকাশ করে। দেখুন stackoverflow.com/a/50341404/7092558
Gibezynu নু

0

যদি এই ধরণের সমস্যার জন্য সাধারণ কাজের তুলনায় ভেরিয়েবলটি সংশোধন করার প্রয়োজন না হয় তবে ল্যাম্বডা ব্যবহার করে এমন কোডের অংশটি বের করতে হবে এবং পদ্ধতি-পরামিতিতে চূড়ান্ত কীওয়ার্ড ব্যবহার করা হবে।


0

ল্যাম্বডা এক্সপ্রেশনটিতে ব্যবহৃত একটি পরিবর্তনশীল একটি চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত হওয়া উচিত, তবে আপনি একটি চূড়ান্ত এক উপাদান অ্যারের মান নির্ধারণ করতে পারেন।

private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
    try {
        TimeZone calTzLocal[] = new TimeZone[1];
        calTzLocal[0] = calTz;
        cal.getComponents().get("VTIMEZONE").forEach(component -> {
            TimeZone v = component;
            v.getTimeZoneId();
            if (calTzLocal[0] == null) {
                calTzLocal[0] = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
            }
        });
    } catch (Exception e) {
        log.warn("Unable to determine ical timezone", e);
    }
    return null;
}

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