Java的String(字符串详解)

String有哪些特性

不变性:String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创 建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并 频繁访问时,可以保证数据的一致性。
常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时, 会直接返回缓存的引用。
final:使用 fifinal 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性

String被设计成不可变的原因或者String类为什么是final类型

  1. 性能优化:字符串常用于作为键(例如在哈希表中)或进行缓存。由于字符串是不可变的,可以缓存其哈希码,从而加速哈希表的查找操作。此外,由于字符串的不可变性,可以在需要的情况下共享字符串对象,从而减少内存消耗。
  2. 线程安全:不可变的字符串在多线程环境下是线程安全的。多个线程可以同时访问和共享字符串对象,而不需要进行额外的同步措施。这简化了多线程编程的复杂性。
  3. 安全性:字符串经常用于表示密码、URL等敏感信息。如果字符串是可变的,那么在创建它之后,它的值可能会被无意或有意地修改,导致安全隐患。通过将字符串设计成不可变的,可以确保它的值在创建后不会被篡改。
  4. 缓存和哈希映射:字符串的不可变性使得它们可以用作缓存的键或哈希映射的键。因为键是不可变的,所以不会发生键值对在映射中意外更改位置,确保了映射的一致性。
  5. 设计简单:不可变性简化了字符串的设计和使用。不可变的字符串不需要提供修改方法,因此代码更加简洁且易于理解。
    总之,将字符串设计为不可变的具有诸多优势,包括性能优化、线程安全性、安全性、缓存和哈希映射的优化以及代码设计的简单性等。这也是为什么Java中的String类被设计成不可变的重要原因。
    String 是引用类型,底层用 char 数组实现的。
    1.为了实现字符串池
    2.为了线程安全
    3.为了实现String可以创建HashCode不可变性

被final修饰的类不能被继承,也就是不能有子类。那么为什么要把String设计为不能被继承呢?简单来说有两点:安全和效率。
对于这个问题,Java之父James Gosling在一次记者采访中说明过,大体的原因如下:
1.安全迫使String类被设计成不可变类的一个原因就是安全。(在进行系统的校验工作中,如果设为可变类,就有可能会出现严重的系统崩溃问题。)
举例:字符串常量池
2.高效高司令是这样回答的:他会更倾向于使用不可变类(final),因为它能够缓存结果,当你在传参时不需要考虑谁会修改它的值。如果是可变类的话,则有可能需要重新拷贝出来一个新值进行传参,这样性能上就会有一定的损失。

1)字符串常量池需要 String 不可变。因为 String 设计成不可变,当创建一个 String 对象时,
若此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。
如果字符串变量允许必变,会导致各种逻辑错误,如改变一个对象会影响到另一个独立对象。
2)String 对象可以缓存 hashCode。字符串的不可变性保证了 hash 码的唯一性,因此可以缓存 String 的 hashCode,这样不用每次去重新计算哈希码。在进行字符串比较时,可以直接比较 hashCode,提高了比较性能;
3)安全性。String 被许多 java 类用来当作参数,如 url 地址,文件 path 路径,反射机制所需的 Strign 参数等,若 String 可变,将会引起各种安全隐患。

1)String 类是 final 型,固 String 类不能被继承,它的成员方法也都默认为 final 方法。String
对象一旦创建就固定不变了,对 String 对象的任何改变都不影响到原对象,相关的任何改变
操作都会生成新的 String 对象。
2)String 类是通过 char 数组来保存字符串的,String 对 equals 方法进行了重定,比较的是
值相等。
String a = “test”; String b = “test”; String c = new String(“test”);
a、b 和字面上的 test 都是指向 JVM 字符串常量池中的"test"对象,他们指向同一个对象。而
new 关键字一定会产生一个对象 test,该对象存储在堆中。所以 new String(“test”)产生了两
个对象,保存在栈中的 c 和保存在堆中的 test。而在 java 中根本就不存在两个完全一模一样
的字符串对象,故在堆中的 test 应该是引用字符串常量池中的 test。

String str1 = “abc”; //栈中开辟一块空间存放引用 str1,str1 指向池中 String 常量"abc"
String str2 = “def”; //栈中开辟一块空间存放引用 str2,str2 指向池中 String 常量"def"
String str3 = str1 + str2;//栈中开辟一块空间存放引用 str3
//str1+str2 通过 StringBuilder 的最后一步 toString()方法返回一个新的 String 对象"abcdef"
//会在堆中开辟一块空间存放此对象,引用str3指向堆中的(str1+str2)所返回的新String对象。
System.out.println(str3 == “abcdef”);//返回 false
因为 str3 指向堆中的"abcdef"对象,而"abcdef"是字符池中的对象,所以结果为 false。JVM对 String str="abc"对象放在常量池是在编译时做的,而 String str3=str1+str2 是在运行时才知道的,new 对象也是在运行时才做的。

