• String、Long 源码解析学习记录


    String源码

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

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

    相等判断

    public boolean equals(Object anObject) {
        // 判断内存地址是否相同
        if (this == anObject) {
            return true;
        }
        // 待比较的对象是否是 String,如果不是 String,直接返回不相等
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            // 两个字符串的长度是否相等,不等则直接返回不相等
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                // 依次比较每个字符是否相等,若有一个不等,直接返回不相等
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    
    
    

    拆分和合并

    拆分使用 split (),该方法有两个入参数。第一个是将要拆分的字符,第二个参数是一个 int 型数值,叫 limit,来限制我们需要拆分成几个元素。如果 limit 比实际能拆分的个数小,将按照 limit 的个数进行拆分。

    拆分结果里面不会出现被拆分的字段

    空值是拆分不掉的,仍然成为结果数组的一员

    其中google提供的 Splitter ,可以达到去除空值的效果

    String a =",a, ,  b  c ,";
    // Splitter 是 Guava 提供的 API 
    List<String> list = Splitter.on(',')
        .trimResults()// 去掉空格
        .omitEmptyStrings()// 去掉空值
        .splitToList(a);
    log.info("Guava 去掉空格的分割方法:{}",JSON.toJSONString(list));
    // 打印出的结果为:
    ["a","b  c"]
    

    合并

    合并可以使用 join 方法,此方法是静态的。

    缺点

    不支持依次 join 多个字符串,例如依次 join 字符串 s 和 s1,如果写成 String.join(",",s).join(",",s1) 最后得到的是 s1 的值,第一次 join 的值被第二次 join 覆盖了;
    如果 join 的是一个 List,无法自动过滤掉 null 值。

    google也提供了解决该方法的API

    // 依次 join 多个字符串,Joiner 是 Guava 提供的 API
    Joiner joiner = Joiner.on(",").skipNulls();
    String result = joiner.join("hello",null,"china");
    log.info("依次 join 多个字符串:{}",result);
    
    List<String> list = Lists.newArrayList(new String[]{"hello","china",null});
    log.info("自动删除 list 中空值:{}",joiner.join(list));
    // 输出的结果为;
    依次 join 多个字符串:hello,china
    自动删除 list 中空值:hello,china
    

    LONG

    Long 最被我们关注的就是 Long 的缓存问题,Long 自己实现了一种缓存机制,缓存了从 -128 到 127 内的所有 Long 值,如果是这个范围内的 Long 值,就不会初始化,而是从缓存中拿.

    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);
        }
    }
    

    为什么使用 Long 时,大家推荐多使用 valueOf 方法,少使用 parseLong 方法?
    因为 Long 本身有缓存机制,缓存了 -128 到 127 范围内的 Long,valueOf 方法会从缓存中去拿值,如果命中缓存,会减少资源的开销,parseLong 方法就没有这个机制。

  • 相关阅读:
    Java 实现线程安全的三种方式
    tomcat启动时报EOFException错误的解决方式
    mysql优化——show processlist命令详解
    mysql数据库的锁有多少种,怎么编写加锁的sql语句
    java中的int与byte的转化
    JDK配置环境变量
    Eclipse32位官网下载地址
    js正则表达式匹配
    身份证号校验方法
    使用反射将JavaBean转为Map
  • 原文地址:https://www.cnblogs.com/AmosAlbert/p/12832186.html
Copyright © 2020-2023  润新知