如果你在java中声明一个字符串数组
String[] words;
那只是给你一个正确的参考?
现在,我来自C的背景,所以我知道一串"字符串"在C中是指针或数组数组的指针。但是,我想知道JVM如何使用这个声明......它只是一个参考?那么当你给它足够的内存时,它也会给字符串提供不同的长度吗?
我很难描述,但我知道字符串只是字符数组,那么JVM如何确定字符串在分配之前有多长时间?它是否使用新的更新字符串长度重新分配全新的字符串数组。
char array[6][6]; //in C this is necessary because it needs to know the column and row length
与此相似
char* array[5]; // you still need to malloc the slots in the array for a two dimensional length to be achieved
但在java中我不明白这是如何工作的
String line = null;
try {
while ((line = bfr.readLine()) != null) {
if (StringUtils.isBlank(line))
continue;
System.out.println(line);
String[] chunks = line.split(","); //this line right here, how does JVM allocate proper memory
MindsparkPartnerCode record = new MindsparkPartnerCode();
record.setIEFFCode(chunks[0]);
records.add(record);
答案 0 :(得分:3)
嗯,你真的在这里问了两个问题。
首先,declaring数组(任何深度)都不会在Java中分配内存,而在C示例中,您声明和定义数组,其中< em> 分配内存。
爪哇:
String[] words; // Just a reference (null at this point) -- no memory allocated
C:
char array[6][10]; // *Does* allocate 60 bytes of memory, usually on the stack.
在Java中,在使用new
运算符之前,不会分配任何内存(当然,除了基元之外)。
Foo bar; // Just a reference
bar = new Foo(); // NOW memory has been allocated.
new
会向新对象返回引用。把所有不是原始的东西想象成一个参考(包括数组!)。
字符串也不例外。
String[] foo;
...只是对 String对象引用数组的引用 。没什么。
即使您创建阵列......
foo = new String[20];
... Java分配20 * sizeof(JavaReference)
个字节(其中JavaReference
是JVM用来表示引用的任何底层类型)。因此,数组的大小现在已知。
当您实际向该阵列添加字符串时......
foo[0] = "Hello!"; // Which is essentially...
foo[0] = new String("Hello!");
... THAT 是指告诉JVM你的字符串有多长,从而告诉它分配(strlen("Hello!") + 1) * 2
字节(因为Java以UTF-16编码存储其字符串) )。
同样,请记住strings are immutable,因此JVM不必担心realloc
他们。
关于字符串的问题对于Java来说很棘手,因为Java只需要另外一个类(String
)并将其转换为语言结构(如最后一个代码示例所示)。难怪在考虑内存和分配时,字符串可能会令人困惑。
答案 1 :(得分:2)
在Java中,String
不是字符数组。它是对堆上类java.lang.String
的垃圾收集实例的引用。来自文档:
String类表示字符串。 Java程序中的所有字符串文字,例如&#34; abc&#34;,都是作为此类的实例实现的。
字符串是不变的;它们的值在创建后无法更改。字符串缓冲区支持可变字符串。因为String对象是不可变的,所以可以共享它们。例如:
String str = "abc";
相当于:
char data[] = {'a', 'b', 'c'}; String str = new String(data);
类String包括用于检查序列的各个字符,用于比较字符串,搜索字符串,提取子字符串以及创建字符串副本的方法,其中所有字符都转换为大写或小写。案例映射基于Character类指定的Unicode标准版本。
Java语言为字符串连接运算符(+)提供特殊支持,并为其他对象转换为字符串。字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。字符串转换是通过方法toString实现的,由Object定义并由Java中的所有类继承...
因此可以从一个字符数组创建String
,但它不仅仅是一个字符数组。此类内置于Java本身,因此编译器知道如何从键入代码的字符串文字中实例化此类的实例。
因此,当您执行以下操作时:
String[] chunks = line.split(",");
您正在类java.lang.String
的实例上调用方法split
。它返回给你自己分配的java.lang.String
个对象的数组(数组和字符串)。最终,当它们不再被引用时,这些都将被垃圾收集。
答案 2 :(得分:1)
String[] chunks = line.split(","); //this line right here, how does JVM allocate proper memory
到此声明完成时,您可以参考N + 1个新对象:
String[]
数组对象String
个对象,一个坐在数组的每个插槽中答案 3 :(得分:0)
我也有一些C背景。在Java中,某些东西的数组与C中的完全相同。它是一个指针数组(或者只是像int这样的基类型)。数组的大小必须可用于Java,以及
String[] words = new String[10];
您的示例将单词声明为字符串数组,从而产生变量&#39;单词&#39;使用指向字符串数组的空指针。我的例子将指出&#39;单词&#39;到10个指向字符串的数组。
查看API java.util.arrays
https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html
答案 4 :(得分:0)
它为其他堆对象分配一个引用数组。 Java中的capital-S String本身是对堆上对象的引用,而该对象又包含对char []的引用,该引用可以具有任意大小。