অভ্যন্তরীণ শ্রেণীর অবজেক্ট থেকে বাইরের শ্রেণীর অবজেক্টটি ধরে রাখা


245

আমার কাছে নিম্নলিখিত কোড রয়েছে। আমি বাইরের শ্রেণীর অবজেক্টটি ধরে রাখতে চাই যা ব্যবহার করে আমি অভ্যন্তরীণ শ্রেণীর অবজেক্টটি তৈরি করেছি inner। আমি এটা কিভাবে করবো?

public class OuterClass {

    public class InnerClass {
        private String name = "Peakit";
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        InnerClass inner = outer.new InnerClass();
       // How to get the same outer object which created the inner object back?
        OuterClass anotherOuter = ?? ;

        if(anotherOuter == outer) {
             System.out.println("Was able to reach out to the outer object via inner !!");
        } else {
             System.out.println("No luck :-( ");
        }
    }
}

সম্পাদনা: আচ্ছা, আপনারা কেউ কেউ একটি পদ্ধতি যুক্ত করে অভ্যন্তরীণ শ্রেণিকে সংশোধন করার পরামর্শ দিয়েছেন:

public OuterClass outer() {
   return OuterClass.this;
}

তবে যদি আমার অভ্যন্তরীণ বর্গটি সংশোধন করার নিয়ন্ত্রণ না থাকে, তবে (কেবলমাত্র নিশ্চিত করার জন্য) আমাদের অভ্যন্তরীণ শ্রেণীর অবজেক্ট থেকে সংশ্লিষ্ট বহিরাগত শ্রেণি অবজেক্টটি পাওয়ার আরও কিছু উপায় আছে?

উত্তর:


329

অভ্যন্তর শ্রেণীর মধ্যেই, আপনি ব্যবহার করতে পারেন OuterClass.this। এই এক্সপ্রেশনটি, যা কোনও লেকসুলভ এনকোলেসিং উদাহরণকে উল্লেখ করতে দেয়, জেএলএসে যোগ্যthis হিসাবে বর্ণিত হয়েছে ।

আমি মনে করি না যদিও অভ্যন্তর শ্রেণীর কোডের বাইরে থেকে উদাহরণটি পাওয়ার কোনও উপায় আছে। অবশ্যই, আপনি সর্বদা নিজের সম্পত্তি প্রবর্তন করতে পারেন:

public OuterClass getOuter() {
    return OuterClass.this;
}

সম্পাদনা: পরীক্ষা-নিরীক্ষার মাধ্যমে, দেখে মনে হচ্ছে যে বাইরের শ্রেণীর রেফারেন্স ধারণ ক্ষেত্রটির প্যাকেজ স্তরের অ্যাক্সেস রয়েছে - কমপক্ষে আমি জেডিকে ব্যবহার করছি।

সম্পাদনা করুন: ব্যবহৃত (নাম this$0) হয় , আসলে জাভা বৈধ যদিও JLS এর ব্যবহার নিরুৎসাহিত:

$চরিত্রটি কেবল যান্ত্রিকভাবে উত্পন্ন উত্স কোডে ব্যবহার করা উচিত বা খুব কমই, উত্তরাধিকার সিস্টেমে প্রাক-বিদ্যমান নামগুলি অ্যাক্সেস করতে।


ধন্যবাদ জন! তবে যদি আমার অভ্যন্তরীণ শ্রেণীটি সংশোধন করার নিয়ন্ত্রণ না থাকে (আমার সম্পাদনা পরীক্ষা করুন)।
শিখর

7
@ পেইকিট: তারপরে যতদূর আমি জানি, আপনি প্রতিবিম্বটি ব্যবহার না করা আপনার ভাগ্য থেকে দূরে। মনে হচ্ছে এটি সত্যই যদিও এনক্যাপসুলেশন লঙ্ঘন - যদি অভ্যন্তরীণ শ্রেণি আপনাকে এর বাহ্যিক দৃষ্টান্তটি কী বলতে চায় না তবে আপনার এটি সম্মান করা উচিত এবং এমন নকশা করার চেষ্টা করা উচিত যা আপনার প্রয়োজন নেই।
জন স্কিটি

1
এটি এখনও জাভা 8 এ বৈধ?
misty

@ মিস্টি হ্যাঁ, এটি।
হাটফিন্ড

36

OuterClass.this বাইরের শ্রেণীর রেফারেন্স।


7
তবে কেবল আউটারক্লাসের উত্সের মধ্যে / এর মধ্যে। এবং আমি মনে করি না যে ওপি এটি চায়।
স্টিফেন সি

23

আপনি (তবে আপনার উচিত নয়) কাজের প্রতিচ্ছবি ব্যবহার করতে পারেন:

import java.lang.reflect.Field;

