- Java 8 default method
- Java 8 中新增了 default method,就是可以给接口增加默认实现方法 
- 由于接口支持多继承,所以这种做法其实变相实现了多继承 
- 但是 default method 的设计目的不是为了实现多继承 
- 而是为了给 Java 原来的 Api 提供一些默认实现,比如: 
- java.utils.List - 是一个列表接口,Java 8 之前它没有任何的实现 
- 如果你想要给数组排序,只能调用其他的工具类实现 
- 但是在 Java 8 中就给它新增了一个 sort 接口 
 
- 这个 default method 和普通方法一样也可以被重写 
- Java If 语句的一个隐藏功能
- Java 的 if 语句,如果判断条件确定为 false,那么再编译的时候这个 if 会被编译器扔掉,如果确定为 true,则会去掉判断条件,直接运行条件内部代码 
- 比如这种代码: - final bool condition = false; if(condition){ System.out.println("i am deleted"å); }
- 在编译后下面的代码都被删了,这个规定只限于 if 语句,while/for 不会删掉 
- 有什么用呢? 
- 比如在项目里有些功能只在开发时候使用,你就可以定义一个全局的开关,然后这些功能都写在 if 语句中,在上线的时候把开关设置为 false,这部分代码就会被忽略 
- 补充一下 Java Class 相关
- int.class 和 Integer.class 不是同一个对象 
- 看了一下字节码 int.class 对应的是: 
 
- Integer.TYPE,是一个静态属性 
 
- 注意这里的 Class 不是通过常规的 ClassLoader 加载类生成的,而是通过一个叫: 
- static native Class<?> getPrimitiveClass(String name);
- 这个 Native 方法生成的 
- JVM的实现中,在JVM初始化的时候就会把原始类型和void对应的Class对象创建出来。这些Class对象的创建不依赖任何外部信息(例如说需要从Class文件加载的信息),不需要经历类加载过程,而纯粹是JVM的实现细节。 
- void 也有对应的 Class,这些都是为了反射方便 
 
- Java 基类和它们的包装类
- 关于 Java 为什么不直接用包装类替换基本类型 
- 1.基本类型不存在 null,一旦初始化 JVM 就会给其出生值,而包装类初始化时值为 null 
- 2.基本类型比包装类轻量 
Long sum = 0L; // uses Long, not long
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
  sum += i;
}
- 上面这段代码测试耗时 6.765s,但是如果把 Long 换成 long 结果是 0.966s 
- 因为如果使用 Long sum += i 的过程要不断的创建 Long 对象 
- 3.基本类型可以直接用 == 比较大小 
- Java 信号量
- 之前做广告有个需求,要求多个广告 SDK 按顺序加载广告,最开始想的是通过 Java 提供的锁 Lock 控制,但是 Lock 的申请和释放必须在同一个线程,而下一个广告 SDK 要等这个 SDK 请求成功或者失败后才能加载,SDK 所在线程又不好控制,所以使用 Lock 不合适 
- 后来查到 Java 提供一个信号量机制,感觉特别合适:Semaphore,它特别适合资源控制并发数量 
- 比如你首先定好最大并发数量是 1: - Semaphore s = new Semaphore(1)然后在第一个广告进入时调用- s.acquire()申请到资源
- 如果资源不足就会阻塞等待,如果没有申请打就会阻塞,在广告成功或失败时调用 - s.release()释放资源,此时其他等待的线程就会再去竞争资源,申请和释放没有线程的限制非常适合当前使用场景
- Java 线程安全
- 关于线程安全,从 Java 的角度,就是保证原子性操作,比如 
- int a = 1 
- 线程1 执行 a++ 
- 线程2 执行 a++ 
- 这个过程假设线程1 先从主内存中拿到 a 并存在线程内存中 a‘,这个时候 a’ = 1,然后在当前线程执行 a++ 其实是 a’++,等计算完成后再写回到主内存,就像是 a = a’ 
- 这个过程一共是三步 
- 如果不加锁,线程2 拿到的 a 可能是 1 也可能是在线程1执到的第 1,2,3 步的时候 
- 如果在线程1的第 1,2,步拿到的,此时 a 还是 1 

