Java 基础
JDK 和 JRE 是入门第一问。JDK(Java Development Kit)是开发工具包,包含了 JRE 以及 javac 编译器和调试工具;JRE(Java Runtime Environment)就只是运行环境。装了 JDK 自然就有了 JRE,反过来不行。开发用 JDK,服务器上只跑应用的话装个 JRE 就够了。
== 和 equals 的区别在面试里出现频率极高。简单说,对于基本类型,== 比较值是否相等;对于引用类型,== 比较两个变量是否指向同一块内存。equals 方法在 Object 类里就是 ==,所以默认是比较引用。但 String、Integer 这些类重写了 equals,改成了比较内容。看代码:
String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x == y); // true
System.out.println(x == z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true
x 和 y 指向常量池同一个引用,== 就是 true;而 z 是 new 出来在堆上的新对象,== 自然是 false。equals 全 true 是因为 String 重写了它。这也解释了为什么两个 hashCode 相同的对象 equals 不一定为 true——'通话'和'重地'就是典型案例,hashCode 都是 1179395,但字符串内容不同。
final 关键字用法:修饰类则类不可继承,修饰方法不可重写,修饰变量变成常量,必须初始化且之后不能修改。
Math.round(-1.5) 返回 -1。取整规则是向数轴右侧取,正数 0.5 向上取整,负数直接舍去小数,记住就好。
String 不是基本类型,Java 的基本类型就八种:byte、boolean、char、short、int、float、long、double。操作字符串时,String 是不可变对象,每次拼接都会产生新对象,所以频繁改动时该用 StringBuffer 或 StringBuilder。二者区别在于 StringBuffer 线程安全但慢,StringBuilder 快但在多线程下不安全。单线程场景优先 StringBuilder。还有,String str="i" 这种方式从常量池取,new String("i") 则在堆上分配,两回事。反转字符串直接用 new StringBuilder(str).reverse().toString() 就行。常用方法就不一个个列了,indexOf、charAt、replace、trim、split、getBytes、length、toLowerCase、toUpperCase、substring、equals 这些查 API 都能看到。
抽象类不一定包含抽象方法,但包含抽象方法的类一定得声明为抽象类。抽象类不能实例化,也不能用 final 修饰——这两个限制互相矛盾。接口和抽象类:一个类只能继承一个抽象类,但可以实现多个接口;抽象类可以有构造方法,接口不行;接口方法默认 public,抽象类没有这个限制。
Java IO 流分字节流和字符流,字节流按 8 位传输,字符流按 16 位传输,处理文本时字符流更方便。BIO 是传统的同步阻塞 IO;NIO 同步非阻塞,基于 Channel 和多路复用;AIO 是异步非阻塞,基于事件回调。文件操作现在多用 Files 工具类,exists、createFile、createDirectory、delete、copy、move、size、read、write 这些静态方法基本覆盖了日常需求。
容器
Java 集合框架分 Collection 和 Map 两大体系。Collection 下面有 List(有序可重复)和 Set(无序不可重复),List 的实现主要是 ArrayList(动态数组)和 LinkedList(双向链表),还有线程安全的 Vector 和 Stack;Set 常见的有 HashSet、LinkedHashSet、TreeSet。Map 存键值对,键不能重复,常用 HashMap、LinkedHashMap、TreeMap、Hashtable 以及并发下的 ConcurrentHashMap。


