包装器类很好,它们的用途也很容易理解。但是为什么我们忽略原始类型呢?
最佳答案
这取决于您所说的“原始”
Java中的“原始”通常被认为是“值类型”。但是,C#具有string
关键字,其作用与Java的String完全相同,只是编辑器以不同的方式突出显示了该关键字。它们是System.String
或java.lang.String
类的别名。字符串不是两种语言中的值类型,因此以这种方式它不是原始类型。
如果用“原始”表示语言已内置,则String是原始。它仅使用大写字母。字符串文字(用引号引起来的东西)会自动转换为System.String
,并且+用于串联。因此,通过此标记,它们(和数组)与int,longs等一样原始。
首先,什么是字符串?
字符串不是包装器。字符串是引用类型,而原始类型是值类型。这意味着,如果您具有:
int x = 5;
int y = x;
x和y的内存均包含“5”。但是有:
String x = "a";
String y = x;
x和y的内存均包含指向字符“a”的指针(以及长度,偏移量,ClassInfo指针和监视器)。字符串的行为就像原始元素一样,因为它们是不可变的,因此通常不成问题,但是,例如,如果您使用反射来更改字符串的内容(不要这样做!),则x和y都会看到改变。实际上,如果您具有:
char[] x = "a".toCharArray();
char[] y = x;
x[0] = 'b';
System.out.println(y[0] == 'b'); // prints "true"
因此,不要只使用char [](除非这是您想要的行为,否则您实际上是在尝试减少内存使用)。
每个
Object
都是引用类型-表示您编写的所有类,框架中的每个类,甚至是数组。唯一属于数值类型的是简单的数字类型(int,long,short,byte,float,double,char,bool等)。为什么String不像char []一样可变?
造成这种情况的原因有两个,但主要取决于心理和实现细节:
为什么我们没有字符串的值类型版本?
基本上,性能和实现的细节以及具有2种不同的字符串类型的复杂性。其他值类型具有固定的内存占用量。一个int始终为32位,一个long始终为64位,一个bool始终为1位,依此类推。2其中,这意味着它们可以存储在堆栈中,因此函数的所有参数都位于一个位置。同样,到处都是巨大的字符串副本会降低性能。
另请参阅:In C#, why is String a reference type that behaves like a value type?。指.NET,但这在Java中同样适用。
1-在C/C++和其他 native 编译的语言中,这是正确的,因为它们被放置在过程的代码段中,操作系统通常会阻止您对其进行编辑。在Java中,这实际上通常是不正确的,因为JVM将类文件加载到堆上,因此您可以在其中编辑字符串。但是,没有理由不能本地编译Java程序(有工具可以这样做),并且某些体系结构(尤其是某些ARM版本)可以直接执行Java字节码。
2-实际上,其中某些类型在计算机级别具有不同的大小。 E.x. boolean 值以WORD大小存储在堆栈中(x86中为32位,x64中为64位)。在类/数组中,可以将它们区别对待。这都是JVM的实现细节-规范说bool是true还是false,机器可以弄清楚该怎么做。
关于java - 为什么Java具有 “String”类型而不是 “string”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2108828/