java شرح فئة جافا الداخلية ودرجة متداخلة ثابتة




inner class in java شرح (19)

ما هو الفرق الرئيسي بين الطبقة الداخلية والفئة المتداخلة الثابتة في Java؟ هل يلعب التصميم / التنفيذ دورًا في اختيار واحد من هؤلاء؟


When we declare static member class inside a class, it is known as top level nested class or a static nested class. It can be demonstrated as below :

class Test{
    private static int x = 1;
        static class A{
        private static int y = 2;
        public static int getZ(){
            return B.z+x;
        }
    }
    static class B{
        private static int z = 3;
        public static int getY(){
            return A.y;
        }
    }
}

class TestDemo{
     public static void main(String[] args){
        Test t = new Test();
        System.out.println(Test.A.getZ());
        System.out.println(Test.B.getY());
    }
}

When we declare non-static member class inside a class it is known as inner class. Inner class can be demonstrated as below :

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}

هناك دقة حول استخدام الطبقات الثابتة المتداخلة التي قد تكون مفيدة في بعض المواقف.

في حين يتم الحصول على إنشاء سمات ثابتة قبل أن يتم إنشاء الطبقة عبر مُنشئها ، لا يبدو أن السمات الثابتة داخل الطبقات الثابتة المتداخلة يتم الحصول عليها حتى يتم استدعاء مُنشئ الصف ، أو على الأقل حتى بعد الإشارة لأول مرة إلى السمات ، حتى إذا يتم وضع علامة "نهائي".

خذ بعين الاعتبار هذا المثال:

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

على الرغم من أن "المتداخلة" و "innerItem" يتم الإعلان عنها على أنها "نهائية ثابتة". لا يتم إجراء الإعداد nested.innerItem إلا بعد أن يتم إنشاء classly (أو على الأقل ليس حتى بعد الإشارة إلى العنصر الثابت المتداخلة أولاً) ، كما يمكنك أن ترى بنفسك عن طريق التعليق وإلغاء كتابة الخطوط التي أشرت إليها ، في الاعلى. نفس الشيء لا ينطبق على "outerItem".

على الأقل هذا ما أراه في Java 6.0.


The following is an example of static nested class and inner class :

OuterClass.java

public class OuterClass {
     private String someVariable = "Non Static";

     private static String anotherStaticVariable = "Static";  

     OuterClass(){

     }

     //Nested classes are static
     static class StaticNestedClass{
        private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable"; 

        //can access private variables declared in the outer class
        public static void getPrivateVariableofOuterClass(){
            System.out.println(anotherStaticVariable);
        }
     }

     //non static
     class InnerClass{

         //can access private variables of outer class
         public String getPrivateNonStaticVariableOfOuterClass(){
             return someVariable;
         }
     }

     public static void accessStaticClass(){
         //can access any variable declared inside the Static Nested Class 
         //even if it private
         String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable; 
         System.out.println(var);
     }

}

OuterClassTest:

public class OuterClassTest {
    public static void main(String[] args) {

        //access the Static Nested Class
        OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();

        //test the private variable declared inside the static nested class
        OuterClass.accessStaticClass();
        /*
         * Inner Class Test
         * */

        //Declaration

        //first instantiate the outer class
        OuterClass outerClass = new OuterClass();

        //then instantiate the inner class
        OuterClass.InnerClass innerClassExample =  outerClass. new InnerClass();

        //test the non static private variable
        System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass()); 

    }

}

Ummm... an inner class IS a nested class... do you mean anonymous class and inner class?

Edit: If you actually meant inner vs anonymous... an inner class is just a class defined within a class such as:

public class A {
    public class B {
    }
}

Whereas an anonymous class is an extension of a class defined anonymously, so no actual "class is defined, as in:

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };

Further Edit:

Wikipedia claims there is a difference in Java, but I've been working with Java for 8 years, and it's the first I heard such a distinction... not to mention there are no references there to back up the claim... bottom line, an inner class is a class defined within a class (static or not), and nested is just another term to mean the same thing.

There is a subtle difference between static and non-static nested class... basically non-static inner classes have implicit access to instance fields and methods of the enclosing class (thus they cannot be constructed in a static context, it will be a compiler error). Static nested classes, on the other hand, don't have implicit access to instance fields and methods, and CAN be constructed in a static context.


