চূড়ান্ত বস্তুটি কেন সংশোধন করা যেতে পারে?


90

আমি যে কোড ভিত্তিতে কাজ করছি তার মধ্যে নিম্নলিখিত কোডগুলি জুড়ে এসেছি:

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }

    public static void addProvider(ConfigurationProvider provider) {
        INSTANCE.providers.add(provider);
    }

    ...

INSTANCEহিসাবে ঘোষণা করা হয় final। কেন বস্তু যুক্ত করা যেতে পারে INSTANCE? চূড়ান্ত ব্যবহার অকার্যকর করা উচিত নয়। (এটা হয় না)।

আমি ধরে নিচ্ছি উত্তরটি পয়েন্টার এবং মেমরির সাথে কিছু করতে হবে তবে নিশ্চিতভাবে জানতে চাই।


এই ভুল ধারণাটি প্রায়শই উঠে আসে, এটি একটি প্রশ্ন হিসাবে নয়। প্রায়শই উত্তর বা মন্তব্য হিসাবে।
রবিন

4
জেএলএসের সহজ ব্যাখ্যা: "যদি একটি চূড়ান্ত ভেরিয়েবল কোনও জিনিসের সাথে একটি রেফারেন্স ধরে রাখে তবে বস্তুর ক্রিয়াকলাপের মাধ্যমে বস্তুর অবস্থা পরিবর্তিত হতে পারে, তবে ভেরিয়েবল সর্বদা একই বস্তুকে বোঝায়।" জেএলএস ডকুমেন্টেশন
রিয়েলপিকে

উত্তর:


163

finalকেবল অবজেক্ট রেফারেন্সকে অপরিবর্তনীয় করে তোলে । এটি যে বস্তুটির দিকে ইঙ্গিত করে তা এটি করে স্থায়ী নয়। INSTANCEকখনই অন্য কোনও অবজেক্টকে উল্লেখ করতে পারে না তবে এটি যে অবজেক্টটিকে নির্দেশ করে তা রাষ্ট্রের পরিবর্তন হতে পারে।


4
+1, আরও তথ্যের জন্য দয়া করে java.sun.com/docs/books/jls/second_edition/html/… , বিভাগ 4.5.4 দেখুন।
আবেল

সুতরাং আসুন আমি বলি যে আমি কোনও ConfigurationServiceঅবজেক্টের ডিসিরিয়ালাইজ করেছি এবং আমি একটি ইনস্ট্যান্স করার চেষ্টা করব = deserializedConfigurationServiceঅনুমতি দেওয়া হবে না?
ডায়গোগুইলার

আপনি কখনই INSTANCEঅন্য কোনও অবজেক্টের জন্য নিযুক্ত করতে পারেন নি could অন্য বিষয়টি কোথা থেকে এসেছে তা বিবেচ্য নয়। (এনবি এই ক্লাসটি লোড করেছে এমন INSTANCEপ্রতি জন ClassLoaderরয়েছে theory আপনি তত্ত্বের ভিত্তিতে একটি জেভিএমে ক্লাসটি বেশ কয়েকবার লোড করতে পারেন এবং প্রতিটি পৃথক। তবে এটি একটি আলাদা, প্রযুক্তিগত বিষয়))
সান

অখিল আমার উত্তরে আপনার সম্পাদনাটি এটি ভুল করেছে; এটি আসলে বাক্যটির অনুভূতিটিকে বিপরীত করেছিল, যা সঠিক ছিল। রেফারেন্স পরিবর্তনযোগ্য। বস্তু পরিবর্তনযোগ্য হয়। এটি "অপরিবর্তনীয় হয়ে ওঠে না"।
শন

আমি যে সম্পাদনাটি করেছি তার জন্য @ সানওউন স্রাই, আপনার বক্তব্যটি পুরোপুরি সঠিক এবং ধন্যবাদ।
অখিলগাইট

33

চূড়ান্ত হওয়া অপরিবর্তনীয় হওয়ার মতো নয়।

final != immutable

finalশব্দ নিশ্চিত রেফারেন্স পরিবর্তিত না হয় করতে ব্যবহার করা হয় (যে, রেফারেন্স এটি একটি নতুন এক দ্বারা প্রতিস্থাপিত করা যাবে না)

তবে, বৈশিষ্ট্যটি যদি স্ব পরিবর্তনযোগ্য হয় তবে আপনি স্রেফ যা বর্ণনা করেছেন তা করা ঠিক হবে।

এই ক্ষেত্রে

class SomeHighLevelClass {
    public final MutableObject someFinalObject = new MutableObject();
}

আমরা যদি এই ক্লাসটি ইনস্ট্যান্ট করি তবে আমরা চূড়ান্তsomeFinalObject হওয়ায় বৈশিষ্ট্যের জন্য অন্য মান নির্ধারণ করতে পারব না ।

