这取决于你的意思是“原始”
Java中的“原始”通常被认为是“值类型”.然而,C#有一个字符串关键字,它与Java的String完全相同,编辑器只是被高亮显示.它们是类System.String或java.lang.String的别名.字符串不是任何一种语言的值类型,所以以这种方式它不是一个原始的.
如果用“原始”表示内置的语言,则String是一个原语.它只是使用大写字母.文字(引号中的那些东西)将自动转换为System.String并用于连接.所以通过这个标记,它们(和数组)与int,longs等一样是原始的
首先,什么是String?
字符串不是包装器. String是一个引用类型,而原始类型是值类型.这意味着如果你有:
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 [](除非这是你想要的行为,或者你真的想减少内存使用).
每个对象都是一个引用类型 – 这意味着你写的所有类,框架中的每个类,甚至是数组.唯一的值类型是数值类型(int,long,short,byte,float,double,char,bool等)
为什么String不像char []?
这有几个原因,但它主要归结于心理学和实施细节:
想象一下,如果你将一个字符串传递给另一个函数,那么这个函数就会变得混乱.或者如果它将它保存在某个地方,并在将来更改它?对于大多数引用类型,您接受此类型的一部分,但Java开发人员决定,至少对于字符串,他们不希望用户不必担心.
>字符串不能以原子方式处理,意味着多线程/同步将成为一个问题.
>文字字符串(您在代码中放入引号的内容)在计算机的级别1可能是不可变的(出于安全考虑).当程序启动或使用写时复制时,可以将它们全部复制到内存的另一部分,但这很慢.
为什么我们没有一个值类型版本的字符串?
基本上,性能和实现细节,以及具有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++和其他本地编译的语言中,这是真的,因为它们被放置在进程的代码段中,操作系统通常阻止你编辑.在Java中,实际上通常是不真实的,因为JVM将类文件加载到堆上,因此可以在其中编辑一个字符串.然而,没有任何原因可以无法编译Java程序(有些工具可以这样做),而某些架构(尤其是某些版本的ARM)可以直接执行Java字节码.
2 – 在实践中,这些类型中的一些在机器级别具有不同的大小. E.x.布尔存储为堆栈上的WORD-size(x86上为32位,x64为64位).在类/数组中,它们可能被不同地对待.这是JVM所有的实现细节 – 规范说,bools是true还是false,机器可以弄清楚如何做.