أعتقد أن الاتفاقية المتبعة بشكل عام هي:

  • فئة ثابتة داخل فئة المستوى الأعلى هي فئة متداخلة
  • فئة غير ثابتة داخل فئة المستوى الأعلى هي فئة داخلية ، والتي تحتوي أيضًا على شكلين إضافيين:
    • الطبقة المحلية - الفئات المعلنة المعلنة داخل كتلة مثل طريقة أو هيكل منشئ
    • فئة مجهولة - فصول غير مسماة يتم إنشاء المثيلات الخاصة بها في التعبيرات والعبارات

ومع ذلك ، هناك القليل من النقاط الأخرى التي يجب تذكرها هي:

  • تكون الطبقات الأعلى المستوى والفئة المتداخلة الثابتة متساوية معًا ، باستثناء أنه في حالة فئة متداخلة ثابتة ، يمكن أن تجعل مرجعًا ثابتًا للحقول / الأساليب الثابتة الخاصة لفئة [الأصل] الخارجية والعكس صحيح.

  • لدى الطبقات الداخلية حق الوصول إلى متغيرات المثيل المثيل للفئة الخارجية [الأصل]. ومع ذلك ، لا تحتوي كل الطبقات الداخلية على أمثلة ، على سبيل المثال ، الطبقات الداخلية في السياقات الثابتة ، مثل فئة غير معروفة يتم استخدامها في كتلة مبدئية ثابتة ، لا تفعل ذلك.

  • فئة المجهول بشكل افتراضي توسيع الفئة الأصل أو تطبق الواجهة الأصل ولا يوجد أي شرط آخر لتوسيع أي فئة أخرى أو تنفيذ واجهات أكثر. وبالتالي،

    • new YourClass(){}; يعني أن class [Anonymous] extends YourClass {}
    • new YourInterface(){}; تعني class [Anonymous] implements YourInterface {}

أشعر أن السؤال الأكبر ما زال مفتوحا أيهما يستخدم ومتى؟ حسناً ، هذا يعتمد في الغالب على السيناريو الذي تتعامل معه ولكن قراءة الرد الذي قدمهjrudolph قد يساعدك في اتخاذ بعض القرار.


First of all There is no such class called Static class.The Static modifier use with inner class (called as Nested Class) says that it is a static member of Outer Class which means we can access it as with other static members and without having any instance of Outer class. (Which is benefit of static originally.)

Difference between using Nested class and regular Inner class is:

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

First We can to instantiate Outerclass then we Can access Inner.

But if Class is Nested then syntax is:

OuterClass.InnerClass inner = new OuterClass.InnerClass();

Which uses the static Syntax as normal implementation of static keyword.


I think people here should notice to Poster that : Static Nest Class just only the first inner class. فمثلا:

 public static class A {} //ERROR

 public class A {
     public class B {
         public static class C {} //ERROR
     }
 }

 public class A {
     public static class B {} //COMPILE !!!

 }

So, summarize, static class doesn't depend which class its contains. So, they cannot in normal class. (because normal class need an instance).


لا أعتقد أن هناك الكثير الذي يمكن إضافته هنا ، فإن معظم الإجابات تفسر الاختلافات بين الطبقة المتداخلة الثابتة والفصول الداخلية. ومع ذلك ، ضع في الاعتبار المشكلة التالية عند استخدام الفئات المتداخلة مقابل الفئات الداخلية. كما ذكر في بضعة إجابات ، لا يمكن إنشاء الطبقات الداخلية بدون مثيل لفئة الحفظ الخاصة بهم مما يعني أنه قد تم وضع مؤشر إلى فئة الفصول الدراسية الخاصة بهم والتي يمكن أن تؤدي إلى تجاوز الذاكرة أو استبعاد تجاوز السعة بسبب حقيقة أن GC لن تتمكن من جمع القمامة داخل الصفوف حتى إذا لم يتم استخدامها بعد الآن. لجعل هذا واضح تحقق التعليمة البرمجية التالية:

public class Outer {


    public  class Inner {

    }


    public Inner inner(){
        return new Inner();
    }

    @Override
    protected void finalize() throws Throwable {
    // as you know finalize is called by the garbage collector due to destroying an object instance
        System.out.println("I am destroyed !");
    }
}


