转自:String字符串的最大长度是多少?在学习和开发过程中,我们经常会讨论 short ,int 和 long 这些基本数据类型的取值范围,但是对于 String 类型我们好像很少注意它的“取值范围”。那么对于 String 类型,它到底有没有长度限制呢?
其实 String 类型的对象,他们是有长度限制的, String 对象并不能“存储”无限长度的字符串。关于 String 的长度限制要从编译时限制和运行时限制两方面考虑。
String类提供了一个length方法,返回值为int类型,而int的取值上限为2^31 -1。
所以理论上String的最大长度为2^31 -1。
编译期限制
我们所写的字面量会直接存放在方法区的常量池里面,“afu 最帅” 会存放在方法区的常量池中。
Stirng 长度之所以会受限制,是因JVM规范对常量池有所限制。常量池中的每一种数据项都有自己的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8类型表示。
CONSTANT_Utf8的数据结构如下:
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
u1 bytes[length]; 是真正的数据length是数组存放最大字节数,理论上最大长度是2^16-1=65535
Java中的字符常量都是使用UTF8编码的,UTF8编码使用1~4个字节来表示具体的Unicode字符。所以有的字符占用一个字节,而我们平时所用的大部分中文都需要3个字节来存储。
//65534个字母,编译通过
String s1 = "aa..hh";
//21845个中文”自“,编译通过
String s2 = "bb...黑虎呀";
//一个英文字母d加上21845个中文”自“,编译失败
String s3 = "as..黑虎呀";
对于s1,一个字母d的UTF8编码占用一个字节,65534字母占用65534个字节,长度是65534,长度和存储都没超过限制,所以可以编译通过。
对于s2,一个中文占用3个字节,21845个正好占用65535个字节,而且字符串长度是21845,长度和存储也都没超过限制,所以可以编译通过。
对于s3,一个英文字母d加上21845个中文”自“占用65536个字节,超过了存储最大限制,编译失败。
String 运行时的限制主要体现在 String 的构造函数上。下面是 String 的一个构造函数:
public String(char value[], int offset, int count) {
...
}
String内部是使用一个char数组来维护字符序列的,一个char占用两个字节。如果说String最大长度是2^31 -1的话,那么最大的字符串占用内存空间约等于4GB。
也就是说,我们需要有大于4GB的JVM运行内存才 行
Object常用方法有:toString()
、equals()
、hashCode()
、clone()
等。
toString 默认输出内存地址, 重写的时候,打印对应返回的字符串,
equals 默认比较的是内存地址,如果要比较字符串我们需要比较对应的字符,我们重写eques 比较对应字符串
hashCode将与对象相关的信息映射成一个哈希值,默认的实现hashCode值是根据内存地址换算出来。
clone 复制一个对象的浅克隆对象,基本类型是不一样的,但是引用类型是同一份
浅拷贝:拷⻉对象和原始对象的引⽤类型引用同⼀个对象。
深拷贝:拷贝对象和原始对象的引用类型引用不同的对象。
equals与hashcode的关系:
equals相等的两个对象,hashCode一定相等;
hashCode不相等,一定能推出equals也不相等;
hashCode相等,equals可能相等,也可能不等。
hashcode方法主要是用来提升对象比较的效率,先进行hashcode()的比较,如果不相同,那就不必在进行equals的比较,这样就大大减少了equals比较的次数,当比较对象的数量很大的时候能提升效率。
1.hashCode()方法
hashCode()方法返回对象的哈希码(散列码)。哈希码是一个整数,用于在哈希表等数据结构中快速定位对象。
在Java中,哈希表(如 HashMap、HashSet 等)使用哈希码来存储和检索对象。hashCode()方法的主要作用是提高搜索、插入和删除等操作的效率。
在覆盖(override)hashCode()方法时,需要保证以下规则:
*如果两个对象通过equals()方法判断为相等,那么它们的hashCode()值必须相等。
*如果两个对象的hashCode()值相等,它们并不一定相等。
2.equals()方法
equals()方法用于比较两个对象是否相等。在默认情况下,equals()方法比较的是对象的引用,即判断两个对象是否指向同一内存地址。
然而,很多时候我们需要自定义相等性判断的逻辑,因此可以覆盖equals()方法。
要注意的是,如果我们在类中覆盖了equals()方法,通常也需要同时覆盖hashCode()方法,以确保哈希表等数据结构能正确地处理对象