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

谢谢观看!

相关推荐
invicinble8 小时前
关于对后端开发工程师,在项目层面的基本需求与进阶方向
java
hhy_smile8 小时前
Python environment and installation
开发语言·python
懒鸟一枚8 小时前
Java17新特性详解
java
戌中横8 小时前
JavaScript 对象
java·开发语言·javascript
crossaspeed8 小时前
面向对象的三大特征和反射(八股)
java·开发语言
连山齐名8 小时前
程序员棋谱之一——单例模式
开发语言·单例模式
zfj3218 小时前
java synchronized关键字用法和底层原理
java·开发语言·轻量级锁·重量级锁·偏向锁·线程同步
梵高的代码色盘8 小时前
互联网大厂Java求职面试实录与技术深度解析
java·spring·缓存·微服务·面试·互联网大厂·技术深度
沐雨风栉8 小时前
用 Kavita+cpolar 把数字书房装进口袋
服务器·开发语言·数据库·后端·golang
E_ICEBLUE8 小时前
Excel vs CSV:在系统数据处理中该如何选择?
java·excel·csv·格式转换