Java 静态方法的实例变量
Java instance variable of a static method
静态方法的实例变量什么时候在java中获取内存?
在静态方法中创建实例变量(在参数中或在函数内部声明)是完全正确的,但我想知道静态方法的实例变量何时分配内存,如果 class 没有对象已创建?
其实我是想说静态方法里面的局部变量
如果您在静态方法中声明变量或使用参数,则它根本不是实例变量。它是一个局部变量,一旦方法被调用就会被初始化
static void methodTest(int i) {
String s = "Hello";
}
此处s
是该方法的局部变量。
i
是函数参数,也是方法
的局部变量
静态方法中没有实例变量。
如果你指的是参数和局部变量,它们是在堆栈上分配的(任何创建的对象都像往常一样在堆上分配)。
class 的静态字段将在加载 class 时初始化。
class 的实例变量将在构造实例时分配(并可能初始化)。
静态方法定义的变量在方法作用域内仍然是局部变量,就好像非静态方法创建局部变量一样。然而,问题是变量永远不会被垃圾收集,只要 class 加载器(通常是主 class,它只在运行时终止时得到 "unloaded",这就像挠你的左耳用你的右手)没有被卸载和垃圾收集。并且对象只有在不再被引用时才会被 GC,并且在静态字段的情况下,由于我描述的行为,即使没有人使用它们,它们也倾向于被引用。因此,在内存和资源有问题的大型应用程序中,在静态方法中声明任何内容都是非常糟糕的主意,因为您很快就会用无法收集的局部变量污染内存。
首先,术语 instance variable
不准确,我假设您问的是 local variable
,例如下面示例中的 a
和 b
:
void method(int a) {
int b = 3;
}
在Java中,只有基元和引用存储在栈中,对象在构造时存储在堆中。一旦范围结束,堆栈将被清理,堆由垃圾收集器清理。
这是一个例子:
public class Main {
static A a = new A();
static void method() {
int b = 2;
C c = new C();
}
}
您的代码第一次引用 Main
时,class 加载程序将加载 class 并初始化其所有静态字段 - 对象 new A()
将进入堆。这里什么都没有发生,方法 method
也可能不存在。
当您调用方法 method
时,它会在堆栈上添加值 2
,然后它会在堆栈上添加引用 c
,它将指向对象 new C()
在堆中。
当method存在时,2
和c
被移出栈(实际上并没有移出,只是栈顶换到了下面两个位置所以这两个值会是每当其他东西进入堆栈时都会被覆盖),而 new C()
将保留在堆中,直到垃圾收集器触发。它很可能会立即被垃圾收集,因为 GC 可能检测到没有更多对该对象的引用。
静态方法的实例变量什么时候在java中获取内存? 在静态方法中创建实例变量(在参数中或在函数内部声明)是完全正确的,但我想知道静态方法的实例变量何时分配内存,如果 class 没有对象已创建?
其实我是想说静态方法里面的局部变量
如果您在静态方法中声明变量或使用参数,则它根本不是实例变量。它是一个局部变量,一旦方法被调用就会被初始化
static void methodTest(int i) {
String s = "Hello";
}
此处s
是该方法的局部变量。
i
是函数参数,也是方法
静态方法中没有实例变量。
如果你指的是参数和局部变量,它们是在堆栈上分配的(任何创建的对象都像往常一样在堆上分配)。
class 的静态字段将在加载 class 时初始化。
class 的实例变量将在构造实例时分配(并可能初始化)。
静态方法定义的变量在方法作用域内仍然是局部变量,就好像非静态方法创建局部变量一样。然而,问题是变量永远不会被垃圾收集,只要 class 加载器(通常是主 class,它只在运行时终止时得到 "unloaded",这就像挠你的左耳用你的右手)没有被卸载和垃圾收集。并且对象只有在不再被引用时才会被 GC,并且在静态字段的情况下,由于我描述的行为,即使没有人使用它们,它们也倾向于被引用。因此,在内存和资源有问题的大型应用程序中,在静态方法中声明任何内容都是非常糟糕的主意,因为您很快就会用无法收集的局部变量污染内存。
首先,术语 instance variable
不准确,我假设您问的是 local variable
,例如下面示例中的 a
和 b
:
void method(int a) {
int b = 3;
}
在Java中,只有基元和引用存储在栈中,对象在构造时存储在堆中。一旦范围结束,堆栈将被清理,堆由垃圾收集器清理。
这是一个例子:
public class Main {
static A a = new A();
static void method() {
int b = 2;
C c = new C();
}
}
您的代码第一次引用 Main
时,class 加载程序将加载 class 并初始化其所有静态字段 - 对象 new A()
将进入堆。这里什么都没有发生,方法 method
也可能不存在。
当您调用方法 method
时,它会在堆栈上添加值 2
,然后它会在堆栈上添加引用 c
,它将指向对象 new C()
在堆中。
当method存在时,2
和c
被移出栈(实际上并没有移出,只是栈顶换到了下面两个位置所以这两个值会是每当其他东西进入堆栈时都会被覆盖),而 new C()
将保留在堆中,直到垃圾收集器触发。它很可能会立即被垃圾收集,因为 GC 可能检测到没有更多对该对象的引用。