深拷贝和浅拷贝

  • 赋值就是拷贝
  • 基本数据类型不存在深拷贝和浅拷贝的区别
  • 引用类型之间进行地址的赋值:arr2 = arr1的形式,就是浅拷贝。
  • 如果将引用的对象也进行赋值,arr1和arr2不再指向同一个地址,就是深拷贝。

值传递方式

四种引用方式

更好的阅读体验

gc就是城管,强引用就是当地人,软引用就是移民的人,弱引用就是黑户口,哪天城管逮到就遣走,虚引用是个死亡证明,一般活人是根本不用的,只有人挂了的时候,去火葬场才能查到是哪个人挂了

面试题

  1. 为什么说 Java 语言“编译与解释并存”?
  2. Java 泛型了解么?什么是类型擦除?介绍一下常用的通配符?
  3. hashCode()与 equals()
  4. 为什么要有 hashCode?
  5. 什么重写 equals 时必须重写 hashCode 方法?
    为什么重写equals()方法时,必须要求重写hashCode()方法?
  6. 自动装箱与拆箱
  7. 8 种基本类型的包装类和常量池
    Integer,Long,Short,Byte 创建常量的时候,如果常量在-128-127 ,就从常量池中取数据,否则新建一个对象
    Integer i1=40;Java 在编译的时候会直接将代码封装成 Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。
    Integer i1 = new Integer(40);这种情况下会创建新的对象。
  8. 重载和重写的区别
  9. 深拷贝 vs 浅拷贝
    其实就是传递对象的时候,如果new了一个新的对象,就是deepclone,如果创建了一个对象引用传递的对象,就是shallow clone
  10. 在 Java 中定义一个不做事且没有参数的构造方法的作用
  11. 成员变量与局部变量的区别有哪些?
  12. 一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?
  13. 在一个静态方法内调用一个非静态成员为什么是非法的?
    静态方法和变量是在类中创建的,而非静态成员是在对象中创建的,因此静态方法肯定不能调用非静态成员。
    而实例方法调用静态非静态都可以。
  14. String StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?
    StringBuffer与StringBuilder 的区别
    String: final修饰的char数组,每次改变需要重新创建新的String对象
    StringBuffer: 加了同步锁Synchronized,线程安全,每次修改对本身进行操作 append,delete,replace,insert
    StringBuilder,没有加同步锁,因此效率比StringBUffer高10%~20%,但是线程不安全
  15. Object 类的常见方法总结
  1. public final native Class<?> getClass()//native方法,用于返回当前运行时对象的Class对象,使用了final关键字修饰,故不允许子类重写。
  2. public native int hashCode() //native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的HashMap。
  3. public boolean equals(Object obj)//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用户比较字符串的值是否相等。
  4. protected native Object clone() throws CloneNotSupportedException//naitive方法,用于创建并返回当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常。
  5. public String toString()//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个方法。
  6. public final native void notify()//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
  7. public final native void notifyAll()//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
  8. public final native void wait(long timeout) throws InterruptedException//native方法,并且不能重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。
  9. public final void wait(long timeout, int nanos) throws InterruptedException//多了nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上nanos毫秒。
  10. public final void wait() throws InterruptedException//跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
  11. protected void finalize() throws Throwable { }//实例被垃圾回收器回收的时候触发的操作