সুতরাং এটি সম্ভব নয়:

....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor  = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final

তবে যদি বস্তুটি এটি নিজেই পরিবর্তিত হয়:

class MutableObject {
     private int n = 0;

     public void incrementNumber() {
         n++;
     }
     public String toString(){
         return ""+n;
     }
}  

তারপরে, সেই পরিবর্তনীয় বস্তুর অন্তর্ভুক্ত মানটি পরিবর্তন করা যেতে পারে।

SomeHighLevelClass someObject = new SomeHighLevelClass();

someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();

System.out.println( someObject.someFinal ); // prints 3

এটিতে আপনার পোস্টের একই প্রভাব রয়েছে:

public static void addProvider(ConfigurationProvider provider) {
    INSTANCE.providers.add(provider);
}

এখানে আপনি ইনস্ট্যান্টের মান পরিবর্তন করছেন না, আপনি এর অভ্যন্তরীণ অবস্থাটি সংশোধন করছেন (মাধ্যমে, সরবরাহকারী.এডিডি পদ্ধতি)

আপনি যদি প্রতিরোধ করতে চান যে শ্রেণীর সংজ্ঞাটি এভাবে পরিবর্তন করা উচিত:

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }
    // Avoid modifications      
    //public static void addProvider(ConfigurationProvider provider) {
    //    INSTANCE.providers.add(provider);
    //}
    // No mutators allowed anymore :) 
....

তবে, এটি খুব বেশি অর্থবহ হতে পারে না :)

যাইহোক, আপনাকে একই কারণে অ্যাক্সেসটি সিঙ্ক্রোনাইজ করতে হবে


26

ভুল বোঝাবুঝির মূল কথাটি আপনার প্রশ্নের শিরোনামে। এটা না বস্তুর যা চূড়ান্ত, এটা পরিবর্তনশীল । ভেরিয়েবলের মান পরিবর্তন করতে পারে না, তবে এর মধ্যে থাকা ডেটাগুলি পারে।

সর্বদা মনে রাখবেন যে আপনি যখন কোনও রেফারেন্স টাইপ ভেরিয়েবল ঘোষণা করেন, তখন সেই ভেরিয়েবলের মান একটি রেফারেন্স হয়, কোনও অবজেক্ট নয়।


11

চূড়ান্ত মানে রেফারেন্স পরিবর্তন করা যায় না। এটি INSTANCE কে চূড়ান্ত হিসাবে ঘোষণা করা হলে আপনি অন্য রেফারেন্সে পুনরায় নিয়োগ দিতে পারবেন না। বস্তুর অভ্যন্তরীণ অবস্থা এখনও পরিবর্তনযোগ্য।

final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;

একটি সংকলন ত্রুটি নিক্ষেপ করবে


7

একবার কোনও finalভেরিয়েবল নির্ধারিত হয়ে গেলে এটিতে সর্বদা একই মান থাকে। যদি কোনও finalভেরিয়েবল কোনও অবজেক্টের রেফারেন্স ধরে রাখে, তবে বস্তুর ক্রিয়াকলাপের সাহায্যে অবজেক্টের অবস্থা পরিবর্তিত হতে পারে তবে ভেরিয়েবল সর্বদা একই বস্তুকে উল্লেখ করবে। এটি অ্যারেগুলিতেও প্রযোজ্য, কারণ অ্যারেগুলি বস্তু; যদি কোনও finalভেরিয়েবল একটি অ্যারের রেফারেন্স ধরে রাখে, তবে অ্যারের ক্রিয়াকলাপ দ্বারা অ্যারের উপাদানগুলি পরিবর্তন করা যেতে পারে তবে ভেরিয়েবল সর্বদা একই অ্যারেগুলিকে উল্লেখ করবে।

উৎস

কোনও বস্তুকে অপরিবর্তনীয় করে তোলার বিষয়ে এখানে গাইড ।


4

চূড়ান্ত এবং অপরিবর্তনীয় এক জিনিস নয়। চূড়ান্ত মানে রেফারেন্সকে পুনরায় নিয়োগ দেওয়া যাবে না তাই আপনি বলতে পারবেন না

INSTANCE = ...

অপরিবর্তনীয় মানে হ'ল বস্তুটি নিজেই সংশোধন করা যায় না। এর উদাহরণ java.lang.Stringক্লাস। আপনি কোনও স্ট্রিংয়ের মান পরিবর্তন করতে পারবেন না।


2

জাভা ভাষায় অন্তর্ভুক্ত অপরিবর্তনের ধারণা নেই have কোনও মিউটর হিসাবে পদ্ধতি চিহ্নিত করার উপায় নেই। অতএব ভাষার অবজেক্টের অপরিবর্তনীয়তা প্রয়োগের কোনও উপায় নেই।

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