(2016年3月31日 14:01:07)

1. 反射

运行时metadata元数据

java可以在运行时获得对象的类、方法、成员变量等信息,可以动态加载类字节码、创建实例、调用方法、执行java代码等等。这种能力是C++不具备的。常用的工具是:动态代理,Spring的AOP核心就用这个,分2种,jvm自带的基于接口的动态代理,还有cglib基于继承的代理。

注解annotation

注解在框架中被广泛使用,注解不同于注释,它会被编译到字节码中。可以给以下地方加注解:类、方法、成员变量、参数,并在运行时动态读取到。注解的值可以是基本类型、String、枚举等及其数组。https://code.pugwoo.com/learning/j2se/src/branch/master/annotation

2. jvm基础

异常:Throwable/Error/Exception/RuntimeException
try -> catch -> finally

类加载

类加载由ClassLoader实现类完成,加载顺序有父类开始加载,父类加载不到则委托给子类加载,直到加载到为止或最终加载不到抛ClassNotFoundException。

  • Bootstrap ClassLoader 负责加载java基础类
  • Extension ClassLoader 负责加载java扩展类,%JRE_HOME/lib/ext
  • App ClassLoader 负责加载当前java应用的classpath中的所有类。

classLoader呈树形结构,根是bootstrapClassloader,当前classLoader只能加载其直系父类的类,tomcat中不同webapp就是这样隔离类.
不同的classLoader中的类不能()强制转换类型,父子classLoader也不行。
自己继承ClassLoader定制加载类:本质上拿到编译后的.class的二进制byte[],就可以调用classLoader类的define方法加载类。定制的加载类的父类是AppClassloader。
classLoader看到的是二进制,所以类可以来自于网络,甚至是cglib之类生成。
Class.forName和ClassLoader.loadClass区别:后者进行类初始化。

枚举

java的枚举很强大,可以有枚举自己的属性、方法、还可以覆盖方法(abstract强制枚举实现)
有时,会直接用interface的变量来作为枚举使用。(默认就是final的)

泛型:泛型是编译器才有的,用于编译时检查。运行时就没有泛型的信息,可能抛出ClassCastException。
泛型支持限制 和 <T extends Number & Comparator>
使用1: 类和接口定义时名称上加上或<T1,T2>等。
使用2: 方法在关键词后面,返回值前面加上
数组可以转化为其父类的引用,而泛型则不行。

实例化顺序:静态(类成员,初始化代码块) -> 类成员->初始化代码块 -> 构造方法
注:构造方法是static方法,可以访问static变量。

进程结束时做点事情:Runtime.getRuntime().addShutdownHook(shutdownThread);

内部类:
1) 非静态内部类:相当于依赖于外部类实例的闭包,可以访问外部类的成员变量,不能有static method和非final的static变量,testInternalClass.new InternalClass();
2) 静态内部类(用的多):就如同一个普通的类一样,不依赖于外部类的实例。唯一比普通类多的就是可以访问外部类private静态变量,动态变量不行。new TestStaticInternalClass.InternalClass()

类加载资源:XXXClass.class.getResource(“/root.txt”) 可以指定根目录或相对目录
(使用classloader的时候,不可以指定“/”来读取)
读取时,源码和jar包同等对待。

String和正则表达式:
String是有编码的byte[],String内部的编unicode(utf-8),乱码只有可能是转成String时指定错了编码。
replace没有正则,replaceAll有正则,可以用来去除某些不要的字符
StringBuffer线程安全和StringBuilder

jni/jna可以加载.a.so.dll动态链接库并调用。

一般使用BigDecimal来表示价格,或者按分来存价格。mysql数据库也有对应的decimal的类型。

根据 Java 规范,两个使用 equal() 方法来判断相等的对象,必须具有相同的hash code。这样HashMap才能正常工作。

内存回收

GC回收算法:
标记清除法 从根object为所有被引用的对象标记上,没有标记的对象就是访问不到的对象,就是可以被回收的对象。
分代 本质上是根据对象的存活时间分区块存储。有点类似db的分库分表。

3. 容器相关

数组和List
数组[]和其工具类Arrays,快速复制,一般业务上用得少,除非关注性能
List主要有ArrayList和LinkedList

线程安全的List就用Vector

Map
Map常用的就HashMap和LinkedHashMap
Hash的方式基本就两种:分桶和N次探测法

工具类Collections
常用:排序sort(实现Comparator)、二分查找、转不可变List、反转、最大值

线程安全的各种容器
1) 普通的List、Map的实现都不是线程安全的。线程安全的容器,实际上就是把线程同步集成在容器实现中,更加内聚了。
2) BlockingQueue 线程安全的生产者消费者模型,类似linux的msgq,好用

ConcurrentHashMap 当这个map是类共享变量读写时,需要用到。关于性能:如果hashmap写方法加上synchronized,也是线程安全的,但性能不行。所以实际上是分桶来锁的,这样就可以用多个锁来管hash桶。
PriorityQueue

List遍历中删除/新增一个元素,Iterator是唯一安全的方式。或者用jdk8的removeIf

100. 原Guava工具类

2014年那会使用的Guava工具类,现已经基本被woo-utils代替,好的特性已经重新实现到woo-utils中了。当时比较看中的功能:

1) 排序器Ordering(大返回1,等于返回0,小返回-1及各种组合,更友好的方式是返回一个本来可以Comparable的字段);Base64 encode decode;md5;Longs.tryParse;Throwables包装Exception;Joiner;
2)本地Cache,可以设置超时等
3)多线程的Minitor和Monitor.Guard,可以实现线程同步(阻塞等待)
4)guava的不可变ImmuatbleMap之类很实用;MutilMap代替Map>这种;Table代替Map>;集合操作Sets;
5)函数化编程习惯:Function,结合Lists.transform等使用
6)IO:对文件的读取都放在Files工具类中。

文档更新时间: 2020-12-15 21:54   作者:nick