//hotspot的oop.hpp文件中class oopDescclass oopDesc { friend class VMStructs; private: volatile markOop _mark; //对象头部分 union _metadata { // klassOop 类元数据指针 Klass* _klass; narrowKlass _compressed_klass; } _metadata;复制代码
public static void main(String[] args){ Object a = new Object(); // 16B 关闭压缩还是16B,需要是8B倍数;12B+填充的4B int[] arr = new int[10]; // 24B 关闭压缩则是16B } public class ObjectNum { //8B mark word //4B Klass Pointer 如果关闭压缩则占用8B //-XX:-UseCompressedClassPointers或-XX:-UseCompressedOops, int id; //4B String name; //4B 如果关闭压缩则占用8B byte b; //1B 实际内存可能会填充到4B Object o; //4B 如果关闭压缩则占用8B } 复制代码
2^11 * 4G
。不过jvm只是将指针左移三位,因此最大范围是 2^3 * 4G = 32G
。如果 大于32G ,指针压缩会失效。如果GC堆大小在 4G以下 ,直接砍掉高32位,避免了编码解码过程 -XX:+UseCompressedOops
( 默认开启 ),禁止指针压缩: -XX:-UseCompressedOops
private static native void registerNatives() public final native Class<?> getClass() public native int hashCode() protected native Object clone() throws CloneNotSupportedException public final native void notify() public final native void notifyAll() public final native void wait(long timeout)
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode());}public boolean equals(Object obj) { return (this == obj);}public final void wait(long timeout, int nanos) throws InterruptedException;//都是基于native void wait(long timeout)实现的public final void wait() throws InterruptedException; wait(long timeout, int nanos)、wait() //jvm回收对象前,会特意调用此方法 protected void finalize() throws Throwable;复制代码
如不指定排序顺序,java里的默认排序顺序是升序的,从小到大
public boolean equals(Object obj) { return (this == obj);}
Collections.java//Collections.sort(List<T> list),调用的是List的sort方法public static <T extends Comparable<? super T>> void sort(List<T> list) { list.sort(null); }复制代码
List的sort 则调用了Arrays.sort
List.javadefault void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } }复制代码
如果Comparator c 为null,则是调用 Arrays.sort(Object[] a) ;最终调用LegacyMergeSort(归并排序)方法处理
Arrays.javapublic static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } }复制代码
LegacyMergeSort方法里的一段代码;最终底层是使用 归并排序 和compareTo来排序
Arrays.java ...... if (length < INSERTIONSORT_THRESHOLD) { for (int i=low; i<high; i++) for (int j=i; j>low && ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--) swap(dest, j, j-1); return; }复制代码
Comparator也是一个接口,不过提供了更丰富的操作,需要实现 int compare(T o1, T o2)
方法
Comparator提供了常用的几个静态方法thenComparing、reversed、reverseOrder(操作对象需要实现Comparator或者Comparable);可配合List.sort、Stream.sorted、Collections.sort使用。
@Data @AllArgsConstructorstatic class Pair implements Comparator<Pair>, Comparable<Pair> { Integer one; Integer two; @Override public String toString() { return one + "-" + two; } @Override public int compareTo(Pair o) { return one.compareTo(o.one); } @Override public int compare(Pair o1, Pair o2) {return o1.compareTo(o2);} }public static void main(String[] args) { List<Pair> col = Arrays.asList( new Pair(4, 6), new Pair(4, 2),new Pair(1, 3)); col.sort(Comparator.reverseOrder()); col.stream().sorted(Comparator.comparing(Pair::getOne).thenComparing(Pair::getTwo)) .forEach(item -> System.out.println(item.toString()) ); }复制代码
Collections.sort默认是升序排序的,可以看到reverseOrder将顺序反过来了;用了thenComparing的col则是先判断Pair::getOne的大小,如果相等则判断Pair::getTwo大小来排序
result:4-6 4-2 1-3 ---------------- 1-3 4-2 4-6复制代码
构造方法是每一个类独有的,并不能被子类继承,因为构造方法没有返回值,子类定义不了和父类的构造方法一样的方法。但是在同一个类中,构造方法可以重载
public class TestEquals { int i; public TestEquals() { i = 0; } //构造方法重载 public TestEquals(int i) { this.i = i } }复制代码
equals是用来比较两个对象是否相等的,可以重写该方法来实现自定义的比较方法;而hashCode则是用来获取对象的哈希值,也可以重写该方法。当对象存储在Map时,是首先利用Object.hashCode判断是否映射在同一位置,若在同一映射位,则再使用equals比较两个对象是否相同。
如果重写equals导致对象比较相同而hashCode不一样,是违反JDK规范的;而且当用HashMap存储时,可能会存在多个我们自定义认为相同的对象,这样会为我们代码逻辑埋下坑。
Object.wait是需要在synchronized修饰的代码内使用,会让出CPU,并放弃对对象锁的持有状态。而Thread.sleep则简单的挂起,让出CPU,没有释放任何锁资源
ObjectInputStream.readObject()
String one = new String("Hello");
题外话:string.intern();intern先判断常量池是否存相同字符串,存在则返回该引用;否则在常量池中记录堆中首次出现该字符串的引用,并返回该引用。
如果是先执行 String s = "hello" ;
相当于执行了intern();先在常量池创建"hello",并且将引用A存入常量池,返回给s。此时String("hello").intern()会返回常量池的引用A返回
String one = "hello"; String two = new String("hello"); String three = one.intern(); System.out.println(two == one); System.out.println(three == one); result: false // one虽然不等于two;但是它们具体的char[] value 还是指向同一块内存的 true // one 和 three 引用相同复制代码
A a = new A(); A b = a;
此时a和b指向同一块内存的对象 @Getterstatic class A implements Cloneable{ private B b; private int index; public A(){ b = new B(); index = 1000; } public A clone()throws CloneNotSupportedException{ return (A)super.clone(); } }static class B{ }public static void main(String[] args) throws Exception{ A a = new A(); A copyA = a.clone(); System.out.println( a.getIndex() == copyA.getIndex() ); System.out.println( a.getB() == copyA.getB() ); } @Getterstatic class A implements Cloneable{ private B b; private int index; public A(){ b = new B(); index = 1000; } public A clone()throws CloneNotSupportedException{ return (A)super.clone(); } }static class B{ }public static void main(String[] args) throws Exception{ A a = new A(); A copyA = a.clone(); System.out.println( a.getIndex() == copyA.getIndex() ); System.out.println( a.getB() == copyA.getB() ); }复制代码
//返回结果都是true,引用类型只是复制了引用值truetrue复制代码
深复制:重写clone方法时使用序列化复制,(注意需要实现Cloneable,Serializable)
public A clone() throws CloneNotSupportedException { try { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(this); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream inputStream = new ObjectInputStream(byteIn); return (A) inputStream.readObject(); } catch (Exception e) { e.printStackTrace(); throw new CloneNotSupportedException(e.getLocalizedMessage()); } }复制代码