1. boolean 占一位 而不是一个字节! 0 - 1 ,默认是 0
2. 除了八种基础类型,其他的都是引用类型,初始化都是null;
八种类型是 int:0 double0.0 char:\u0000 boolean:0
3. 方法参数是值传递
4. 内存:
栈(stack):自动分配连续的空间,后进先出;放局部变量
堆(heap):不连续,放创建出来的对象(new 出来的)
方法区在堆里面:类的信息(代码)、static变量、常量池(字符串)
5. java 三大特性:
-
1. 封装
-
2. 继承
-
3. 多态
6. 继承可提高代码的复用性
7. 所有的构造器中的第一句话 都是 super() - 都是调用弗雷的构造器
8. 对于StringBuilder以及ArrayList的操作,其实就是对数组的操作!底层的很多方法以及实现方式都是一样的
例如 remove方法 都是使用 System.arraycopy,add的扩容也是;
关于扩容: StringBuilder是16,遇到int时是原长度的2倍进行增加的,而ArrayList是10
9.java底层判断两个对象是否相等都是使用的equals,例如ArrayList中的remove方法;
10. 一般来讲只要是需要用哈希类型的数据结构,都需要重写hashcode()和equals(),例如HashMap,它就是使用hashcode来确定数组下标,但是为了不丢失hashcode相同的值,所以数组中每一项都是一个单向链表;因此,查找顺序是先使用hashcode确定数组项,然后再使用equals()遍历链表找到目标值;
下面是HashMap.put()的部分源代码:
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
11. HashSet的底层是用HashMap实现的;
12. 遍历HashMap:其实就是遍历map中的 EntrySet
Iterator<Map.Entry> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}
或者使用 foreach
Set<Map.Entry> set = map.entrySet();
for (Map.Entry entry : set) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
13. 泛型就是标签,泛化类型;
泛型不能使用在静态属性上,但是可以卸写在公共的抽象方法上;
泛型是在声明的时候指定具体的类型的,不能为基本类型,只能是引用类型;
泛型没有多态;
数组不能用泛型;
14. 一般乱码问题:1.编码与解码的字符集不统一;2.字节缺少,长度丢失;
15. 把不需要序列化的属性添加transient;
16. 一些数据结构中的存储单元都是由transient修饰的,例如 ArrayList LinkedList。 原因:elementData是一个缓存数组 ,它通常会预留一些容量,等容量不足的时候扩容,例如现在有5个元素,而elementData的实际容量是10,那序列化的时候只需要存储5个元素就可以了,后面5个元素不需要存储,没有意义。所以,ArrayList把elementData设计为transient,然后在writeObject()方法中将其序列化,并且只序列化了实际存储的那些元素,而不是整个数组;
17. java1.7 io流的关闭可以使用 try catch with resource
/**
* 1.7 try with resource
*/
public static void close() {
double d = 2.5;
long num = 100l;
String str = "数据类型";
File dest = new File("f:/demo/testData.txt");
//声明流
try (
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
) {
dos.writeDouble(d);
dos.writeLong(num);
dos.writeUTF(str);
dos.flush();
dos.close();
} catch (Exception e) {
}
}
18. volatile字段的写入操作先于读操作,所以总是能拿到最新的值!
19. ConcurrentLinkedQueue 的tail:
入队主要是做两件事情: 1. 将入队节点设置为当前队列列尾节点的下一个节点。2. 如果tail节点的next节点不为空,则将入队节点设置成tail节点,如果tail节点的next节点为空,则将入队节点设置成tail的next节点,所以tail节点不总是尾节点!