我正在学习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();
}
}
任何人都可以让我知道为什么我无法运行该程序吗?
答案 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节)围起来的局部类声明的范围是紧随其后的开关块语句组的其余部分,包括其自己的类声明。
在您的情况下,它在一个块中声明,这是您的方法的主体。因此,您的类可见的范围是此方法正文的其余部分。
由于类型Inner
在main()
中不可见,因此您不能在那里使用它。不过,您可以创建它的实例并在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();
}
}