Jic*_*hao 79 java static-members inner-classes
class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Run Code Online (Sandbox Code Playgroud)
虽然无法访问静态字段OuterClass.InnerClass.i
,但如果我想记录一些应该是静态的东西,例如创建的InnerClass对象的数量,那么将该字段设置为静态会很有帮助.那么为什么 Java禁止内部类中的静态字段/方法呢?
编辑:我知道如何使编译器满意静态嵌套类(或静态内部类),但我想知道的是为什么java禁止语言设计和内部类(或普通内部类)内的静态字段/方法实施方面,如果有人了解更多.
Osc*_*Ryz 45
我想知道的是为什么java禁止内部类中的静态字段/方法
因为那些内部类是"实例"内部类.也就是说,它们就像封闭对象的实例属性.
因为它们是"实例"类,所以允许static
功能没有任何意义,因为static
它首先在没有实例的情况下工作.
就像您尝试同时创建静态/实例属性一样.
请看以下示例:
class Employee {
public String name;
}
Run Code Online (Sandbox Code Playgroud)
如果您创建两个员工实例:
Employee a = new Employee();
a.name = "Oscar";
Employee b = new Employee();
b.name = "jcyang";
Run Code Online (Sandbox Code Playgroud)
很清楚为什么每个人都有自己的财产价值name
,对吗?
内部阶级也是如此; 每个内部类实例独立于另一个内部类实例.
因此,如果您尝试创建counter
类属性,则无法在两个不同的实例之间共享该值.
class Employee {
public String name;
class InnerData {
static count; // ??? count of which ? a or b?
}
}
Run Code Online (Sandbox Code Playgroud)
在创建实例时a
,b
在上面的示例中,静态变量的正确值是count
什么?无法确定它,因为InnerData
类的存在完全取决于每个封闭对象.
这就是为什么,当这个类被声明为static
,它不再需要一个活生生的实例来生存.既然没有依赖关系,您可以自由声明静态属性.
我认为这听起来很反复,但如果你考虑实例与类属性之间的差异,它就会有意义.
Asa*_*aph 33
InnerClass
不能拥有static
成员,因为它属于一个实例(of OuterClass
).如果声明InnerClass
为static
从实例中分离它,你的代码进行编译.
class OuterClass {
static class InnerClass {
static int i = 100; // no compile error
static void f() { } // no compile error
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句:你仍然可以创建实例InnerClass
.static
在这种情况下允许在没有封闭实例的情况下发生OuterClass
.
Gre*_*osz 27
内部类背后的想法是在封闭实例的上下文中操作.不知何故,允许静态变量和方法与这种动机相矛盾?
8.1.2内部类和封闭实例
内部类是未显式或隐式声明为静态的嵌套类.内部类可能不会声明静态初始化器(第8.7节)或成员接口.内部类可能不会声明静态成员,除非它们是编译时常量字段(第15.28节).
Nic*_*lai 11
从 Java 16 开始,情况不再如此。引用JEP 395(关于最终记录):
放宽长期存在的限制,即内部类不能声明显式或隐式静态成员。这将变得合法,特别是将允许内部类声明作为记录类的成员。
确实,下面的代码可以用Java 16编译(用16.ea.27试过):
public class NestingClasses {
public class NestedClass {
static final String CONSTANT = new String(
"DOES NOT COMPILE WITH JAVA <16");
static String constant() {
return CONSTANT;
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 9
实际上,如果静态字段是常量并且在编译时写入,则可以声明静态字段.
class OuterClass {
void foo() {
class Inner{
static final int a = 5; // fine
static final String s = "hello"; // fine
static final Object o = new Object(); // compile error, because cannot be written during compilation
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这是我发现最适合此“限制”的动机:您可以将内部类的静态字段的行为实现为外部对象的实例字段; 因此,您不需要静态字段/方法。我的意思是,某个对象的所有内部类实例共享一个字段(或方法)。
因此,假设您想计算所有内部类实例,则可以这样做:
public class Outer{
int nofInner; //this will count the inner class
//instances of this (Outer)object
//(you know, they "belong" to an object)
static int totalNofInner; //this will count all
//inner class instances of all Outer objects
class Inner {
public Inner(){
nofInner++;
totalNofInner++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于内部类取决于封闭类/外部类的实例,因此需要在初始化内部类之前初始化外部类。
这是JLS关于类初始化的说明。 我们需要指出的是,如果
- 使用由T声明的静态字段,并且该字段不是常量。
因此,如果内部类具有静态字段访问权限,这将导致初始化内部类,但不能确保封闭类被初始化。
这将违反一些基本规则。您可以跳到最后一部分,two cases
以避免出现菜鸟的玩意
关于的事情,有的时候,它的行为在各个方面都像普通的类,并且与Outer类相关联。static nested
class
nested class
static
但是Inner class
/ 的概念将与外部/封闭类相关联。请注意与实例关联的不是类。现在,与实例关联显然意味着(从实例变量的概念出发)它将存在于实例内部,并且在实例之间将有所不同。 non-static
nested class
instance
现在,当我们使某些东西静态时,我们期望它会在加载类时被初始化,并且应该在所有实例之间共享。但是由于是非静态的,即使内部类本身(您现在肯定可以忘记内部类的实例)也没有与外部/封闭类的所有实例共享(至少在概念上),那么我们如何期望某个变量内部类的所有实例将在内部类的所有实例之间共享。
因此,如果Java允许我们在静态嵌套类中使用静态变量。将有两种情况。
context of instance
(实例变量)的概念。那是不。 归档时间: |
|
查看次数: |
26250 次 |
最近记录: |