Метод Локальных внутренних классов программы

Я просто изучаю концепции Java. Кто-нибудь может дать мне знать, почему я не могу запустить эту программу?

package innerClasses;

public class Test {
    int i=10;
    static int j=20;
    public void m1() {
        int k=30;
        final int m=40;

        class Inner {
            public void m2() {
                System.out.println(i);
            }
        }
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test.Inner in = t.new Inner();
        t.m1();
    }

}

Кто-нибудь может дать мне знать, почему я не могу запустить эту программу?

6 ответов

Самая основная причина заключается в объеме. Для того, чтобы сделать

Test.Inner in = t.new Inner();

Inner должны быть определены в Test, но вместо этого он определен в m1 объем.

Класс Inner объявлен внутри метода m1()что делает его недоступным вне этого метода.

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

public class Test {

    int i=10;
    static int j=20;

    public void m1() {
        int k=30;
        final int m=40;
    }

    class Inner {
        public void m2() {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test.Inner in = t.new Inner();
        t.m1();
    }

}

Замена t.m1(); от in.m2(); выведет 10.

РЕДАКТИРОВАТЬ

Если вам нужно создать внутренний класс внутри метода, сделайте так:

public class Test {

    int i=10;
    static int j=20;

    public void m1() {

        int k=30;
        final int m=40;

        class Inner {
            public void m2() {
                System.out.println(i);
            }
        }

        // this is what makes it run
        Inner myInner = new Inner();
        myInner.m2();
    }


    public static void main(String[] args) {
        Test t = new Test();
        t.m1();
    }

}

скомпилировать и запустить.

ИМХО, это не очень хороший способ...

Внутренний класс метода виден только этому методу, поэтому его нельзя использовать ни в каком другом месте.

для использования этого класса вы должны объявить его вне метода.

Вы не можете скомпилировать его, поскольку область действия класса Inner - это метод m1. Если вы хотите иметь возможность создавать экземпляры класса Inner, вы можете определить его непосредственно внутри Test:

public class Test {
    int i=10;
    static int j=20;

    public void m1() {
        int k=30;
        final int m=40;
    }

    // On the Test class level 
    class Inner {
        public void m2() {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test.Inner in = t.new Inner();
        t.m1();
        in.m2(); // prints 10
    }
}

Другая особенность, предоставляемая Java, заключается в использовании анонимных классов. Это может быть создано путем реализации некоторого интерфейса:

// Define an interface to be able to implement it inside the method
interface Inner {
    void m2();
}

public class Test {
    int i=10;
    static int j=20;

    public void m1() {
        int k=30;
        final int m=40;

        // Implement interface and call method on it
        // Functional style: 
        ((Inner) () -> System.out.println(i)).m2();

        // Legacy style:
        new Inner() {
            @Override
            public void m2() {
                System.out.println(i);
            }
        }.m2();

    }

    public static void main(String[] args) {
        Test t = new Test();
        t.m1(); // prints 10 twice
    }
}

или расширение некоторого класса:

// A class we going to extend
class Inner {
    void m2() {
        System.out.println(11);
    }
}

public class Test {
    int i=10;
    static int j=20;

    public void m1() {
        int k=30;
        final int m=40;

        // Extend inner class and call method on it
        new Inner() {
            void m2() {
                System.out.println(i);
            }
        }.m2();

    }

    public static void main(String[] args) {
        Test t = new Test();
        t.m1(); // prints 10, not 11
    }
}

Так что лучший способ для вас зависит от того, какой дизайн кода вы хотите получить в конце концов.

Самая основная причина ошибки времени компиляции - "Scope".
Согласно вашему коду, класс Inner определен внутри метода m1 (этот класс называется Local class/method local class), поэтому, если вы наблюдаете область действия переменной метода, она находится только в объявленном методе, и мы не можем получить доступ к какой-либо переменной метода вне этого метода, и это является причиной, область действия class Inner ограничивается m1 метод, так что если вы хотите создать экземпляр class Inner и вызвать его методы, то вы должны сделать это в m1 метод (в коде вы пытаетесь создать класс Inner объект вне метода m1, что невозможно) следовательно код будет

public class Test {
int i = 10;
    static int j = 20;
    public void m1() {
        int k = 30;
        final int m = 40;
        class Inner {
            public void m2() {
                System.out.println(i);
            }
        }
        Inner in = new Inner();
        in.m2();
    }
    public static void main(String[] args) {
        Test t = new Test();
        t.m1();
    }
}

Для получения дополнительной информации, локальные классы могут использоваться, когда внутри метода требуются повторяющиеся функциональные возможности (поскольку вложенные методы запрещены в java, поэтому мы можем создавать внутренний класс) и, разумеется, если мы не заинтересованы в создании метода уровня класса для пример

class Outer {
    public void cal() { 
        class Inner {
            public void sum(int x, int y) {
                System.out.println("sum : "+(x+y));
            }
        }
        Inner i= new Inner();
        i.sum(10, 20); //sum is repeatdly needed in between code
        i.sum(100, 200);
        i.sum(1000, 2000);
        i.sum(10000, 20000);
    }
}
public class TestClass {
    public static void main(String[] args) {
        new Outer().cal();
    }
}

Ваш class Inner это то, что JLS называет локальным классом (14.3. Объявления локальных классов).

Область действия Локального класса определяется как (6.3. Область объявления):

Область объявления локального класса, немедленно заключенного в блок (§14.2), является остальной частью непосредственно включающего блока, включая его собственное объявление класса.

Область локального объявления класса, непосредственно заключенного в группу операторов блока переключения (§14.11), является остальной частью непосредственно включающей группы операторов блока переключения, включая ее собственное объявление класса.

В вашем случае это объявляется в блоке, который является телом вашего метода. Таким образом, область видимости вашего класса - это остальная часть тела этого метода.

Как тип Inner не виден в main()Вы не можете использовать его там. Вы можете создавать экземпляры этого и использовать их в m1(), хоть.

Другие вопросы по тегам