Java面经(附源码分析)

String、StringBuffer和StringBuilder的区别:

首先String内部的字符数组是使用final修饰,无法修改,每次修改其实是创建一个新的String对象,为了高效字符串操作,引入了StringBuffer和StringBuilder。但StringBuffer的线程是安全的,适合多线程环境下使用,而StringBuilder速度快,但不安全,适合单线程环境下使用。

封装、继承、多态具体含义:

封装:将对象实现细节隐藏,只允许通过公共的接口与外部交互 (数据的安全性,代码可维护性)

继承:子类继承父类后,可获得父类公有的属性和方法(代码的复用性,扩展性)

多态:子类重写父类的方法,将子类对象赋给父类变量,但运行表现子类行为(代码可维护性,解耦合)

String

最多可以放多少个字符?

使用 char[]来维护字符序列的,而char[]的长度是 int类型,所以理论上 String的长度最大为2^31-1,不过根据实际JVM的堆内存限制,编译时,String长度最多可以是2的16次方减2。

源码分析:

java 复制代码
substring(int beginIndex, int endIndex)

int length = length();//获取当前字符串的长度
checkBoundsBeginEnd(beginIndex, endIndex, length);//判断传入的参数是否合法
/*if (begin < 0 || begin > end || end > length) {
    throw new StringIndexOutOfBoundsException(
        "begin " + begin + ", end " + end + ", length " + length);
}*/
int subLen = endIndex - beginIndex;//获取截取字符长度
if (beginIndex == 0 && endIndex == length) {//如果起始点为0并且未位置等于当前字符串长度
    return this;//返回本字符串
}
//否则根据编码方式新建子字符串
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
                  : StringUTF16.newString(value, beginIndex, subLen);

public int indexOf(String str)//查找子串,返回第一个找到的索引位置,没找到返回-1

java 复制代码
//首先根据编码方式进行判断

 if (str.length == 0) {//如果查找子串为空返回0
            return 0;
        }
if (length(value) < str.length) {//如果子串长度大于当前字符长度肯定找不到返回-1
            return -1;
        }
/*src:要搜索的源字节数组。
srcCount:源字节数组中的有效字节数。
tgt:要查找的目标字节数组。
tgtCount:目标字节数组中的有效字节数。
fromIndex:开始搜索的索引位置(包含)*/
    public static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
        //确保数据合法
        assert fromIndex >= 0;
        assert tgtCount > 0;
        assert tgtCount <= tgt.length;
        assert srcCount >= tgtCount;
        //转换字符
        char first = (char)(tgt[0] & 0xff);
        int max = (srcCount - tgtCount);//获取遍历次数,因为次数大于该值后src子字符串长度小于查找字符串所有肯定不成立
        for (int i = fromIndex; i <= max; i++) {
            // 找第一个匹配的字符
            if (getChar(src, i) != first) {
                while (++i <= max && getChar(src, i) != first);
            }
            // 还在范围内进入if
            if (i <= max) {
                int j = i + 1;
                int end = j + tgtCount - 1;//尾位置
                //遍历比对字符是否相同
                for (int k = 1;
                     j < end && getChar(src, j) == (tgt[k] & 0xff);
                     j++, k++);
                if (j == end) {
                    // 到达末尾说明找到,直接返回
                    return i;
                }
            }
        }
        return -1;
    }

public boolean equals(Object anObject) //与其他字符串比较,看内容是否相同

java 复制代码
    public boolean equals(Object anObject) {
        //判断是否是同一个对象,是则内容肯定相同
        if (this == anObject) {
            return true;
        }
        //判断该对象是否是String类
        if (anObject instanceof String) {
            //根据字符串判断是否一样
            String aString = (String)anObject;
            //根据编码方式进行判断
            if (coder() == aString.coder()) {
                return isLatin1() ? StringLatin1.equals(value, aString.value)
                                  : StringUTF16.equals(value, aString.value);
            }
            //上述equals方法内代码
        //如果长度不一样返回false
        if (value.length == other.length) {
            //一个个比较是否相同
            for (int i = 0; i < value.length; i++) {
                //不同返回false
                if (value[i] != other[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
       
        }
        //不是字符串返回false
        return false;
    }

public int compareTo(String anotherString) //比较字符串大小

java 复制代码
   //获取两个字符串长度
    int len1 = value.length;
    int len2 = other.length;
   return compareTo(value, other, len1, len2);
   
   public static int compareTo(byte[] value, byte[] other, int len1, int len2) {
        //获取最短数组长度
        int lim = Math.min(len1, len2);
        //遍历
        for (int k = 0; k < lim; k++) {
            //不相等即可退出
            if (value[k] != other[k]) {
                return getChar(value, k) - getChar(other, k);
            }
        }
        //返回长度差 0------相等 负数------本字符串小于比较的字符串 正数------本字符串大于比较的字符串
        return len1 - len2;
    }

public String concat(String str) //字符串连接,返回当前字符串和参数字符串合并结果

java 复制代码
        //如果拼接的字符为空,直接退出
        if (str.isEmpty()) {
            return this;
        }
        //编码格式一样
        if (coder() == str.coder()) {
            //将两个字符串转数组
            byte[] val = this.value;
            byte[] oval = str.value;
            //求拼接后长度和
            int len = val.length + oval.length;
            //将第一数组copy进去
            byte[] buf = Arrays.copyOf(val, len);
            //将第二个数组copy进去
            System.arraycopy(oval, 0, buf, val.length, oval.length);
            //通过数组返回新的字符串
            return new String(buf, coder);
        }

谢谢观看!

相关推荐
捕鲸叉10 分钟前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer14 分钟前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq16 分钟前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml439 分钟前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~41 分钟前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong16168843 分钟前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7891 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java2 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山2 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
睡觉谁叫~~~2 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust