1. final关键字简记
    (1)final修饰类,表示类不可变,不可继承
    比如,String不可变性
    (2)final修饰方法,表示该方法不可重写
    (3)final修饰变量,这个变量就是常量
    (4)注意:修饰的是基本数据类型,这个值本身不能修改
    *修饰的是引用数据类型,引用的指向不能修改
    *例子:final student student = new Student(1,"aa"); student.setName("bb"); 这样是可以修改的,但不能对student重新赋值新的引用,因为它已经是最终的引用了。
  2. String、StringBuffer、StringBuilder区别
    (1)String跟其它两个类的区别是:
    String是final类型,每次声明都是不可变对象,所以每次操作都会产生新的String对象,然后将指针指向新的String对象。
    (2)StringBuffer、StringBuilder都是在原有的对象上进行操作所以,如果需要经常改变字符串的内容,则应该使用StringBuffer和StringBulider比较好。
    (3)StringBuffer 与 StringBulider的区别:
    *前者是线程安全的,后者是线程不安全的。
    *线程不安全性能更高,但安全性没有后者好。
    *在高并发、多线程需要线程之间共享资源的时候考虑使用线程安全的StringBuffer,在单线程的时候优先考虑性能更高的StringBulider。
  3. 区分多继承、多重继承、多实现:
    *多重继承:A->B->C(爷孙三代的关系)
    *多实现: Person implements IRunable,IEatable (通过实现多个接口 进行多重实现 符合多项国际化标准)
    *多继承: 接口可以多继承,类只支持单继承。
  4. 方法的重写和重载的区别:
    *重载发生在一个类里面,方法名相同,参数列表不同(混淆点:跟返回类型没有关系)
    * 例子:一些构不成重载public double add(int a,int b) public int add(int a,int b) *重写:发生在子类里面,方法名相同,参数列表相同。
  5. ArrayList 和 LinkedList的区别
    (1)底层数据结构的差异:
    *ArrayList,数组,连续的一块内存空间
    *LinkedList ,双向链表,不是连续的内存空间
    (2)简单见解:
    *ArrayList,查找速度快,因为是连续的空间,方便寻址,但是删除,插入慢,因为删除插入需要发生数据迁移。
    *LinkedList,查找比较慢,因为需要通过指针一个个寻找,但是删除,插入比较快,因为只需改变前后节点的指针指向即可
    (3)ArrayList细节分析:
    *扩容:如果空间不够了,ArrayList会先创建一个新的数组,新的数组是原数组的1.5倍是通过位运算进行扩容的,然后再将原数组的数据迁移到新数组的数据中。
  6. HashSet存储原理
    (1)HashSet最底层其实用了HashMap来实现存储,其值作为HashMap的key。
    (2)
  7. HashMap细节再说
    (1)第一,为什么采用Hash算法?有什么优势?解决了什么问题?
    *解决的问题是唯一性
    *存储数据,底层采用的是数组
    *如何判定数组是唯一?
    解决方法:
    1.采用遍历的方式,逐个比较,但是这种效率极低。
    2.采用hash算法,通过计算存储对象的hashcode,然后再跟数组长度-1做位运算,得到我们要存储在数组的那个下标下,如果此时计算机的位置没有其他元素,直接存储,不用比较。此处,我们只会用到hashcode,随着元素不断添加,就可能出现“哈希冲突”,不同对象计算出来的hash值是相同的,这个时候,我们就需要比较,才需要用到equals方法,如果equals相同,则不插入,如果不相等,则形成链表。
    *哈希表的本质就是一个数组,而数组的元素是链表。
  8. ArrayList 与 Vector 区别
    (1)ArrayList线程不安全,效率高,常用
    (2)Vector 线程安全,效率低
  9. Hashtable 、HashMap 、ConcurrentHashMap的区别
    (1) HashTable:线程安全的对象,内部有上锁的控制synchronized,会阻塞,效率低。
    (2) HashMap : 线程不安全对象,不会阻塞,效率高,如果有多个线程同时操作这个hashmap,可能出现线程不安全的情况,甚至会出现死锁。
    (3)ConcurrentHashMap :分段锁,将锁粒度变小,兼顾两者,保证线程安全和性能。
    (4) 三者在开发中一般优先选择hashmap,当然得在不是多个线程访问同一个资源的情况下,优先选择hashmap,局部变量,不是全局变量。多线程访问同一资源下,选择ConcurrentHashMap比较好一点,既保证了性能也保证了安全。。
  10. IO流的分类及选择
    (1)分类:
    *按方向分:输入流(以程序为主角 读取文件) 、输出流(程序写入文件)
    *按读取单位分:字节流(任何文件,二进制文件)、字符流(文本文件)
    *按处理的方式分:节点流、处理流
    *IO流的4大基类:InputStream、OutputStream、Reader、writer
  11. java异常
    常见异常:算数异常、空指针、类型转化异常、数组越界、数字格式转化异常
  12. 创建线程的方式:
    (1)继承Thread
    (2)实现Runable接口
    (3)实现Callable接口(可获取线程执行之后的返回值)
    (4)Runnable与Callable的区别是,后者是有返回型的,而且是一个泛型
//如何正确开启线程
public class MyThread extends Thread {
    public static  void main(String[] args) {
        MyThread myThread = new MyThread();
//        myThread.run();//调用方法,并非开启新线程
        myThread.start();//这才是开启线程
    }
    @Override
    public  void run() {
        System.out.println(Thread.currentThread().getName()+":  running....");
    }
}

public class MyTask2 implements Callable<Boolean> {
    @Override
    public Boolean call() throws Exception {
        return null;
    }
}

//这个是可执行任务,需要其他开启
public class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" Runnable");
    }
}
  1. 什么时候使用线程安全:
    (1)多个线程访问同一资源的时候
    (2)资源是有状态的时候需要线程安全
  2. 线程中Sleep和wait的区别
    (1)所属类不同
    *sleep方法是定义在Thread上
    *wait方法是定义在object上
    (2)对锁的资源处理方式不同
    *sleep不会释放锁
    *wait会释放锁
    (3)使用范围
    *sleep可以使用在任何的代码块
    *wait必须在同步方法中或同步代码块中执行
    (4)与wait配置使用方法
    *void notify()
    *void notifyAll()