# 概述

在各大平台上看到并觉得不错的面试题

# 内容

关于String对象不改变引用地址而改变值
String s = new String("abc");
// 在不改变 s 引用的指向时,使得输出的结果为 abcd
// 一开始毫无思路,能想到的方法,例如转变成 StringBuilder,
// 或者是使用替换,最终都会改变 s 的引用地址
System.out.println(s);
// 所以知道题目实际考差的是    反射
// 后面的 value 是 String 底层是 char [] value,
Field value = s.getClass().getDeclaredField("value");
// 改变权限  
// 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
// 值为 false 则指示反射的对象应该实施 Java 语言访问检查;
value.setAccessible(true);
value.set(s,"abcd".toArray());

关于String对象的是否相等

对于 **==** 来说,在 java 中,对比的是基本数据类型,那么比较的就会是他们的值
如果比较的是引用类型,那么比较的则是他们的地址
八大基本数据类型

  • 整数
    1. byte
    2. short
    3. int(默认)
    4. long
  • 浮点数
    1. float
    2. double(默认)
  • 字符
    • char
  • 布尔值
    • boolean
String s1 = new String("abc");
String s2 = "abc";
String s3 = s1.intern();
// s1 == s2    true  or  flase
// s2 == s3    true  or  flase
-------------------------------------------------------
// 通过 new 的方式来创建对象,那么他会生成两个对象,
// 一个是放在字符串常量池中,一个是 String 对象放在堆中
// 通过 "" 来创建对象,会先在常量池中查找是否有这个值,
// 如果有,会将常量池对象赋值给它
//intern () 方法,首先会检查字符串常量池是否存在这个值,
// 如果存在,则返回该字符串的引用
// 如果不存在,则把这个值添加到字符串常量池中,并返回引用。

Integer的对象界限
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 128;
Integer i4 = 128;
// i1 == i2    true  or  flase
// i3 == i4    true  or  flase
--------------------------------------------------------------
// 这个 Integer 内部有一个 static 代码块,会直接生成一个范围
// 在 [-128,127] 返回的 Integer 数组对象
// 当我们将一个基本类型的变量(int 型)封装成 Integer 对象是,
// 会调用 Integer 内部的 valueOf () 方法,在这个方法内,
// 会先判断当前传进来的数字是否在 - 128<= 传进来的值 & lt;=127
// 如果在这个范围内,那么会就在刚刚生成的数组中找到对应的 Integer 对象并返回,
// 如果超过了这个范围就会生成一个新的 Integer 对象
// 所以当我们创建的值在这个范围内的话,那么多个相同的值使用的是同一个对象.

String StringBuffer StringBuilder的区别

String 是 final 修饰的、不可变,每次操作都会产生新的 string 对象,
StringBuffer 和 StringBuilder 都是在原对象上操作
StringBuffer 是线程安全的,StringBuilder 线程不安全
StringBuffer 方法都是 synchronized 修饰的
性能:StringBuilder>StringBuffer>String

场景:经常需要改变字符串的使用 StringBuffer StringBuilder
优先使用 StringBuilder,多线程使用共享变量时使用 StringBuffer


二分搜索算法
二分搜索算法
//    标准的二分搜索算法步骤:
//    1. 前提:有已经排序好的数组
//    2. 定义左右边界,确定搜索范围
//    3. 获取中间值
//    4. 对比数组 [中间值] 与待搜索值是否相同
//        相同则返回中间值
//        如果不相同,则重新设置边界
//    5. 当左边界 > 右边界时,循环结束
// 例子
public static int binarySearch(int[] a, int i){
    int l = 0, r = a.length - 1 , m ;
    while(l<r){
        m = (l+r)/2;
        if(a[m] == i){
            return m;
        }else if(a[m] < i ){
            r = m - 1;
        }else if(a[m] > i ){
            l = m + 1;
        }
    }
    return -1;
}

问题
以上的二分法是标准的二分法
存在的问题是整数溢出
原因: (l+r)
    当这个数组很大的时候
    假定r = Integer.MAX_VALUE -1;
    l = 0
    当待找值>第一次数组中间值时
    那么此时的l = r /2
    这时候(l+r)就会溢出
解决办法:
方法一:
m = l + (r-l)/2;
方法二:
m = (l+r) >>> 1; // 无符号右移一位,推荐