public static void main(String arg[]) {

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();

    // out instance is no more used and should be garbage collected !!!
    // However this will not happen as inner instance is still alive i.e used, not null !
    // and outer will be kept in memory until inner is destroyed
    outer = null;

    //
    // inner = null;

    //kick out garbage collector
    System.gc();

}

إذا قمت بإزالة التعليق على // inner = null; سيقوم البرنامج بوضع " أنا دمرت! " ، ولكن مع ذلك علقت أنه لن.
والسبب هو أن المثيل الداخلي الأبيض لا يزال يشير إلى أن GC لا يمكنه جمعه ولأنه يشير (له مؤشر إلى) المثيل الخارجي فإنه لا يتم جمعه أيضًا. بعد ما يكفي من هذه الأشياء في مشروعك ويمكن نفاد الذاكرة.
مقارنة بالفئات الداخلية الثابتة التي لا تحتوي على نقطة إلى فئة الطبقة الداخلية لأنها ليست ذات صلة بالمادة ولكنها مرتبطة بالطبقة. يمكن للبرنامج أعلاه طباعة " لقد تم إتلافها! " إذا قمت بإجراء فئة داخلية ثابتة ثم إنشاء مثيل مع Outer.Inner i = new Outer.Inner();


يقول البرنامج التعليمي Java :

المصطلحات: تنقسم الطبقات المتداخلة إلى فئتين: ثابتة وغير ثابتة. تسمى الفئات المتداخلة التي تم تعريفها static ببساطة الفئات المتداخلة الثابتة. تسمى الطبقات المتداخلة غير الثابتة الفئات الداخلية.

في اللغة الشائعة ، يتم استخدام المصطلحين "المتداخل" و "الداخلي" بالتبادل من قبل معظم المبرمجين ، لكنني سأستخدم المصطلح الصحيح "فئة متداخلة" التي تغطي كل من العناصر الداخلية والثابتة.

يمكن أن تكون الفئات متداخلة إلى ما لا نهاية ، على سبيل المثال ، يمكن أن تحتوي الفئة A على الفئة B التي تحتوي على الفئة C التي تحتوي على الفئة D ، وما إلى ذلك. ومع ذلك ، فإن أكثر من مستوى من التعشيش الطبقي نادر ، حيث إنه تصميم سيء بشكل عام.

هناك ثلاثة أسباب تجعلك تنشئ فئة متداخلة:

  • المنظمة: يبدو أحيانًا أكثر منطقية لفرز فئة إلى مساحة اسم فئة أخرى ، خاصة عندما لا يتم استخدامها في أي سياق آخر
  • الوصول: الطبقات المتداخلة لها وصول خاص إلى المتغيرات / الحقول الخاصة بفئاتها التي تحتوي عليها (تحديدًا أي المتغيرات / الحقول تعتمد على نوع الفئة المتداخلة ، سواء كانت داخلية أو ثابتة).
  • الملاءمة: الحاجة إلى إنشاء ملف جديد لكل نوع جديد أمر مزعج ، مرة أخرى ، خاصة عندما يتم استخدام النوع فقط في سياق واحد

هناك أربعة أنواع من الطبقات المتداخلة في Java . باختصار ، هم:

  • فئة ثابتة : أعلن كعضو ثابت في فصل آخر
  • الطبقة الداخلية : أعلن كعضو مثيل في فصل آخر
  • الطبقة الداخلية المحلية : أعلن داخل أسلوب مثيل لفئة أخرى
  • فئة داخلية مجهولة : مثل الطبقة الداخلية المحلية ، ولكن مكتوبة كتعبير يُرجع كائنًا منفردًا

دعوني أوضح تفاصيل أكثر.


فئات ثابتة

الطبقات الثابتة هي أسهل طريقة لفهمها لأنها لا علاقة لها بحالات الطبقة المحتوية.

فئة ثابتة هي فئة تم تعريفها كعضو ثابت في فصل آخر. تمامًا مثل الأعضاء الآخرين الثابتين ، فإن مثل هذه الفئة هي في الواقع مجرد شماعة تستخدم الطبقة المحتوية على أنها مساحة اسمها ، على سبيل المثال ، إعلان طبقة الماعز باعتبارها عضوًا ثابتًا من فئة Rhino في البيتزا المجمعة المعروفة باسم pizza.Rhino.Goat .

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

