Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 声明但不初始化对象是否分配内存?_Java_Optimization - Fatal编程技术网

Java 声明但不初始化对象是否分配内存?

Java 声明但不初始化对象是否分配内存?,java,optimization,Java,Optimization,进一步解释我的问题。只需编写字符串foo分配内存。或者,只有当变量第一次给定值时,内存才会被留出?谢谢 在创建字符串之前,不会分配内存。仅仅定义字符串是不够的。如果使用字符串文字创建字符串对象,则该对象存储在字符串常量池中,并且每当使用new关键字创建字符串对象时,该对象都存储在堆内存中 String s5 = new String("abc"); 例如,当您创建如下所示的字符串对象时,它们将存储在字符串常量池中 String s = "abc"; 当您使用下面这样的新关键字创建字符串对象

进一步解释我的问题。只需编写
字符串foo分配内存。或者,只有当变量第一次给定值时,内存才会被留出?谢谢

在创建字符串之前,不会分配内存。仅仅定义字符串是不够的。如果使用字符串文字创建字符串对象,则该对象存储在字符串常量池中,并且每当使用new关键字创建字符串对象时,该对象都存储在堆内存中

String s5 = new String("abc");
例如,当您创建如下所示的字符串对象时,它们将存储在字符串常量池中

String s = "abc"; 
当您使用下面这样的新关键字创建字符串对象时,它们将存储在堆内存中

String s5 = new String("abc");

我将以不同的方式回答这个问题,因为我认为链接(重复)的答案是错误的

当您仅声明引用时,内存将被分配

public MyClass {
   public String s;
}
该引用
s
在堆上需要8个“是”(通常是大多数JVM)。记忆必须在那里

现在,当您分配它时,会分配更多内存

public static void main( String args... ) {
   MyClass c = new MyClass();
   c.s = new String("Hello Memory");
}
字符串
“Hello Memory”
也占用内存,但是引用
s
仍然占用堆上的8个“是”,并且是创建
MyClass
时分配的内存的一部分。此外,所有Java对象在堆上都有大约8个字节的额外开销(所有Java对象都有一个与其相关联的监视器,因此需要开销)

在方法
main
中,
c
除了
new
需要在堆上分配的内存外,还需要8个字节(在堆栈上)。如果你想了解内存是如何工作的,我真的认为你需要考虑这种分配


我可能会搞砸这件事,因为内存分配很棘手,但下面是这个程序如何分配内存,从
main
开始

调用
main
时首先分配
c
:8字节

然后
newmyclass()
在堆上分配16个字节(大小为
s
+8字节开销)

接下来,(准备好了吗?
newstring(“Hello Memory”)在堆上分配48个字节。为什么?Java字符串声明如下:

public final String {
   private final char[] string;
   private int hashcode;
}

字符串对象的开销为8字节,数组的开销为12字节(数组是对象,也需要数组的长度,所以正常的8字节开销+4字节的长度)。
hashcode
字段再占用4个字节,字符串数据“Hello Memory”占用24个字节(12个
chars
每个字符占用2个字节)。如果我做对了,它总共有48个字节。C程序员不是笑就是哭。

您没有在这里声明对象。您已经声明了一个引用变量。变量占用内存,初始化后引用的对象也会占用内存。

通常,它会在堆或堆栈的某个位置分配一些内存。然而,如果你从不使用变量,编译器通常会消除它,完全不使用内存。在你所引用的问题中,这些变量的可能重复是一些非常糟糕的答案。我很确定被接受的答案完全错了。@markspace这有多可怕?它们都声明一个变量会消耗内存。更不用说,你不会因为重复的文章有更好的答案而将文章标记为重复的-你标记重复的原因是之前有人问过问题..他们会这样做吗?我想他们说声明变量不需要内存。我再查一下。我想这是错的。仅在声明引用时分配内存<代码>字符串s作为成员字段或作为局部变量或参数时,通常需要8个字节。8个(或4个)字节用于指针@markspace强调了一个重要的点,即值有内存,指针也有内存。@markspace实际上,这也是错误的。当方法被输入时,堆栈被分配。我认为这是很明显的,但是是的。如果您声明了一个局部变量或方法参数,那么在方法调用之前,该内存不会被实际使用。我认为即使在细节上有所不同,一些代码在调用站点分配参数时也会分配完整的堆栈空间。有些确实使用了两种内存分配:一种是在调用站点只为方法参数分配内存,另一种是在开始时在方法内部分配局部变量。我相信其他方案也已经尝试过了,这些只是我所知道的常见方案。@markspace这不是“一些代码”和其他代码的问题。Java字节码在Java虚拟机规范中定义。它的行为是这样或那样的,不难找到它是什么。实际上。。。他声明了一个变量(可能包含引用)。原则上你是对的,但很多细节都是错的“当你分配它时,会分配更多的内存”——从字面上看,这是错误的。它从来不是赋值,而是
new
操作符字符串
“Hello Memory”
在类加载时分配,因为它是编译时常量。正如您所写的,它需要一个
char[]
加上
String
对象执行
新字符串(“Hello内存”)重用数组并分配另一个
字符串
对象使用
新字符串(someString)
总是毫无意义的。我建议你用“不需要这个”之类的话来评论它。大多数情况下你是对的,尽管我认为你在吹毛求疵。我的示例程序只是一个关于如何使用内存的示例。我想它们在某些情况下可能很重要,但我的目标只是讨论原语和引用占用的内存与
new
在堆上分配的内存之间的区别。我自己有一个缺点:“创建新字符串(“Hello Memory”);重用数组“Nope”。从Java7U6开始,char数组不是