public class Outer {
    public class Inner {
    }

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

        // Create the inner instance
        Inner inner = new Outer().new Inner();

        // Get the implicit reference from the inner to the outer instance
        // ... make it accessible, as it has default visibility
        Field field = Inner.class.getDeclaredField("this$0");
        field.setAccessible(true);

        // Dereference and cast it
        Outer outer = (Outer) field.get(inner);
        System.out.println(outer);
    }
}

অবশ্যই, অন্তর্নিহিত রেফারেন্সের নামটি সম্পূর্ণ অবিশ্বাস্য, তাই আমি যেমন বলেছিলাম, আপনার উচিত হবে না :-)


2

এই প্রশ্নের আরও সাধারণ উত্তরের মধ্যে ছায়াযুক্ত ভেরিয়েবল এবং সেগুলি কীভাবে অ্যাক্সেস করা হয় তা জড়িত।

নিম্নলিখিত উদাহরণে (ওরাকল থেকে) সালে পরিবর্তনশীল x এর মধ্যে মেন () ছায়াকরণ হয় Test.x :

class Test {
    static int x = 1;
    public static void main(String[] args) {
        InnerClass innerClassInstance = new InnerClass()
        {
            public void printX()
            {
                System.out.print("x=" + x);
                System.out.println(", Test.this.x=" + Test.this.x);
            }
        }
        innerClassInstance.printX();
    }

    public abstract static class InnerClass
    {
        int x = 0;

        public InnerClass() { }

        public abstract void printX();
    }
}

এই প্রোগ্রামটি চালানো মুদ্রণ করবে:

x=0, Test.this.x=1

আরও এখানে: http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6


উদাহরণটি পয়েন্টটি সর্বোত্তম প্রমাণ করেছে তা নিশ্চিত নন কারণ "টেস্ট.থিস.এক্স" "টেস্ট.এক্স" এর সমান কারণ এটি স্থির, সত্যই এটি ঘেরযুক্ত শ্রেণি অবজেক্টের সাথে সম্পর্কিত নয়। আমি মনে করি কোডটি যদি ক্লাস টেস্ট এবং টেস্ট.এক্স.র স্থায়ী না হয়ে কনস্ট্রাক্টরে থাকে তবে এর চেয়ে ভাল উদাহরণ হতে পারে।
sb4

0

উদাহরণটি এখানে:

// Test
public void foo() {
    C c = new C();
    A s;
    s = ((A.B)c).get();
    System.out.println(s.getR());
}

// classes
class C {}

class A {
   public class B extends C{
     A get() {return A.this;}
   }
   public String getR() {
     return "This is string";
   }
}

0

যদি আপনার অভ্যন্তর শ্রেণিকে সংশোধন করার নিয়ন্ত্রণ না থাকে তবে রিফেকশন আপনাকে সহায়তা করতে পারে (তবে প্রস্তাব দিচ্ছে না)। এই $ 0টি অভ্যন্তর শ্রেণিতে উল্লেখ করা হয় যা জানায় যে অভ্যন্তর শ্রেণীর বর্তমান উদাহরণ তৈরি করতে আউটার শ্রেণির কোন উদাহরণ ব্যবহৃত হয়েছিল।


-1
/**
 * Not applicable to Static Inner Class (nested class)
 */
public static Object getDeclaringTopLevelClassObject(Object object) {
    if (object == null) {
        return null;
    }
    Class cls = object.getClass();
    if (cls == null) {
        return object;
    }
    Class outerCls = cls.getEnclosingClass();
    if (outerCls == null) {
        // this is top-level class
        return object;
    }
    // get outer class object
    Object outerObj = null;
    try {
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            if (field != null && field.getType() == outerCls
                    && field.getName() != null && field.getName().startsWith("this$")) {
                field.setAccessible(true);
                outerObj = field.get(object);
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return getDeclaringTopLevelClassObject(outerObj);
}

অবশ্যই, অন্তর্নিহিত রেফারেন্সের নামটি অবিশ্বাস্য, সুতরাং আপনার কাজের প্রতিচ্ছবি ব্যবহার করা উচিত নয়।


'স্ট্যাটিক ইনার' শর্তে একটি বৈপরীত্য।
মার্নকুইস অফ লর্ন

-2

2020-06-15 এ সম্পাদিত হয়েছে

public class Outer {

    public Inner getInner(){
        return new Inner(this);
    }

    static class Inner {

        public final Outer Outer;

        public Inner(Outer outer) {
            this.Outer=outer;
        }
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        Inner inner = outer.getInner();
        Outer anotherOuter=inner.Outer;

        if(anotherOuter == outer) {
            System.out.println("Was able to reach out to the outer object via inner !!");
        } else {
            System.out.println("No luck :-( ");
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.