بصراحة ، تعتبر الفئات الثابتة ميزة لا قيمة لها نظرًا لأن الفئات مقسمة بالفعل إلى مساحات الأسماء بواسطة الحزم. إن السبب الحقيقي الوحيد الذي يمكن تصوره لإنشاء فئة ثابتة هو أن مثل هذه الفئة لديها إمكانية الوصول إلى أعضاء المجموعة الخاصة في الطبقة الثابتة ، لكنني أجد أن هذا مبررًا عجيبًا لميزة الفئة الثابتة في الوجود.


الطبقات الداخلية

الطبقة الداخلية هي فئة معلنة كعضو غير ثابت في فصل آخر:

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

كما هو الحال مع فئة ثابتة ، تُعرف الطبقة الداخلية بأنها مؤهلة من خلال اسم الفئة المحتوي عليها ، pizza.Rhino.Goat ، ولكن داخل الطبقة المحتوية ، يمكن أن تكون معروفة باسمها البسيط. ومع ذلك ، فإن كل حالة من طبقات الطبقة الداخلية ترتبط بنوع معين من الطبقة المحتوية عليها: فغالباً ، ترتبط " الماعز" الذي تم إنشاؤه في جيري ، بشكل ضمني بمثيل الكركدن هذا في جيري . بخلاف ذلك ، نجعل مثيل الكركدن المصاحب صريحًا عندما نقوم بتفعيل Goat :

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

(لاحظ أنك تشير إلى النوع الداخلي كعنصر الماعز فقط في بناء الجملة الجديد الغريب: حيث تقوم Java بتحويل النوع المحتوي من جزء وحيد القرن . و ، نعم ، فإن rhino.Goat () الجديد سيكون أكثر منطقية بالنسبة لي أيضًا.)

إذن ما الذي يربحنا هذا؟ حسنًا ، لدى مثيل الطبقة الداخلية حق الوصول إلى أعضاء مثيل مثيل الفئة المحتوية. تتم الإشارة إلى أعضاء التضمين هذه داخل الصف الداخلي من خلال أسماءهم البسيطة فقط ، وليس عن طريق هذا ( هذا في الطبقة الداخلية يشير إلى مثيل الطبقة الداخلية ، وليس مثيل الفئة المحتوية عليه):

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

في الطبقة الداخلية ، يمكنك الرجوع إلى هذا الفصل من الفئة التي تحتوى على Rhino.this ، ويمكنك استخدام هذا للإشارة إلى أعضائها ، مثل Rhino.this.barry .


فئات داخلية محلية

الطبقة الداخلية المحلية هي فئة معلنة في جسم الطريقة. تُعرف هذه الفئة فقط ضمن طريقة احتوائها ، بحيث يمكن فقط إنشاء مثيل لها والوصول إلى أعضائها ضمن أسلوب احتوائها. الكسب هو أن طبقة داخلية داخلية مرتبطة ويمكن الوصول إلى المتغيرات المحلية النهائية لطريقته المحتوية. عندما يستخدم المثيل المحلي النهائي لطريقة احتوائه ، يحتفظ المتغير بالقيمة التي يحتفظ بها في وقت إنشاء المثيل ، حتى إذا كان المتغير قد خرج عن نطاقه (وهذا هو في الواقع جافا الخام ، وإصدار محدود من الإغلاق).

نظرًا لأن الطبقة الداخلية المحلية ليست عضوًا في فئة أو حزمة ، فلا يتم الإعلان عنها بمستوى الوصول. (كن واضحا ، ومع ذلك ، فإن أعضاءها لديهم مستويات وصول مثل في فصل عادي.)

إذا تم التصريح عن فئة داخلية محلية في أسلوب مثيل ، فإن إنشاء مثيل للطبقة الداخلية يرتبط بالمثيل المحمي بواسطة الأسلوب المحتوي هذا في وقت إنشاء المثيل ، وبالتالي يمكن الوصول إلى أعضاء مثيل الطبقة المحتوية كما في حالة الطبقة الداخلية. يتم إنشاء فئة داخلية محلية ببساطة عن طريق اسمها ، على سبيل المثال ، يتم إنشاء مثيل للطبقة الداخلية المحلية مثل Cat الجديد () ، وليس هذا new.Cat () كما قد تتوقع.


فصول داخلية مجهولة

