Внутренний класс Java и статический вложенный класс - PullRequest
1626 голосов
/ 16 сентября 2008

В чем основное различие между внутренним классом и статическим вложенным классом в Java? Играет ли дизайн / реализация роль в выборе одного из них?

Ответы [ 25 ]

10 голосов
/ 18 ноября 2015

Не думаю, что здесь есть что добавить, большинство ответов прекрасно объясняют различия между статическим вложенным классом и внутренним классом. Однако при использовании вложенных классов и внутренних классов учтите следующую проблему. Как упомянуто в нескольких ответах, внутренние классы не могут быть созданы без экземпляра и включающего его класса, что означает, что они HOLD указывают на экземпляр своего охватывающего класса, что может переполнение памяти или исключение переполнения стека из-за того, что сборщик мусора не сможет собирать окружающие классы, даже если они больше не используются. Чтобы сделать это понятным, проверьте следующий код:

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 не может собрать его, и поскольку он ссылается (имеет указатель на) на внешний экземпляр, он тоже не собирается. Наличие достаточного количества этих объектов в вашем проекте и нехватка памяти.
По сравнению со статическими внутренними классами, которые не содержат указателя на экземпляр внутреннего класса, потому что он не связан с экземпляром, а связан с классом. Приведенная выше программа может вывести « Я уничтожен! », если вы сделаете класс Inner статическим и создадите экземпляр с Outer.Inner i = new Outer.Inner();

10 голосов
/ 14 ноября 2013

В случае создания экземпляра, экземпляр не статический внутренний класс создается со ссылкой объект внешнего класса, в котором он определен. это означает, что есть включающий экземпляр. Но экземпляр статического внутреннего класса создается со ссылкой на класс Outer, а не с ссылка на объект внешнего класса. Это значит не включающий экземпляр.

Например:

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….
  }
}
8 голосов
/ 16 сентября 2008

Вложенный класс - это очень общий термин: каждый класс, который не является верхним уровнем, является вложенным классом. Внутренний класс - это нестатический вложенный класс. Джозеф Дарси написал очень хорошее объяснение о Вложенных, Внутренних, Членских и Высших Классах .

8 голосов
/ 16 сентября 2008

Термины используются взаимозаменяемо. Если вы хотите быть по-настоящему педантичным в этом, то вы можете определить «вложенный класс» для ссылки на статический внутренний класс, у которого нет включающего экземпляра. В коде у вас может быть что-то вроде этого:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

Хотя это не совсем общепринятое определение.

7 голосов
/ 16 сентября 2008

Ммм ... внутренний класс - это вложенный класс ... Вы имеете в виду анонимный класс и внутренний класс?

Редактировать: Если вы на самом деле имели в виду внутренний против анонимного ... внутренний класс - это просто класс, определенный внутри класса, такой как:

public class A {
    public class B {
    }
}

Принимая во внимание, что анонимный класс является расширением класса, определенного анонимно, поэтому фактический «класс» не определен, как в:

public class A {
}

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

Далее Редактировать:

Википедия утверждает, что в Java есть разница , но я работаю с Java уже 8 лет, и это первое, что я услышал о таком различии ... не говоря уже о том, что там нет ссылок для подтверждения утверждения ... нижняя строка, внутренний класс - это класс, определенный внутри класса (статический или нет), а вложенный - просто еще один термин, означающий то же самое.

Существует небольшая разница между статическим и нестатическим вложенным классом ... в основном нестатические внутренние классы имеют неявный доступ к полям экземпляра и методам включающего класса (поэтому они не могут быть созданы в статическом контексте, это будет быть ошибкой компилятора). Статические вложенные классы, с другой стороны, не имеют неявного доступа к полям и методам экземпляра и МОГУТ быть сконструированы в статическом контексте.

7 голосов
/ 21 июля 2015

Ориентация на учащихся, которые являются новичками в Java и / или во вложенных классах

Вложенные классы могут быть:
1. Статические вложенные классы.
2. Нестатические вложенные классы. (также известный как Внутренние классы ) => Пожалуйста, помните это


1. Внутренние классы
Пример:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}


Внутренние классы являются подмножествами вложенных классов:

  • внутренний класс - это особый тип вложенного класса
  • внутренние классы являются подмножествами вложенных классов
  • Можно сказать, что внутренний класс также является вложенным классом, но вы можете NOT сказать, что вложенный класс также является внутренним классом .

Специальность внутреннего класса:

  • экземпляр внутреннего класса имеет доступ ко всем членам внешнего класса, даже к тем, которые помечены как «частные»


2.Статические вложенные классы:
Пример:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

Случай 1: создание статического вложенного класса из не включающего класса

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

Случай 2: создание статического вложенного класса из включающего класса

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

Специальность статических классов:

  • Статический внутренний класс будет иметь доступ только к статическим членам внешнего класса и не будет иметь доступа к нестатическим членам.

Вывод:
Вопрос: В чем основное различие между внутренним классом и статическим вложенным классом в Java?
Ответ: просто изучите специфику каждого класса, упомянутого выше.

6 голосов
/ 22 марта 2017

Внутренний класс и вложенный статический класс в Java. Оба класса объявлены внутри другого класса, известного как класс верхнего уровня в Java. В терминологии Java: если вы объявляете вложенный класс статическим, он будет называться вложенным статическим классом в Java, в то время как нестатический вложенный класс просто называется внутренним классом.

Что такое внутренний класс в Java?

Любой класс, который не является верхним уровнем или объявлен внутри другого класса, известен как вложенный класс, и из этих вложенных классов класс, который объявлен нестатическим, известен как внутренний класс в Java. В Java есть три вида внутреннего класса:

1) Локальный внутренний класс - объявляется внутри блока кода или метода.
2) Анонимный внутренний класс - это класс, который не имеет имени для ссылки и инициализируется в том же месте, где он создается.
3) Член внутреннего класса - объявлен как нестатический член внешнего класса.

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");
        }
    }
}

Что такое вложенный статический класс в Java?

Вложенный статический класс - это другой класс, который объявлен внутри класса как член и сделан статическим. Вложенный статический класс также объявляется как член внешнего класса и может быть закрытым, открытым или защищенным, как любой другой член. Одним из основных преимуществ вложенного статического класса перед внутренним классом является то, что экземпляр вложенного статического класса не привязан ни к какому включающему экземпляру класса Outer. Вам также не нужен экземпляр класса Outer для создания экземпляра вложенного статического класса в Java .

1) Может иметь доступ к статическим элементам данных внешнего класса, включая private.
2) Статический вложенный класс не может получить доступ к нестатическому (экземплярному) элементу данных или , методу .

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: Внутренний класс и вложенный статический класс в Java с примером

5 голосов
/ 02 декабря 2016

Когда мы объявляем статический класс-член внутри класса, он называется вложенным классом верхнего уровня или статическим вложенным классом. Это можно продемонстрировать, как показано ниже:

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());
    }
}

Когда мы объявляем нестатический класс-член внутри класса, он называется внутренним классом. Внутренний класс можно продемонстрировать, как показано ниже:

    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);
        }
    }
}
5 голосов
/ 28 марта 2012

Я думаю, что люди здесь должны заметить для Афиши, что: Классический Гнездовой Класс - только первый внутренний класс Например:

 public static class A {} //ERROR

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

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

 }

Итак, подведем итог: статический класс не зависит от того, какой класс он содержит. Таким образом, они не могут в обычном классе. (потому что нормальному классу нужен экземпляр).

3 голосов
/ 04 января 2017

Ниже приведен пример static nested class и 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()); 

    }

}
...