java笔记三(String篇)

String

  • String 被声明为 final
  • Java 8 中,String 内部使用 char 数组存储数据;Java 9 之后,String 类的实现改用 byte 数组存储字符串,同时使用 coder 来标识使用了哪种编码。
String不可变
不可变好处:
  • String不可变,其hash值也不可变。在 String 类中,哈希值是在第一次计算时缓存的,后续对该哈希值的请求将直接使用缓存值。
String text1 = "沉默王二";
String text2 = "沉默王二";

// 计算字符串 text1 的哈希值,此时会进行计算并缓存哈希值
int hashCode1 = text1.hashCode();
System.out.println("第一次计算 text1 的哈希值: " + hashCode1);

// 再次计算字符串 text1 的哈希值,此时直接返回缓存的哈希值
int hashCode1Cached = text1.hashCode();
System.out.println("第二次计算: " + hashCode1Cached);

// 计算字符串 text2 的哈希值,由于字符串常量池的存在,实际上 text1 和 text2 指向同一个字符串对象
// 所以这里直接返回缓存的哈希值
int hashCode2 = text2.hashCode();
System.out.println("text2 直接使用缓存: " + hashCode2);

String 对象是不可变的,其哈希值在创建后不会发生变化。这使得 String 类可以缓存哈希值,提高哈希表等数据结构的性能。

  • 安全性
  • 线程安全: String 不可变性天生具备线程安全,可以在多个线程中安全地使用。
  • 可以实现字符串常量池String Pool。

Java字符串String常量池

字符串的使用频率实在是太高了,所以 Java 虚拟机为了提高性能和减少内存开销,在创建字符串对象的时候进行了一些优化,特意为字符串开辟了一块空间——也就是字符串常量池。
解释:
对于:

String s = "三妹";

ava 虚拟机会先在字符串常量池中查找有没有“三妹”这个字符串对象,如果有,则不创建任何对象,直接将字符串常量池中这个“三妹”的对象地址返回,赋给变量 s;如果没有,在字符串常量池中创建“三妹”这个对象,然后将其地址返回,赋给变量 s。

eg.

String s = new String("二哥");
String s1 = new String("二哥");
//创建3个对象
String s = "三妹";
String s1 = "三妹";
//如果字符串常量池没有"三妹"则创建1个对象

字符串常量池在内存中的什么位置呢?待进一步了解。

  • Java 7之前,位于永久代。
  • Java 7开始,字符串常量池从永久代移动到堆
  • Java 8永久代被取消,由元空间取代。

String.intern() 方法

理解下面网页的两幅图片。
链接: link

String 类型的变量和常量做“+”运算时发生了什么?
  • 变量:
    对象引用和“+”的字符串拼接方式,实际上是通过 StringBuilder 调用 append() 方法实现的,拼接完成之后调用 toString() 得到一个 String 对象。
  • 常量:
    常量折叠: Javac 编译器会对源代码做的极少量优化措施之一, 对编译器在程序编译期就可以确定值的常量进行折叠。
    折叠例子:
final String str1 = "str";
final String str2 = "ing";
// 下面两个表达式其实是等价的
String c = "str" + "ing";// 常量池中的对象
String d = str1 + str2; // 常量池中的对象
System.out.println(c == d);// true

编译器在运行时才能知道其确切值的话,就无法对其优化,eg:

final String str1 = "str";
final String str2 = getStr();
String c = "str" + "ing";// 常量池中的对象
String d = str1 + str2; // 在堆上创建的新的对象
System.out.println(c == d);// false
public static String getStr() {
      return "ing";
}

Formatter与String.format()
Formatter f = new Formatter(System.out);//定向输出到System.out
  • 格式化
正则表达式

java中\表示:后面的字符有特殊意义
eg.

-?\\d+   :表示可能有一个-号,后面跟着一位或多位数字。
(- | \\+)?   :表示字符串的起始字符可能是一个-或一个+,或者二者都没有。(+在正则表达式中有特殊意义,所以用\\转义)

有用的文档:(来自二哥的java进阶之路)
https://github.com/cdoco/learn-regex-zh

https://github.com/cdoco/common-regex

Pattern和Matcher待进一步了解。
tips
  • 重写toStrnig:
    字符操作简单 -> 信赖编译器;
    需要使用循环 -> 自己创建StringBuilder
  • 递归陷阱
    java编程思想 p509
  • System.out.format()用法同C的printf
练习Java中拆分字符串

杂记

  • Character.isDigit()方法判断字符是不是数字。
  • 异或运算符(^), 字符大小可以通过异或32进行转换。
  • java中Arrays.sort()的几种用法
    1 所有元素进行排序,并且是按从小到大的顺序
 1 import java.util.Arrays;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         
 6         int[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
 7         Arrays.sort(a);
 8         for(int i = 0; i < a.length; i ++) {
 9             System.out.print(a[i] + " ");
10         }
11     }
12 
13 }

2 Arrays.sort(int[] a, int fromIndex, int toIndex)
对数组部分排序,也就是对数组a的下标从fromIndex到toIndex-1的元素排序

 1 import java.util.Arrays;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         
 6         int[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
 7         Arrays.sort(a, 0, 3);
 8         for(int i = 0; i < a.length; i ++) {
 9             System.out.print(a[i] + " ");
10         }
11     }
12
13 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值