إن الطبقة الداخلية المجهولة هي طريقة ملائمة من الناحية النحوية لكتابة فصل داخلي محلي. الأكثر شيوعًا ، يتم إنشاء فئة داخلية محلية على الأكثر مرة واحدة فقط في كل مرة يتم تشغيل أسلوب احتوائها. سيكون من اللطيف ، إذن ، إذا أمكننا الجمع بين تعريف الطبقة الداخلية المحلية ودمجها الأحادي في شكل تركيب ملائم واحد ، وسيكون من الجيد أيضًا إذا لم يكن علينا التفكير في اسم للفئة (أقل عددًا غير مفيدًا) أسماء تحتوي على شفرتك ، كان ذلك أفضل). تسمح الطبقة الداخلية المجهولة بكل من هذه الأشياء:

new *ParentClassName*(*constructorArgs*) {*members*}

هذا هو تعبير إرجاع مثيل جديد لفئة غير مسماة التي تمتد ParentClassName . لا يمكنك توفير منشئ الخاصة بك. بدلاً من ذلك ، يتم توفير واحد ضمني والذي يستدعي ببساطة منشئ السوبر ، لذلك يجب أن تتلاءم الحجج المتوفرة مع منشئ السوبر. (إذا كان الوالد يحتوي على منشئات متعددة ، فإن "الأبسط" يسمى "أبسط" كما هو محدد من قبل مجموعة معقدة من القواعد لا تستحق أن تتعلم بالتفصيل - فقط انتبه إلى ما تخبرك به NetBeans أو Eclipse.)

بدلاً من ذلك ، يمكنك تحديد واجهة لتنفيذها:

new *InterfaceName*() {*members*}

ينشئ مثل هذا تعريف مثيل جديد لفئة غير مسماة الذي يوسع الكائن وتنفذ InterfaceName . مرة أخرى ، لا يمكنك توفير الخاصة بك المنشئ. في هذه الحالة ، توفر Java ضمنيًا مُنشئًا لا - arg ، لا شيء - (لذلك لن يكون هناك أبداً منشئ منشئ في هذه الحالة).

على الرغم من أنه لا يمكنك إعطاء فئة داخلية مجهولة منشئ ، فلا يزال بإمكانك القيام بأي إعداد تريده باستخدام كتلة مُهيئ (يتم وضع كتلة {{}} خارج أي أسلوب).

يجب أن تكون واضحًا أن الطبقة الداخلية المجهولة هي ببساطة طريقة أقل مرونة لإنشاء طبقة داخلية محلية مع مثيل واحد. إذا كنت ترغب في فصل داخلي داخلي يقوم بتنفيذ واجهات متعددة أو يقوم بتنفيذ واجهات أثناء توسيع بعض الصفوف بخلاف الكائن أو الذي يحدد مُنشئه الخاص ، فإنك تكون عالقاً في إنشاء فئة داخلية محلية مسماة.


من برنامج Java التعليمي :

تنقسم الطبقات المتداخلة إلى فئتين: ثابتة وغير ثابتة. تسمى الفئات المتداخلة التي تم تعريفها static ببساطة الفئات المتداخلة الثابتة. تسمى الطبقات المتداخلة غير الثابتة الفئات الداخلية.

يتم الوصول إلى الطبقات المتداخلة الثابتة باستخدام اسم الفئة المرفق:

OuterClass.StaticNestedClass

على سبيل المثال ، لإنشاء كائن للفئة المتداخلة الثابتة ، استخدم بناء الجملة هذا:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

توجد كائنات مثيلات فئة داخلية داخل مثيل للفئة الخارجية. خذ بعين الاعتبار الفئات التالية:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

يمكن أن يوجد مثيل InnerClass فقط داخل مثيل من OuterClass ولديه إمكانية الوصول المباشر إلى الأساليب والحقول الخاصة به.

لتهيئة فئة داخلية ، يجب عليك أولاً إنشاء الطبقة الخارجية. ثم قم بإنشاء الكائن الداخلي داخل الكائن الخارجي باستخدام بناء الجملة هذا:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

انظر: دروس جافا - الطبقات المتداخلة

للتأكد من اكتمالها ، هناك أيضًا شيء مثل فئة داخلية بدون مثيل مرفق :

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

هنا ، new A() { ... } هي فئة داخلية يتم تعريفها في سياق ثابت وليس لها مثيل مرفق.


