Java基础

  • 请你谈谈StringBuffer和StringBuilder有什么区别,底层实现上呢?
    1. StringBuffer线程安全,StringBuilder线程不安全,底层实现上的话,StringBuffer其实就是比StringBuilder多了Synchronized修饰符。
    2. String str = new String(“abc”)到底创建了几个对象?
      1. 答:2个对象。一个对象是”abc”,另一个是指向”abc”的引用对象”s”;
      2. 你对String对象的intern()熟悉吗?
  • 什么是不可变对象?不可变对象有什么好处?Java为什么要将String声明为final?
    1. 对象创建之后,值就不可改变。
    2. 好处?
      1. 常量池限制:多个字符串变量指向池中同一个。提高效率。只用复制地址。如果String不声明为不可变对象,则常量池失去意义。
      2. 安全性:不可变的话,账号密码这类字符串就不会被串改。
      3. 线程安全:保证多线程下的安全。
      4. hashCode固定,适合作为map的key。
    3. 衍生:如何改变String的final char[] value的值?
      1. 反射
    4. 衍生:String是不可变对象,而StringBuffer StringBuilder是可变对象。
  • 为什么重写了equals还要重写hashcode?
  • HashCode相同的对象,equals也相同吗?如何理解?
    • HashCode相同,Equal不一定相同、==不一定相同
  • 什么是值传递和引用传递?
  • int和Integer的区别? int 和Integer谁占用的内存更多?
    • Integer是int的包装类型,在拆箱和装箱中,二者自动转换。int是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象。
    • Integer 对象会占用更多的内存。Integer是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少。
  • Java中拆箱与装箱的原理?
    1. 自动装箱:编译器调用valueOf()将原始类型值转成对象;
    2. 自动拆箱:编译器通过类似intValue(),doubleValue()这些方法将对象转换成原始类型值。
  • 接口和抽象类的区别?
    1. 继承实现。接口可以继承和多实现,抽象类只能单继承;
    2. 构造方法。接口没有构造方法,抽象类有;
    3. 变量。抽象类中的变量可以使用任何权限修饰符,接口中默认public static final;
    4. (静态、抽象)方法。抽象类中的方法可以不是抽象的,接口中的方法默认都是抽象的;抽象类中可以包含静态方法,接口中不能。
    5. jdk8。接口支持lambda表达式FunctionInterface\default修饰,抽象类不支持;
    6. 抽象是对类的抽象,是一种模板设计;接口是一种行为规范。
  • 反射的原理是什么?
  • class.forname和classloader区别?
    • Class.forName()是加载类并初始化(执行static方法),但是ClassLoader的loadClass()只加载类,并不进行初始化。
  • try catch finally块中return的执行顺序
    • 当没有异常发生时,优先级finally>try

草稿:基础技术点 - 图1草稿:基础技术点 - 图2

  • 当有异常发生时,优先级finally>catch>捕获异常最外面的return

草稿:基础技术点 - 图3草稿:基础技术点 - 图4

  • 请说明Comparable和Comparator接口的作用以及它们的区别。
    1. Comparable:可以和自己比较
    2. Comparator:不支持和自己比较。比较的是两个相同类的实例。更加灵活。
  • 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
    1. Iterator的安全失败是基于对底层集合做拷贝,因此,它不受源集合上修改的影响。java.util包下面的所有的集合类都是快速失败的,而java.util.concurrent包下面的所有的类都是安全失败的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的迭代器永远不会抛出这样的异常。
  • 请你讲讲wait方法的底层原理?
    1. ObjectSynchronizer::wait方法通过object的对象中找到ObjectMonitor对象调用方法 void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) 通过ObjectMonitor::AddWaiter调用把新建立的ObjectWaiter对象放入到 _WaitSet 的队列的末尾中然后在ObjectMonitor::exit释放锁,接着 thread_ParkEvent->park 也就是wait。
  • 关于 final 关键字的一些总结

主要修饰类、方法、变量

  • 修饰类:不能被继承。所有成员方法都会隐式指定为final。
  • 修饰方法:继承类不能修改。
  • 修饰变量:对于基础数据类型,初始化之后不可修改;对于引用数据类型,初始化之后不能更改引用。
  • short s1= 1; s1 = s1 + 1; 该段代码是否有错,有的话怎么改?

