提问人:davidalayachew 提问时间:7/9/2023 更新时间:7/9/2023 访问量:85
无法在静态上下文中调用内部类的构造函数 -- “非静态变量,这不能从静态上下文引用” [重复]
Can't call constructor of inner class in a static context -- "non-static variable this cannot be referenced from a static context" [duplicate]
问:
我有一个和一个.喜欢这个。OuterClass
NestedClass
public class OuterClass
{
public class NestedClass
{
}
}
每当我尝试在静态上下文中调用构造函数(如静态字段或静态方法)时,我都会收到编译器错误。NestedClass
下面是一个示例代码。
public class OuterClass
{
public class NestedClass
{
public static final NestedClass someStaticField = new NestedClass();
public static NestedClass someStaticMethod()
{
return new NestedClass();
}
}
}
这是我得到的编译器错误。
$ javac OuterClass.java
OuterClass.java:7: error: non-static variable this cannot be referenced from a static context
public static final NestedClass someStaticField = new NestedClass();
^
OuterClass.java:12: error: non-static variable this cannot be referenced from a static context
return new NestedClass();
^
2 errors
这些错误意味着什么,我应该编写什么才能实现能够在静态上下文中调用构造函数的预期结果?
答:
长话短说,问题是因为在 Java 中,如果 my 前面没有修饰符,那么它就被认为是一个内部类,并且内部类不允许有静态字段或方法。因此,如果我希望我有静态字段或方法,那么我必须使我的类成为静态嵌套类。意思是,我需要在我的 .NestedClass
static
NestedClass
NestedClass
static
class
NestedClass
这是变化。
BEFORE -- public class NestedClass
AFTER -- public static class NestedClass
对于长版本,这里有一个很棒的教程,由Oracle自己提供,引导您了解这个概念。
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
简而言之,如果 class 内部有一个类,则 class 被视为嵌套类。B
A
B
嵌套类有两种类型:内部类和静态嵌套类。
内部类是指类按照我上面的方式定义——一个类在另一个类中。在直接的例子中,类前面不会有静态修饰符。B
静态嵌套类与内部类完全相同,但它们前面确实有一个静态修饰符。
举个例子。
public class OuterClass
{
// not static!
public class InnerClass
{
public static final InnerClass someStaticField = new InnerClass();
public static InnerClass someStaticMethod()
{
return new InnerClass();
}
}
// static! -- If you don't put the static keyword, then it's not a static class!
public static class StaticNestedClass
{
public static final StaticNestedClass someStaticField = new StaticNestedClass();
public static StaticNestedClass someStaticMethod()
{
return new StaticNestedClass();
}
}
}
如果我尝试编译这个,我会得到相同的 2 个编译错误(就像我的问题一样),但我没有收到编译错误!InnerClass
StaticNestedClass
这样做的原因是允许静态嵌套类具有静态字段/方法,但不允许内部类具有静态字段/方法。
这是一个严格的规则。这意味着,我唯一可能让我拥有静态字段或方法的方法就是将该内部类转换为静态嵌套类,这是通过将关键字放在关键字前面来完成的。NestedClass
static
class
这是固定版本。
public class OuterClass
{
//now its static!
public static class NestedClass
{
public static final NestedClass someStaticField = new NestedClass();
public static NestedClass someStaticMethod()
{
return new NestedClass();
}
}
}
不再有编译错误!
评论
public static Inner instance = new Outer().new Inner()
问题在于 is 不是 - 既不隐式也不显式地声明为 - 所以它是一个内部类。摘自 Java 语言规范 8.1.3。内部类和封闭实例:NestedClass
static
内部类是不是显式或隐式的嵌套类。
static
要创建此类内部类的实例,需要封闭类(外部类)的实例。如果不是在静态上下文中,则在创建此类实例时隐式使用。在静态上下文中,没有,我们必须提供封闭类的实例。这是通过使用限定的类实例创建表达式来实现的,例如:this
this
outer.new InnerClass()
限定类实例创建表达式允许创建内部成员类及其匿名子类的实例。
可以在 JLS 15.9.2 中找到更多详细信息。确定封闭实例。
将其应用于问题的代码,我们可以做到:
public class OuterClass
{
public class NestedClass // actually an Inner Class
{
public static final NestedClass someStaticField = new OuterClass().new NestedClass();
public static NestedClass someStaticMethod()
{
var outer = new OuterClass();
return outer.new NestedClass();
}
}
}
第二种可能性是,通过声明嵌套类并避免对封闭实例的需求,不使嵌套类成为内部类:static
public class OuterClass
{
// static added to following declaration
public static class NestedClass
{
public static final NestedClass someStaticField = new NestedClass();
public static NestedClass someStaticMethod()
{
return new NestedClass();
}
}
}
使用哪种解决方案应该基于特定的用例和数据模型,而不仅仅是因为编译器接受它!
注意:从 Java 16 (JEP 359) 开始,内部类的成员是允许的,因此我们可以在内部类中声明记录类。static
static
评论