方法本地内部类程序

时间:2018-06-28 11:59:16

标签: java inner-classes

我正在学习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 个答案:

答案 0 :(得分:2)

最基本的原因是因为范围。为了做

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

Inner必须在Test中定义,但必须在m1范围内定义。

答案 1 :(得分:1)

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

}

编译并运行。

恕我直言,这不是一个好方法...

答案 2 :(得分:0)

方法内部类仅对该方法可见,因此您不能在任何其他位置使用此方法。

要使用此类,您必须在方法之外声明它。

答案 3 :(得分:0)

您不能编译它,因为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
    }
}

因此,最适合您的方法取决于您最终想要获得哪种代码设计。

答案 4 :(得分:0)

您的class Inner是JLS所说的Local Class (14.3. Local Class Declarations)

scope of a Local Class is defined as (6.3. Scope of a Declaration)

  

紧接在块中的局部类声明(第14.2节)的范围是紧接在其后的块的其余部分,包括它自己的类声明。

     

立即由开关块语句组(第14.11节)围起来的局部类声明的范围是紧随其后的开关块语句组的其余部分,包括其自己的类声明。

在您的情况下,它在一个块中声明,这是您的方法的主体。因此,您的类可见的范围是此方法正文的其余部分。

由于类型Innermain()中不可见,因此您不能在那里使用它。不过,您可以创建它的实例并在m1()中使用它们。

答案 5 :(得分:0)

编译时错误的最基本原因是“范围”。
根据您的代码,Inner类是在方法m1内定义的(此类称为Local class/method local class),因此,如果您观察方法变量的范围,则该变量仅在声明的方法内,并且我们无法访问任何方法该方法之外的变量,这就是原因,class Inner的范围仅限于m1方法 因此,如果要实例化class Inner并调用其方法,则必须使用m1方法(在代码中,您正在尝试在方法m1之外创建类Inner对象,但这不是可能),因此代码应该是

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