```

JavaSE知识点二

BigDecimal:

  • BigDecimal可以精确储存小数;
  • 使用conpareTo的方法进行两个数比较 a.compareTo(b);
  • 构造igDecimal使用ValueOf或者String来构造
  • BigDecimal b = new BigDecimal(“0.1”)
    BigDecimal b = BigDecimal.valueOf(0.1)
  • BigDecimal 的实现利用到了 BigInteger, 所不同的是 BigDecimal 加入了小数位的概念

基本数据类型与包装数据类型的使用标准

  • 所有的 POJO 类属性必须使用包装数据类型。
    • 数据库的查询结果可能是 null,因为自动拆箱(定义了int 即使传回来的是Integer,自动拆箱成int),用基本数据类型接收有 NPE 风险。
  • RPC 方法的返回值和参数必须使用包装数据类型。(Remote Procedure Call)

    • rpc详解及实现
    • 比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

      集合

      Arrays.asList(): 我们可以使用它将一个数组转换为一个List集合。

      基本知识点 - 图1
      Arrays.asList()是泛型方法,传入的对象必须是对象数组。
      String[] myArray = {“Apple”, “Banana”, “Orange”};
      List myList = Arrays.asList(myArray);
      //上面两个语句等价于下面一条语句
      List myList = Arrays.asList(“Apple”,”Banana”, “Orange”);

      1. /**<br /> *返回由指定数组支持的固定大小的列表。此方法作为基于数组和基于集合的API之间的桥梁,<br /> * 与 Collection.toArray()结合使用。返回的List是可序列化并实现RandomAccess接口。<br /> */<br /> public static <T> List<T> asList(T... a) {<br /> return new ArrayList<>(a);<br /> }

List myList = Arrays.asList(myArray);
System.out.println(myList.size());//1
System.out.println(myList.get(0));//数组地址值
System.out.println(myList.get(1));//报错:ArrayIndexOutOfBoundsException
int[] array = (int[]) myList.get(0);
System.out.println(array[0]);//1
当传入一个原生数据类型数组时,Arrays.asList() 的真正得到的参数就不是数组中的元素,而是数组对象本身!此时List 的唯一元素就是这个数组,这也就解释了上面的代码。
Arrays.asList() 方法返回的并不是 java.util.ArrayList ,而是 java.util.Arrays 的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。

List myList = Arrays.asList(1, 2, 3);
System.out.println(myList.getClass());//class java.util.Arrays$ArrayList

Collection.toArray()方法使用的坑&如何反转数组

  • T[] toArray(T[] a);
  • 如何反转数组?
    • String[] s = new String[]{“dog”};
      - List list = new ArrayList(Arrays.asList(s));
      - Collections.reverse(list);
      - s = list.toArray(new String[0]);

new String[0]就是起一个模板的作用,指定了返回数组的类型,0是为了节省空间,因为它只是为了说明返回的类型。

Collection 和 Collections的区别
  • Collection是集合的上层接口,Collections是一个辅助类,有集合元素的添加、二分搜索、排序和反转等操作

    集合的删除注意事项:不要在 foreach 循环里进行元素的 remove/add 操作 & fail-fast 机制

  • 如果要进行remove操作,可以调用迭代器的 remove 方法而不是集合类的 remove 方法。因为如果列表在任何时间从结构上修改创建迭代器之后,以任何方式除非通过迭代器自身remove/add方法,迭代器都将抛出一个ConcurrentModificationException,这就是单线程状态下产生的 fail-fast 机制。

  • 在foreach循环外,使用Collection#removeIf()条件删除集合的元素。
  • fail-fast 机制 :多个线程对 fail-fast 集合进行修改的时,可能会抛出ConcurrentModificationException,单线程下也会出现这种情况,上面已经提到过。fail-fast机制源码分析
  • java.util包下面的所有的集合类都是fail-fast的,而java.util.concurrent包下面的所有的类都是fail-safe的。fail-fast(快速失败)机制和fail-safe(安全失败)机制的介绍和区别
  • 基本知识点 - 图2

下面代码报并发修改异常 这就是fast-fail机制迭代器在调用next()、remove()方法时都是调用checkForComodification()方法,该方法主要就是检测modCount == expectedModCount ? 若不等则抛出ConcurrentModificationException 异常,从而产生fail-fast机制。
public static void main(String[] args){
List list = new ArrayList<>();
list.add(“1”);
list.add(“2”);
String item = “1”;
Iterator iterator = list.iterator();
while(iterator.hasNext()){
/System.out.println(“删除:” + iterator.next());
iterator.remove();
/
if (“1”.equals(item))
list.remove(item);
System.out.println(iterator.next());
}
}