Inner class and nested static class in Java both are classes declared inside another class, known as top level class in Java. In Java terminology, If you declare a nested class static, it will called nested static class in Java while non static nested class are simply referred as Inner Class.

What is Inner Class in Java?

Any class which is not a top level or declared inside another class is known as nested class and out of those nested classes, class which are declared non static are known as Inner class in Java. there are three kinds of Inner class in Java:

1) Local inner class - is declared inside a code block or method.
2) Anonymous inner class - is a class which doesn't have name to reference and initialized at same place where it gets created.
3) Member inner class - is declared as non static member of outer class.

public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in java");
        }
    }
}

What is nested static class in Java?

Nested static class is another class which is declared inside a class as member and made static. Nested static class is also declared as member of outer class and can be make private, public or protected like any other member. One of the main benefit of nested static class over inner class is that instance of nested static class is not attached to any enclosing instance of Outer class. You also don't need any instance of Outer class to create instance of nested static class in Java .

1) It can access static data members of outer class including private.
2) Static nested class cannot access non-static (instance) data member or method .

public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in java");
        }
    }
}

Ref: Inner class and nested Static Class in Java with Example


فئة متداخلة: صنف داخل الفصل

أنواع:

  1. فئة متداخلة ثابتة
  2. فئة متداخلة غير ثابتة [الفئة الداخلية]

فرق:

فئة متداخلة غير ثابتة [الفئة الداخلية]

في كائن فئة متداخلة غير ثابتة من الطبقة الداخلية موجودة داخل كائن من الطبقة الخارجية. بحيث يمكن لعضو البيانات في الطبقة الخارجية الوصول إلى الطبقة الداخلية. لذلك ، من أجل إنشاء كائن من الطبقة الداخلية ، يجب علينا إنشاء كائن من الطبقة الخارجية أولاً.

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

فئة متداخلة ثابتة

في كائن فئة متداخلة ثابت من الطبقة الداخلية لا تحتاج إلى كائن من الطبقة الخارجية ، لأن كلمة "ثابت" تشير إلى عدم الحاجة إلى إنشاء كائن.

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

إذا كنت تريد الوصول إلى x ، فاكتب الطريقة الداخلية التالية

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);

