String、Long源码解析和面试题

我们常听人说,HashMap的key建议使用不可变类,比如说 String 这种不可变类。这里说的不可变指的是类值一旦被初始化,就不能再被改变了,如果被修改,将会是新的类,我们写个 demo 来演示一下。从代码上来看,s 的值好像被修改了,但从 debug 的日志来看,其实是 s 的内存地址已经被修改了,也就说 s =“world” 这个看似简单的赋值,其实已经把 s 的引用指向了新的 String,debug 的截图显示内存地址已经被修改
摘要由CSDN通过智能技术生成

String

不变性

我们常听人说,HashMap的key建议使用不可变类,比如说 String 这种不可变类。这里说的不可变指的是类值一旦被初始化,就不能再被改变了,如果被修改,将会是新的类,我们写个 demo 来演示一下。

String s ="hello";
s ="world";

从代码上来看,s 的值好像被修改了,但从 debug 的日志来看,其实是 s 的内存地址已经被修改了,也就说 s =“world” 这个看似简单的赋值,其实已经把 s 的引用指向了新的 String,debug 的截图显示内存地址已经被修改,两张截图如下:


我们从源码上查看一下原因:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
   
    /** The value is used for character storage. */
    private final char value[];
}    

我们可以看出来两点:

  1. String 被 final 修饰,说明 String 类绝不可能被继承了,也就是说任何对 String 的操作方法,都不会被继承覆写;
  2. String 中保存数据的是一个 char 的数组 value。我们发现 value 也是被 final 修饰的,也就是说 value 一旦被赋值,内存地址是绝对无法修改的,而且 value 的权限是 private 的,外部绝对访问不到,String 也没有开放出可以对 value 进行赋值的方法,所以说 value 一旦产生,内存地址就根本无法被修改。

以上两点就是 String 不变性的原因,充分利用了 final 关键字的特性,如果你自定义类时,希望也是不可变的,也可以模仿 String 的这两点操作。

因为 String 具有不变性,所以 String 的大多数操作方法,都会返回新的 String,如下面这种写法是不对的:

String str ="hello world !!";
// 这种写法是替换不掉的,必须接受 replace 方法返回的参数才行,这样才行:str = str.replace("l","dd");
str.replace("l","dd");

字符串乱码

在生活中,我们经常碰到这样的场景,进行二进制转化操作时,本地测试的都没有问题,到其它环境机器上时,有时会出现字符串乱码的情况,这个主要是因为在二进制转化操作时,并没有强制规定文件编码,而不同的环境默认的文件编码不一致导致的。

我们也写了一个 demo 来模仿一下字符串乱码:

String str = "nihao 你好 perye";
// 字符串转化成 byte 数组
byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1);
// byte 数组转化成字符串
String s2 = new String(bytes);
System.out.println(s2);

//输出结果
nihao ?? perye

打印的结果为??,这就是常见的乱码表现形式。是不是把代码修改成 String s2 = new String(bytes,“ISO-8859-1”); 就可以了?这是不行的。主要是因为 ISO-8859-1 这种编码对中文的支持有限,导致中文会显示乱码。唯一的解决办法,就是在所有需要用到编码的地方,都统一使用 UTF-8,对于 String 来说,getBytes 和 new String 两个方法都会使用到编码,把这两处的编码替换成 UTF-8 后,打印出的结果就正常了。

首字母大小写

如果我们的项目被 Spring 托管的话,有时候我们会通过 applicationContext.getBean(className); 这种方式得到 SpringBean,这时 className 必须是要满足首字母小写的,除了该场景,在反射场景下面,我们也经常要使类属性的首字母小写,这时候我们一般都会这么做:

name.substring(0, 1).toLowerCase() + name.substring(1);&#

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值