1 String,Long源码解析
1.1 String
- 不可变性,源于String类和类属性value[]都是用final修饰。类不可继承,属性赋值后其内存地址不可修改。
- 字符串乱码 ,字符串做二进制转化,由于不同系统默认的编码,所以出现乱码,解决方式是指定编码。
- 首字母大小写,name.substring(0, 1).toLowerCase() + name.substring(1);name.substring(0, 1).toUpperCase() + name.substring(1)。
- 相等判断,方法有equals()和equalsIgnoreCase(), 判断两个String是否相登,挨个判断字符是否相等。
- 替换、删除,方法有replace,replaceAll和replaceFirst。
- 拆分和合并,Guava工具的Splitter和Joiner。
1.2 Long
- 缓存问题
缓存了-128到127. 如果是这个范围的值,从此处取值。内部静态类缓存数据。
private static class LongCache {
private LongCache(){}
// 缓存,范围从 -128 到 127,+1 是因为有个 0
static final Long cache[] = new Long[-(-128) + 127 + 1];
// 容器初始化时,进行加载
static {
// 缓存 Long 值,注意这里是 i - 128 ,所以再拿的时候就需要 + 128
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
1.3 面试
- 3.1 为什么使用 Long 时,大家推荐多使用 valueOf 方法,少使用 parseLong 方法
答:因为 Long 本身有缓存机制,缓存了 -128 到 127 范围内的 Long,valueOf 方法会从缓存中去拿值,如果命中缓存,会减少资源的开销,parseLong 方法就没有这个机制。
2 Java常用关键字
2.1 static
静态,修饰类变量,方法,方法块。静态类变量需要注意并发安全问题。
初始化时机
public class Parent {
public static List<String> PARENT_LIST = new ArrayList() {{
System.out.println("parent 静态变量初始化");
}};
static {
System.out.println("parent 静态代码块初始化");
}
public Parent(){
System.out.println("parent 构造器初始化");
}
public void testStatic(){
System.out.println("parent 静态方法执行");
}
}
public class Son extends Parent {
public static List<String> LIST = new ArrayList() {{
System.out.println("son 静态变量初始化");
}};
static {
System.out.println("son 静态代码块初始化");
}
public Son() {
System.out.println("son 构造器初始化");
}
public void testSonStatic(){
System.out.println("son 静态方法执行");
}
public static void main(String[] args) {
System.out.println("main 执行");
new Son();
}
}
打印结果:
parent 静态变量初始化
parent 静态代码块初始化
son 静态变量初始化
son 静态代码块初始化
main 执行
parent 构造器初始化
son 构造器初始化
结论
- 父类静态变量和静态代码块比子类优先初始化;
- 静态变量和静态代码块比构造器优先初始化;
- 父类构造器优先比子类初始化。
2.2 final
- 被final修饰的类,类不可被继承;
- 被final修饰的方法,表示方法不可覆写;
- 被final修饰的变量,表示变量在声明的必须初始化,且内存地址不可改变。注意是内存地址不可改变,不是值不可改变,对于如List,Map对象,可以改变其值。
2.3 try catch finally
public class TryCatchFinally {
public static void main(String[] args) {
TryCatchFinally tryCatchFinally = new TryCatchFinally();
tryCatchFinally.test();
}
public void test(){
try {
System.out.println("log try");
if (true) {
throw new RuntimeException("try exception");
}
} catch (Exception e) {
System.out.println("log catch");
if (true) {
throw new RuntimeException("catch exception");
}
} finally {
System.out.println("log finally");
}
}
}
结果
og try
log catch
log finally
Exception in thread “main” java.lang.RuntimeException: catch exception
- finally先执行,后抛异常;
2.4 volatile
volatile,英文解释:likely to change suddenly and unexpectedly, especially by getting worse,意为易变的。用来共享修饰变量。
**底层原理:**当多个线程在多个cpu分别执行时,为加快速度,线程并不是从内存中读取共享变量,而是从cpu缓存读取,那么就有一个问题,当线程A改变变量X的值时,由于cpu缓存的存在,线程B并不知道变量X已经被修改,这导致变量X值不一致的问题。
解决方法:用volatile修饰变量X,当线程A改变变量X的值时,内存会通知其他cpu其cpu缓存的变量X无效,其他线程则重新从内存读取变量X,保证数据一致性。
2.5 transient
修饰类变量,表示类进行序列化时,忽略此变量。
2.6 default
用来修饰接口方法,表示该方法子类无效实现,但接口必须有默认实现。
public interface ParentInterface {
default void testMy() {
System.out.println("do something");
}
}
2.7 面试题
- 如何证明 static 静态变量和类无关?
- 无需初始化类,可以直接使用静态变量;
- 在类中写main方法,即使不初始化类的代码,静态变量都会自动初始化;
- 静态变量只初始化一次,后面无论new多少个类,静态变量只初始化一次。
3 Arrays、Collections、Objects 常用方法源码解析
3.1 工具类通用特征
- 构造器私有,无需new出来;
- 方法通常被static和final修饰。
3.2 Arrays
Arrays主要用于处理数组,比如排序,查找,填充等等
3.2.1 排序
支持很多参数类型,来个demo:
package demo.two;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.ImmutableList;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@Slf4j
public class MyArraysDemoTest {
@Test
public void testSort() {
List<MySort> list = ImmutableList.of(
new MySort("100"),
new MySort("200"),
new MySort("600"),
new MySort("220"),
new MySort("150")
);
MySort[] mySorts = new MySort[list.size()];
list.toArray(mySorts);
log.info("before mySorts={}", JSON.toJSONString(mySorts));
Arrays.sort(mySorts, Comparator.comparing(MySort::getValue));
log.info("after mySorts={}", JSON.toJSONString(mySorts));
}
@Data
class MySort {
private String value;
public MySort(String value) {
this.value = value;
}
}
}
3.2.2 二分法查找
3.2.3 拷贝
copyOf(),copyOfRange()(部分拷贝)。
3.3 Collections
集合使用的工具类。
3.3.1 求最大最小值
Collections.max() 和 min()方法。
特别的:<T extends Object & Comparable<? super T>> 意思是要求T继承Object类并且实现Comparable接口。
3.3.2 多种类型的集合
有线程安全集合(Synchronized开头)和不可变集合(Unmodifiable开头),看底层实现。
可以看到操作都是加锁的。
不可变集合是从原集合得到一个新集合,只能读,不能写。
3.4 Objects
主要用于判断相等和判断空。
3.4.1 相等判断
Objects 有提供 equals 和 deepEquals 两个方法来进行相等判断,前者是判断基本类型和自定义类的,后者是用来判断数组的。
3.4.2 判空
Objects 提供了各种关于空的一些判断,isNull 和 nonNull 对于对象是否为空返回 Boolean 值,requireNonNull 方法更加严格,如果一旦为空,会直接抛出异常。