I have illustrated various possible correct and error scenario which can occur in java code.

    class Outter1 {

        String OutStr;

        Outter1(String str) {
            OutStr = str;
        }

        public void NonStaticMethod(String st)  {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            //  below static attribute not permitted
            // static String tempStatic1 = "static";    

            //  below static with final attribute not permitted         
            // static final String  tempStatic1 = "ashish";  

            // synchronized keyword is not permitted below          
            class localInnerNonStatic1 {            

                synchronized    public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /* 
        //  static method with final not permitted
          public static void innerStaticMethod(String str11) { 

                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }                            

        }

        public static  void StaticMethod(String st)     {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            // static attribute not permitted below
            //static String tempStatic1 = "static";     

            //  static with final attribute not permitted below
            // static final String  tempStatic1 = "ashish";                         

            class localInnerNonStatic1 {
                public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /*
    // static method with final not permitted
    public static void innerStaticMethod(String str11) {  
                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }    

        }

        // synchronized keyword is not permitted
        static  class inner1 {          

            static String  temp1 = "ashish";
            String  tempNonStatic = "ashish";
            // class localInner1 {

            public void innerMethod(String str11) {
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            public static void innerStaticMethod(String str11) {
                //  error in below step
                str11 = temp1 +" india";    
                //str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }
            //}
        }

        //synchronized keyword is not permitted below
        class innerNonStatic1 {             

//This is important we have to keep final with static modifier in non
// static innerclass below
            static final String  temp1 = "ashish";  
            String  tempNonStatic = "ashish";
            // class localInner1 {

            synchronized    public void innerMethod(String str11) {
                tempNonStatic = tempNonStatic +" ...";
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            /*
            //  error in below step
            public static void innerStaticMethod(String str11) {   
                            //  error in below step
                            // str11 = tempNonStatic +" india";                     
                            str11 = temp1 +" india";
                            System.out.println("innerMethod ===> "+str11);
                        }*/
                    //}
                }
    }

The difference is that a nested class declaration that is also static can be instantiated outside of the enclosing class.

When you have a nested class declaration that is not static, also known as an inner class , Java won't let you instantiate it except via the enclosing class. The object created out of the inner class is linked to the object created from the outer class, so the inner class can reference the fields of the outer.

But if it's static, then the link does not exist, the outer fields cannot be accessed (except via an ordinary reference like any other object) and you can therefore instantiate the nested class by itself.


في حالة إنشاء المثيل ، يتم إنشاء مثيل الطبقة الداخلية غير الساكنة بمرجع كائن من الطبقة الخارجية التي يتم تعريفها فيه. هذا يعني أنه يحتوي على سبيل المثال. ولكن يتم إنشاء طبقة الطبقة الداخلية الثابتة مع الإشارة إلى الطبقة الخارجية ، وليس مع الإشارة إلى كائن من الطبقة الخارجية. هذا يعني أنه لم يأت على سبيل المثال.

فمثلا:

class A
{
  class B
  {
    // static int x; not allowed here…..    
  }
  static class C
  {
    static int x; // allowed here
  }
}

class Test
{
  public static void main(String… str)
  {
    A o=new A();
    A.B obj1 =o.new B();//need of inclosing instance

    A.C obj2 =new A.C();

    // not need of reference of object of outer class….
  }
}

يتم إنشاء مثيل الطبقة الداخلية عند إنشاء مثيل الطبقة الخارجية. لذلك ، يمكن لأعضاء وطرق الطبقة الداخلية الوصول إلى أعضاء وأساليب المثيل (الكائن) للطبقة الخارجية. عندما يخرج مثيل الطبقة الخارجية عن نطاقه ، فإن حالات الطبقة الداخلية تتوقف عن الوجود.

لا تحتوي الطبقة الثابتة المتداخلة على مثال ملموس. يتم تحميلها فقط عند استخدامها لأول مرة (تمامًا مثل الطرق الثابتة). إنها كيان مستقل تمامًا ، لا تملك طرقه ومتغيراته أي وصول إلى مثيلات الطبقة الخارجية.

لا تقترن الفئات المتداخلة الثابتة بالكائن الخارجي ، فهي أسرع ، ولا تأخذ ذاكرة كومة الذاكرة المؤقتة ، لأنها ليست ضرورية لإنشاء مثيل لمثل هذه الفئة. وبالتالي ، فإن القاعدة الأساسية هي محاولة تعريف فئة متداخلة ثابتة ، مع نطاق محدود قدر الإمكان (خاص> = class> = محمي> = عام) ، ثم تحويله إلى فئة داخلية (عن طريق إزالة معرف "ثابت") وفك النطاق ، إذا كان ضروريًا حقًا.



فيما يلي الاختلافات الرئيسية وأوجه التشابه بين فئة Java الداخلية والفئة المتداخلة الثابتة.

آمل أن يساعد!

فئة داخلية

  • يمكن الوصول إلى الطبقة الخارجية على حد سواء ، والطرق والحقول الثابتة
  • يترافق مع فئة من الإحاطة في الفصول الدراسية لتكرار ذلك أولاً يحتاج إلى مثيل للطبقة الخارجية (لاحظ مكان الكلمة الرئيسية الجديد ):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • لا يمكن تعريف أي عضو ثابت نفسه

  • لا يمكن الحصول على تعريف Class أو Interface

فئة متداخلة ثابتة

  • لا يمكن الوصول إلى أساليب أو حقول مثيل الطبقة الخارجية

  • غير مرتبط بأي مثيل لإرفاق الفصل.

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
    

التشابه

  • يمكن لكل من الطبقات الداخلية الوصول حتى إلى الحقول الخاصة وأساليب الطبقة الخارجية
  • كما يمكن للطبقة الخارجية الوصول إلى الحقول الخاصة وأساليب الطبقات الداخلية
  • يمكن أن يكون كلا الفئتين معدِّل وصول خاص أو محمي أو عام

لماذا استخدام الطبقات المتداخلة؟

وفقا لوثائق أوراكل ، هناك عدة أسباب ( وثائق كاملة ):

  • إنها طريقة لتجميع الفئات بشكل منطقي والتي تستخدم فقط في مكان واحد: إذا كان الفصل مفيدًا لفئة أخرى فقط ، فمن المنطقي تضمينه في هذه الفئة والحفاظ على الجمع بينهما. إن وضع مثل هذه "فئات المساعد" يجعل رزمتهم أكثر انسيابية.

  • إنه يزيد من التغليف: فكر في فصلين من المستوى الأعلى ، A و B ، حيث يحتاج B إلى الوصول إلى أعضاء A التي قد يتم إعلانها بشكل خاص. من خلال إخفاء الصنف B داخل الفئة A ، يمكن اعتبار أعضاء A خاصين ويمكن لـ B الوصول إليها. بالإضافة إلى ذلك ، يمكن إخفاء B نفسها من العالم الخارجي.

  • يمكن أن يؤدي إلى رمز أكثر قابلية للقراءة وقابلية للصيانة: تعيين الطبقات الصغيرة داخل الطبقات العليا يضع الرمز أقرب إلى حيث يتم استخدامه.


لا أعتقد أن الفرق الحقيقي أصبح واضحًا في الإجابات السابقة.

أولاً للحصول على الشروط الصحيحة:

  • فئة متداخلة هي فئة موجودة في فئة أخرى عند مستوى التعليمات البرمجية المصدر.
  • إنه ثابت إذا قمت بتعريفه بمعدّل ثابت .
  • تسمى فئة متداخلة غير ثابتة فئة داخلية. (أظل مع فئة متداخلة غير ثابتة.)

إجابة مارتن صحيحة حتى الآن. ومع ذلك ، فإن السؤال الفعلي هو: ما هو الغرض من إعلان فئة متداخلة ثابتة أم لا؟

يمكنك استخدام فئات متداخلة ثابتة إذا كنت ترغب فقط في الاحتفاظ بالفصول الدراسية الخاصة بك معًا إذا كانت تنتمي موضعيًا معًا أو إذا كانت الفئة المتداخلة مستخدمة حصريًا في الفصل المرفق. لا يوجد فرق دلالي بين فئة متداخلة ثابتة وكل فئة أخرى.

تعتبر الطبقات المتداخلة غير الثابتة وحشا مختلفا. على غرار الطبقات الداخلية المجهولة ، فإن هذه الفئات المتداخلة هي في الواقع أغلفة. وهذا يعني أنهم يلتقطون نطاقهم المحيط ومثالهم المحيط وجعل ذلك في المتناول. ربما مثال يوضح ذلك. انظر هذا كعب من حاوية:

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

في هذه الحالة ، ترغب في الحصول على مرجع من عنصر فرعي إلى الحاوية الرئيسية. باستخدام فئة متداخلة غير ثابتة ، يعمل هذا دون بعض العمل. يمكنك الوصول إلى تراكب الحاوية حاوية مع بناء جملة Container.this .

التفسيرات أكثر المتشددين التالية:

إذا نظرت إلى Java bytecodes ، ينشئ المحول البرمجي لفئة متداخلة (غير ثابتة) قد تصبح أكثر وضوحًا:

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this$0

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this$0 : Container
    ARETURN
   L1
    LOCALVARIABLE this Container$Item L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 1
  public <init>(Container,Object) : void
   L0
    LINENUMBER 12 L0
    ALOAD 0: this
    ALOAD 1
    PUTFIELD Container$Item.this$0 : Container
   L1
    LINENUMBER 10 L1
    ALOAD 0: this
    INVOKESPECIAL Object.<init>() : void
   L2
    LINENUMBER 11 L2
    ALOAD 0: this
    ALOAD 2: data
    PUTFIELD Container$Item.data : Object
    RETURN
   L3
    LOCALVARIABLE this Container$Item L0 L3 0
    LOCALVARIABLE data Object L0 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

كما يمكنك مشاهدة المحول البرمجي بإنشاء حقل مخفي Container this$0 . يتم تعيين هذا في المُنشئ الذي يحتوي على معلمة إضافية من نوع الحاوية لتحديد مثيل التضمين. لا يمكنك رؤية هذه المعلمة في المصدر ، لكن المترجم ينشئها ضمنيًا لفئة متداخلة.

مثال مارتن

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

حتى يتم تجميعها إلى مكالمة من شيء من هذا القبيل (في bytecodes)

new InnerClass(outerObject)

من أجل الإنتهاء:

تعتبر الفئة المجهولة مثالاً ممتازًا لفئة متداخلة غير ثابتة لا يرتبط بها أي اسم إلا ولا يمكن الإشارة إليها لاحقًا.





inner-classes