什么是字符串常量池

字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空 间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池 中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。
存储MD5的值应该用VARCHAR还是CHAR
char类型是固定长度的字符串,varchar是可变长度字符串。
而MD5是一个固定长度的字符,不管数据怎么修改,长度不变,这个点很符合char类型。
另外,由于是固定长度,所以在数据变更的时候,不需要去调整存储空间大小,在效率上会比
varchar好。

详解String的intern方法

https://blog.csdn.net/m0_59181747/article/details/121146280

String s = new String (“xyz”); 创建了几个String Object

String str=new String(“123”)创建了几个对象
在这段代码中,创建了两个对象:

  1. 字符串常量池中的对象:当执行String str = new String(“hollis”)时,字符串常量池中会创建一个值为"hollis"的字符串对象。
  2. 堆中的对象:使用new关键字会在堆内存中创建一个新的字符串对象。在这个例子中,new String(“hollis”)将创建一个新的字符串对象,内容为"hollis"。
    需要注意的是,由于字符串具有不可变性,为了避免每次都创建新的字符串对象,Java提供了字符串常量池。在创建字符串时,如果字符串常量池中已经存在相同值的字符串对象,那么就会返回引用指向已存在的字符串对象。
    所以,虽然new String(“hollis”)语句在堆内存中创建了一个新的字符串对象,但仅当字符串常量池中不存在相同值的字符串对象时才会创建,否则会直接返回对应的引用。

String str="i"与 String str=new String(“i”)一样吗

不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中; 而 String str=new String(“i”) 则会被分到堆内存中。

String a = “ab”; String b = “a” + “b”; a == b 吗
在这个特定的情况下,a == b 返回 true。
这是因为在Java中,对于字符串常量的拼接操作,在编译期间就会被优化。在编译时,编译器会将字符串常量的拼接转换为一个新的字符串常量。因此,“a” + "b"在编译时就被优化成了一个新的字符串常量 “ab”。
在这个例子中,String a = “ab”;创建一个指向字符串常量池中的 “ab” 的引用,而String b = “a” + “b”;实际上也创建了一个指向字符串常量池中的 “ab” 的引用。
由于a和b都指向字符串常量池中相同值的字符串对象,表达式a == b会返回 true。
需要注意的是,当使用动态变量或表达式进行字符串拼接时,结果可能不同。例如,如果使用变量 “a” 和 “b” 进行拼接,那么 a == b 将会返回 false,因为这种情况下会创建新的字符串对象。

在使用 HashMap 的时候,用 String 做 key 有什么好处

HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的, 所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更 快。编译期需要用CONSTANT_Utf8_info 结构用于表示字符串常量的值,而这个结构是有长度限制,他的限制是65535。
在Java中,String的长度是有限制的,但实际的限制取决于底层操作系统和硬件的限制。
在Java中,String的长度由int类型的变量count来表示,它可以达到最大值Integer.MAX_VALUE(约为2^31-1)。这意味着在理论上,一个字符串的长度可以达到约20亿个字符。
然而,需要注意的是,尽管String的长度在理论上可以达到很大的值,但实际上会受到内存和性能方面的限制。长字符串将占用更多的内存,并且对于较长的字符串操作可能会产生较大的性能开销。
此外,还要考虑到操作系统和硬件对字符串长度的限制。例如,在某些操作系统中,单个字符串的最大长度可能会受到限制。
因此,尽管String的长度在理论上没有明确的限制,但在实践中,需要根据具体的应用场景和系统环境来评估和处理字符串的长度。

Hashcode()和 equals()和==区别

(1) hashcode()方法跟 equals()在 java 中都是判断两个对象是否相等
(2) 两个对象相同,则 hashcode 至一定要相同,即对象相同 ---->成员变量相同
---->hashcode 值一定相同
(3) 两个对象的 hashcode 值相同,对象不一定相等。总结:equals 相等则 hashcode 一
定相等,hashcode 相等,equals 不一定相等。
(4) ==比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间)

重写了 equals 方法 为什么 也需要重写 HashCode 方法
==与equals 区别
==比较两个对象内存地址
Equals 方法属于 Object 父类中,默认的情况下两个对象内存地址是否相等,只
是我们重写 Object 父类中 Equals 方法来实现 比较 对象属性值是否相等
两个对象值如果相等的话, HashCode 相等
两个对象值如果不相等的话, HashCode 不一定

两个对象 hashCode 值 如果相等, 值是否相等 不一定两个对象值如果是相等的话,hashcode 是相等。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思静语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值