Java作业

来源:互联网 发布:淘宝网购物女装晚礼服 编辑:程序博客网 时间:2024/05/21 11:34

常年与Java打交道,总会遇到各种问题,都一一记录下来了。
为督促自己的学习,也为了与大家分享,写下本文,并持续更新。


Object中的方法

  • private static native void registerNatives(),本地方法,在Object类初始化的时候注册其他native方法 hashCodewaitnotifynotifyAllclone,源码位于Object.c
  • public final native Class<?> getClass(),从oop_metadata中读取_klass_compressed_klass
  • public native int hashCode(),返回对象的identity hash code。具体实现还和锁有关:

    • 当一个对象已经计算过identity hash code,它就无法进入偏向锁状态

    • 当一个对象当前正处于偏向锁状态,并且需要计算其identity hash code的话,则它的偏向锁会被撤销,并且锁会膨胀为重量锁;

    • 重量锁的实现中,ObjectMonitor类里有字段可以记录非加锁状态下的mark word,其中可以存储identity hash code的值。或者简单说就是重量锁可以存下identity hash code。

    来源:RednaxelaFX在知乎“当Java处在偏向锁、重量级锁状态时,hashcode值存储在哪?”下的回答

  • public boolean equals(Object obj),需要满足自反性、对称性、传递性、一致性。

  • protected native Object clone() throws CloneNotSupportedException,由虚拟机实现的对象拷贝方法。对于没有实现java.lang.Cloneable接口的对象,JVM有能力拷贝,但是拒绝拷贝。拷贝时先开辟一块相等的内存空间,然后以jlong(8字节)为原子,从头按顺序拷贝内容。期间原始对象的内容可能改变,因此clone()不是线程安全的,需要自行加锁。但是因为对象内部的所有数据都是以8字节对齐的,所以不会出现只拷贝了半个引用或者只拷贝了半个double的情况。
  • public String toString(),人可读的描述信息。
  • public final native void notify()
    public final native void notifyAll()
    public final native void wait() throws InterruptedException,调用这三个方法的位置都必须同步,并且执行时都会导致偏向锁膨胀为重量级锁。
  • protected void finalize() throws Throwable,实现了这个方法的对象会在初始化时被包装成java.lang.ref.Finalizer塞到Finalizer维护的链表unfinalized中。通过实现这个方法,对象可以在被垃圾回收之前做些事情,比如可以发送一些通知,或者避免自己被垃圾回收,且这个机会最多只有一次,因为这个对象不可能再次进入链表中了。其实finalize()的实现和软、弱、虚引用有些相似,都是java.lang.ref.Reference的子类,通过引用队列实现的。

虚引用实践

整理为博客《弱引用、虚引用、finalize实践,及它们的顺序》


WeakHashMap的实现

WeakHashMapEntry继承自WeakReference,且其referent为entry的key,也就意味着,只要一个entry的key被回收,这个entry就被加入到引用队列中。在WeakHashMapget()put()forEach()size()remove()等诸多方法调用的时候都会调用到一个expungeStaleEntries()方法,这个方法就会遍历引用队列来清理无用的entry。


try-return-finally-return

// 返回值是0private static int foo1() {  int i = 0;  try {    return i; // 生效  } finally {    i++;  }}// 返回值是1private static int foo2() {  int i = 0;  try {    return i;  } finally {    return ++i; // 生效  }}// 返回值是1private static int foo3() {  try {    return 0;  } finally {    return 1; // 生效  }}

总结:finally中的赋值不会改变try中已经计算好的返回值,但是finally中的return会截胡。


编译器常量

final字面量在编译时会被替换为常量。包括final的类属性、final的本地变量。


Arrays.asList(array)的返回值和数组绑定且不可修改?

这个竟然是真的。。。。

Arrays.asList()的返回值不是java.util.ArrayList,而是java.util.Arrays$ArrayList,它没有重写任何定义在AbstractList中的新增和删除有关的方法,因此尝试新增或删除时会调用到AbstractList中的版本,直接抛出异常。

原地排序、修改以及读取,这些底层数组支持的操作都是支持的。


接口和抽象类的区别

Java8和Java9对接口的改变太大了,最近时常会疑惑,为什么接口和抽象类越来越像了。。

其实还是很多“底线”没有突破的,比如单继承和多实现。

下面整理一下,接口简写为I,抽象类简写为A

  • A既可以声明abstract方法,又可以定义任意可见性的带方法体的方法,I只能声明public abstract方法
    • Java8开始I可以声明default方法,也可以声明static方法
    • 预计Java9开始I可以声明private方法
  • A可以声明变量,I只能定义常量
  • A可以extends A,也可以implements II只能extends I
  • 一个类只能extends一个A,但可以implements多个I
  • AconstructorI没有

顺序读写/随机读写 RandomAccessFile

常规使用ReaderWriterInputStreamOutputStream读写文件都是顺序读写,进行随机读写需要使用java.io.RandomAccessFile


20170513 最后更新

0 0