有错误,short类型在进行运算时会自动提升为int类型,也就是说s1+1的运算结果是int类型。
short s1= 1; s1 += 1; 该段代码是否有错,有的话怎么改?
+=操作符会自动对右边的表达式结果强转匹配左边的数据类型,所以没错。

  • finalize 方法是在对象被回收之前调用的方法,给对象自己最后一个复活的机会,但是什么时候调用 finalize 没有保证
  • 64位的JVM当中,int的长度是多少?

Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的Java 虚拟机中,int 类型的长度是相同的。

  • java中int char,long各占多少字节? | 类型 | 位数 | 字节数 | | —- | —- | —- | | short | 2 | 16 | | int | 4 | 32 | | long | 8 | 64 | | float | 4 | 32 | | double | 8 | 64 | | char | 2 | 16 |
  • Java的深拷贝和浅拷贝
    a. 引用拷贝和对象拷贝就是浅拷贝和深拷贝吗?
    — 不是。浅拷贝和深拷贝都属于对象拷贝。浅拷贝仅复制属性的引用而不复制属性引用所指的对象。深拷贝直接复制该属性指向的对象(即原对象和新对象的属性地址不同)。
    b. 如何实现浅拷贝?如何实现深拷贝?
    — 浅拷贝:1. 实现Cloneable接口并重写clone方法。
    — 深拷贝:
    1. 1. 实现Cloneable接口并重写clone方法。
    2. 1. 通过Apache Serializable序列化方式实现。SerializableUtils.clone(obj)
    3. 1. 通过Gson()/Jackson序列化实现
    4. 1. 通过构造函数

c. Objct对象的clone()方法为什么要声明为protected? —// todo

  • Java中的++操作符线程安全吗?
    — 线程不安全。
    — 解决办法:加锁
  • 什么是ThreadLocal?

为使用该变量的每个线程维护一份独立的变量副本,每个线程都可以改变自己的副本,而不影响其他线程的副本;

  • 注解
  • 泛型解决了什么问题?
  • switch是否可以使用string作参数?byte?long?
    • JDK1.7之后可以用string
  • Object对象有哪些方法?
    • wait/notify
    • public native Object clone() throws CloneNotSupportedException
    • hashCode
    • equals
    • toString
    • finialize
    • getClass
    • private static native void registerNatives();
  • wait/notify机制
    1. 在wait/notify之前,为什么要先获取synchronized锁?(即 wait notify为什么必须放在同步块中?)
    2. 线程A获取了锁,执行wait方法挂起,线程B又如何再获取锁?
    3. wait/notify底层实现原理?

— 解答:

  1. 在wait/notify之前,为什么要先获取synchronized锁?(即 wait notify为什么必须放在同步块中?

— native wait0()的注释
草稿:基础技术点 - 图5
意思是:线程执行lock.wait方法时,必须拥有该lock的monitor,而synchronized的字节码拥有monitorEnter、monitorExit指令,所以需要放在synchronized同步块中。
进一步说:
详解:JVM源码分析之Object.wait/notify实现

  • 讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。

IO

  1. Java NIO常用的三个类
    1. 同步IO和异步IO
      1. IO操作分2个步骤,请求IO和实际IO,同步IO和异步IO的主要区别是第二步是否阻塞
      2. 若实际IO操作阻塞请求进程(即请求进程轮询查看IO是否就绪),则为同步IO。
      3. 若实际IO操作并不阻塞请求进程(即由OS进行实际IO操作并返回结果),则为异步IO。
    2. 阻塞IO和非阻塞IO
      1. 阻塞和非阻塞IO的区别在于第一步是否阻塞。
      2. 若发起IO请求后,请求线程一直等待时间实际IO操作完成,则为阻塞IO。
      3. 若发起IO请求后,请求进程返回而不等待,则为非阻塞IO。
    3. BIO、NIO、AIO
      1. BIO-同步阻塞
      2. NIO-同步非阻塞
      3. AIO-异步非阻塞
      4. 草稿:基础技术点 - 图6
  1. 草稿:基础技术点 - 图7

集合

  • JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。
  • HashMap为什么长度超过8会转成树结构?为什么<=6会还原成链表?
    • 红黑树的平均查找长度为O(logN),长度为8是,平均查找长度为3,如果继续使用链表,则查找长度为8/2=4
      - 如果长度<=6,则链表的平均查找长度为3,所以会转换成链表
    • 选择6和8,中间缓冲一个7可以有效防止链表和树之间的频繁转换

线程

  • 线程状态有哪些? 线程池状态转换是怎么样的?

JUC

MySQL

其他

  1. 为什么阿里巴巴禁止把SimpleDateFormat定义为static类型的?
    1. 解决方案
      1. 加锁
      2. 使用JDK1.8的DateTimeFormatter
      3. 使用ThreadLocal

草稿:基础技术点 - 图8