java 学习资料总结
- 1. java集合深入理解
- 1.1 迭代器的快速失败机制 fast-fail
- 1.2 collection 集合
- 1.3 List集合
- 1.3.1 ArrayList
- 1.3.2 LinkList
- 2. Map 综述
- 2.1 彻头彻尾理解 HashMap
- 2.2彻头彻尾理解 LinkedHashMap
- 2.3 彻头彻尾理解 ConcurrentHashMap
- 2.4 彻头彻尾理解 HashTable
- 3. java面试锦集
- 4. String
- 1.String
- 2.StringBuilder
- 3. StringBuffer
- 4. 总结
- 5. 泛型
- 6.注解
- 7.java io
- 7.1 File
- 7.2 字节流字符流
- 7.3 Pushback流
- 7.4 RandomAccessFile
- 7.5 序列化
- a.序列化算法
- b.反序列化创建对象
- c.自定义序列化
- d.注意事项
- 8 线程
- 8.1 创建线程的三种方式
- 8.2 Daemon线程
- 8.3 interrupt的理解
- 8.4 synchronized volatile
- 8.5 wait notify
- 4. Lock
- 5. 并发容器
- 6. 偏向锁,轻量锁,重量级锁
- 7 内存屏障
- 8 可重入锁解析 ReentrantLock
- 1.加锁过程
- 2.解锁过程
- 9 final
- 10 深拷贝VS浅拷贝
1. java集合深入理解
https://blog.csdn.net/u011240877/article/category/6447444
http://www.cnblogs.com/skywang12345/p/3323085.html
1.1 迭代器的快速失败机制 fast-fail
https://blog.csdn.net/chewbee/article/details/78314661
1. 是java集合的一种错误检测机制
2. 防止一个线程在对集合进行迭代时候,另一个线程在结构上
对集合进行修改,不是单纯的修改集合元素值
1.2 collection 集合
https://blog.csdn.net/justloveyou_/article/details/52948661
1.3 List集合
https://blog.csdn.net/justloveyou_/article/details/52955619
1.3.1 ArrayList
a. 内部数据结构
private transient Object[] elementData; // 瞬时域private int size;
b. 扩容操作 这是一个public
函数,默认每次扩容是 1.5倍 + 1
// 调整数组容量public void ensureCapacity(int minCapacity) {modCount++;int oldCapacity = elementData.length;if (minCapacity > oldCapacity) {Object oldData[] = elementData;int newCapacity = (oldCapacity * 3)/2 + 1;if (newCapacity < minCapacity)newCapacity = minCapacity;// minCapacity is usually close to size, so this is a win:// 最终会调用 System.ArrayCopy() 这是一个内存块拷贝函数elementData = Arrays.copyOf(elementData, newCapacity);}}
c. 序列化 虽然内部数据结构一个是瞬态数据和一个基本数据类型 ,但是通过自定义的readObject()/writeObject()
private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{// Write out element count, and any hidden stuffint expectedModCount = modCount;s.defaultWriteObject();// Write out size as capacity for behavioural compatibility with clone()s.writeInt(size);// Write out all elements in the proper order.for (int i=0; i<size; i++) {s.writeObject(elementData[i]);}if (modCount != expectedModCount) {throw new ConcurrentModificationException();}}private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {elementData = EMPTY_ELEMENTDATA;// Read in size, and any hidden stuffs.defaultReadObject();// Read in capacitys.readInt(); // ignoredif (size > 0) {// be like clone(), allocate array based upon size not capacityint capacity = calculateCapacity(elementData, size);SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);ensureCapacityInternal(size);Object[] a = elementData;// Read in all elements in the proper order.for (int i=0; i<size; i++) {a[i] = s.readObject();}}}
d. ArrayList 允许值为null
// 移除此列表中 “首次” 出现的指定元素(如果存在)。这是因为 ArrayList 中允许存放重复的元素。 public boolean remove(Object o) { // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。 if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { // 类似remove(int index),移除列表中指定位置上的元素。 fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }
}
1.3.2 LinkList
a. 头结点不存放任何数据
b. 新增元素放在链表尾部
c. 只能遍历访问,不能随机访问
2. Map 综述
https://blog.csdn.net/justloveyou_/
2.1 彻头彻尾理解 HashMap
https://blog.csdn.net/justloveyou_/article/details/62893086
初始容量: 桶的数量
负载因子: 扩容阈值=负载因子 * 初始容量
- 有两个重要的数据: 容量(默认是16),负载因子(默认是0.75)
- 使用
数组链表
的结构来存储 - put操作
- get操作
- resize扩容操作 多线程的情况下出现
死循环
- 非线程安全的
迭代器的快速失败机制
fast-fail机制
在使用迭代器遍历Hashmap的过程中,别的线程不允许修改hashmap,要不然就会出现快速失败,内部是通过modCount计算器来实现的.
多线程并发HashMap,写操作导致扩容
- 内部的链表产生死循环 cpu100%
- 获取null
- 元素丢失
https://www.cnblogs.com/dongguacai/p/5599100.html
https://blog.csdn.net/u013668852/article/details/77141842
/*** Associates the specified value with the specified key in this map.* If the map previously contained a mapping for the key, the old* value is replaced.** @param key key with which the specified value is to be associated* @param value value to be associated with the specified key* @return the previous value associated with key, or null if there was no mapping for key.* Note that a null return can also indicate that the map previously associated null with key.*/public V put(K key, V value) {//当key为null时,调用putForNullKey方法,并将该键值对保存到table的第一个位置 if (key == null)return putForNullKey(value); //根据key的hashCode计算hash值int hash = hash(key.hashCode()); // ------- (1)//计算该键值对在数组中的存储位置(哪个桶)int i = indexFor(hash, table.length); // ------- (2)//在table的第i个桶上进行迭代,寻找 key 保存的位置for (Entry<K,V> e = table[i]; e != null; e = e.next) { // ------- (3)Object k;//判断该条链上是否存在hash值相同且key值相等的映射,若存在,则直接覆盖 value,并返回旧valueif (e.hash == hash && ((k = e.key) == key || key.equals(k))) {V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue; // 返回旧值}}modCount++; //修改次数增加1,快速失败机制//原HashMap中无该映射,将该添加至该链的链头addEntry(hash, key, value, i); return null;}
2.2彻头彻尾理解 LinkedHashMap
https://blog.csdn.net/justloveyou_/article/details/71713781
0. 增加属性: 链表头节点header , 标志位accessOrder,默认是保持插入顺序
1. 在HashMap的基础上增加双向链表
2. 默认是保持插入顺序
3. LUR算法(最近最少使用)
1. HashMap与LinkHashMap 的get/set方法会访问accessOrder() ,但是HashMap的accessOrder()是空操作
2. LinkHashMap的accessOrder(),如果对应的accessOrder设置为true recordAccess()函数在访问内部节点的时候就会把访问节点放到队列的尾部,并删除当前节点
新增节点
/*** This override alters behavior of superclass put method. It causes newly* allocated entry to get inserted at the end of the linked list and* removes the eldest entry if appropriate.** LinkedHashMap中的addEntry方法*/void addEntry(int hash, K key, V value, int bucketIndex) { //创建新的Entry,并插入到LinkedHashMap中 createEntry(hash, key, value, bucketIndex); // 重写了HashMap中的createEntry方法//双向链表的第一个有效节点(header后的那个节点)为最近最少使用的节点,这是用来支持LRU算法的Entry<K,V> eldest = header.after; //如果有必要,则删除掉该近期最少使用的节点, //这要看对removeEldestEntry的覆写,由于默认为false,因此默认是不做任何处理的。 if (removeEldestEntry(eldest)) { removeEntryForKey(eldest.key); } else { //扩容到原来的2倍 if (size >= threshold) resize(2 * table.length); } } void createEntry(int hash, K key, V value, int bucketIndex) { // 向哈希表中插入Entry,这点与HashMap中相同 //创建新的Entry并将其链入到数组对应桶的链表的头结点处, HashMap.Entry<K,V> old = table[bucketIndex]; Entry<K,V> e = new Entry<K,V>(hash, key, value, old); table[bucketIndex] = e; //在每次向哈希表插入Entry的同时,都会将其插入到双向链表的尾部, //这样就按照Entry插入LinkedHashMap的先后顺序来迭代元素(LinkedHashMap根据双向链表重写了迭代器)//同时,新put进来的Entry是最近访问的Entry,把其放在链表末尾 ,也符合LRU算法的实现 e.addBefore(header); size++; }
recordAccess()
HashMap是一个空函数,LinkHashMap如下所示:
void recordAccess(HashMap<K,V> m) { LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; //如果链表中元素按照访问顺序排序,则将当前访问的Entry移到双向循环链表的尾部, //如果是按照插入的先后顺序排序,则不做任何事情。 if (lm.accessOrder) { lm.modCount++; //移除当前访问的Entry remove(); //将当前访问的Entry插入到链表的尾部 addBefore(lm.header); } }
- 使用LinkHashMap实现LRU算法
public class LRU<K,V> extends LinkedHashMap<K, V> {private static final long serialVersionUID = 1L;public LRU(int initialCapacity,float loadFactor, boolean accessOrder) {super(initialCapacity, loadFactor, accessOrder);}/* LinkHashMap中的实现就是单纯的返回一个false,也就是不删除节点protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {return false;}
*/@Overrideprotected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {// TODO Auto-generated method stubif(size() > 6){return true;}return false;}public static void main(String[] args) {LRU<Character, Integer> lru = new LRU<Character, Integer>(16, 0.75f, true);String s = "abcdefghijkl";for (int i = 0; i < s.length(); i++) {lru.put(s.charAt(i), i);}System.out.println("LRU中key为h的Entry的值为: " + lru.get('h'));System.out.println("LRU的大小 :" + lru.size());System.out.println("LRU :" + lru);}
}
2.3 彻头彻尾理解 ConcurrentHashMap
https://blog.csdn.net/justloveyou_/article/details/72783008
a. segment继承ReentrantLock ,使得对象具备了锁的功能
b. 初始容量,负载因子,并发级别 三个重要参数 . 默认值分别为16 , 0.75 , 16
构造函数 : 根据初始容量,并发级别,确定 多少各segment 以及每个segment多少个桶
public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) {if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)throw new IllegalArgumentException();if (concurrencyLevel > MAX_SEGMENTS) concurrencyLevel = MAX_SEGMENTS;// Find power-of-two sizes best matching argumentsint sshift = 0; // 大小为 lg(ssize) int ssize = 1; // 段的数目,segments数组的大小(2的幂次方)// 并发级别可能不是2的幂次方 ,转换一下// 假设并发级别是5,那么就会分为8段while (ssize < concurrencyLevel) {++sshift; ssize <<= 1;}segmentShift = 32 - sshift; // 用于定位段segmentMask = ssize - 1; // 用于定位段// this.segments = Segment.newArray(ssize); // 创建segments数组if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;int c = initialCapacity / ssize; // 总的桶数/总的段数 = 平均每个段中的桶数目 ,但是不是 2 幂次方if (c * ssize < initialCapacity)++c;int cap = 1; // 每个段所拥有的桶的数目(2的幂次方)while (cap < c)cap <<= 1;for (int i = 0; i < this.segments.length; ++i) // 初始化segments数组this.segments[i] = new Segment<K,V>(cap, loadFactor);}
c. put操作
d. get操作
// Segment 类V get(Object key, int hash) {if (count != 0) { // read-volatile,首先读 count 变量HashEntry<K,V> e = getFirst(hash); // 获取桶中链表头结点while (e != null) {if (e.hash == hash && key.equals(e.key)) { // 查找链中是否存在指定Key的键值对V v = e.value;if (v != null) // 如果读到value域不为 null,直接返回return v; // 如果读到value域为null,说明发生了重排序,加锁后重新读取return readValueUnderLock(e); // recheck}e = e.next;}}return null; // 如果不存在,直接返回null
}
e. rehash操作
f. size() 统计大小操作
- 不加锁重试2次,每次去统计segment中的数量的时候,计入modCount的大小, 所有的段统计完成,去比较一下每个段中的modCount是否产生变化
- 如果产生变化,那么就对所有的段加锁,再次统计一下
g. 与JDK1.8实现的ConcurrentHashMap对比
https://blog.csdn.net/fouy_yun/article/details/77816587
1. 取消了分段
2. 链表长度默认超过8 ,变成红黑树
put操作 部分添加操作加锁
1. 若table[]未创建,则初始化。 2. 当table[i]后面无节点时,直接创建Node(无锁操作)。 cas原子操作 3. 如果当前正在扩容,则帮助扩容并返回最新table[]。 4. 然后在链表或者红黑树中追加节点。 锁住当前table[i] 5. 最后还回去判断是否到达阀值,如到达变为红黑树结构。
get操作 整个过程都没有加锁
1. 首先定位到table[]中的i。 2. 若table[i]存在,则继续查找。 3. 首先比较链表头部,如果是则返回。 4. 然后如果为红黑树,查找树。 5. 最后再循环链表查找。
2.4 彻头彻尾理解 HashTable
https://blog.csdn.net/justloveyou_/article/details/72862373
- Hashtable不同于HashMap,前者既不允许key为null,也不允许value为null;
- HashMap中用于定位桶位的Key的hash的计算过程要比Hashtable复杂一点,没有Hashtable如此简单、直接;
- 在HashMap的插入K/V对的过程中,总是先插入后检查是否需要扩容;而Hashtable则是先检查是否需要扩容后插入;
- Hashtable不同于HashMap,前者的put操作是线程安全的
put操作 :
- 方法同步
- 不允许空value
- 没有对key做出null处理,暗示key不能为null
- 计算桶的位置使用的是取模运算,也不是HashMap的&运算,也就是说HashTable的初始容量没有什么要求
- 先判断是否需要扩容,再插入节点
public synchronized V put(K key, V value) { // 加锁同步,保证Hashtable的线程安全性// Make sure the value is not nullif (value == null) { // 不同于HashMap,Hashtable不允许空的valuethrow new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry tab[] = table;int hash = key.hashCode(); // key 的哈希值,同时也暗示Hashtable不同于HashMap,其不允许空的keyint index = (hash & 0x7FFFFFFF) % tab.length; // 取余计算节点存放桶位,0x7FFFFFFF 是最大的int型数的二进制表示// 先查找Hashtable上述桶位中是否包含具有相同Key的K/V对for (Entry<K, V> e = tab[index]; e != null; e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {V old = e.value;e.value = value;return old;}}// 向Hashtable中插入目标K/V对modCount++; // 发生结构性改变,modCount加1if (count >= threshold) { //在插入目标K/V对前,先检查是否需要扩容(不同于HashMap的插入后检查是否需要扩容) // Rehash the table if the threshold is exceededrehash();tab = table;index = (hash & 0x7FFFFFFF) % tab.length; // 扩容后,重新计算K/V对插入的桶位}// Creates the new entry.Entry<K, V> e = tab[index];tab[index] = new Entry<K, V>(hash, key, value, e); // 将K/V对链入对应桶中链表,并成为头结点count++; // Hashtable中Entry数目加1return null;}
get操作
- 同步方法
- 取模的方式定位桶位置
- 在链表中查找指定的key ,没找到返回null
public synchronized V get(Object key) { // 不同于HashMap,Hashtable的读取操作是同步的Entry tab[] = table;int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; // 定位K/V对的桶位for (Entry<K, V> e = tab[index]; e != null; e = e.next) { // 在特定桶中依次查找指定Key的K/V对if ((e.hash == hash) && e.key.equals(key)) {return e.value; }}return null; // 查找失败}
3. java面试锦集
https://blog.csdn.net/justloveyou_/article/details/78653660
https://blog.csdn.net/justloveyou_/article/details/78653929
https://blog.csdn.net/justloveyou_/article/details/78313167
4. String
https://blog.csdn.net/justloveyou_/article/details/52556427
https://blog.csdn.net/justloveyou_/article/details/60983034
1.String
对String的一般认识
- 类使用了final修饰,不能被继承
- 内部字段也被final修饰,初始化就不能再次修改
- String是一个不可变类,线程安全
- 内部使用的是char[]来表示
编译期间就会把字面字符串放到字符串常量池 字符串拼接操作
- 字符串字面量拼接,标量替换
- 字符串引用拼接 ,还是会调用StringBuilder.append toString返回一个String对象
引用拼接的本质:
String s4 = s1 + s2 + s3;
====>
String s4 = (new StringBuilder(String.valueOf(s1))).append(s2).append(s3).toString();
2.StringBuilder
- 不是线程安全的类
- 是单线程下替换StringBuffer的一个类
3. StringBuffer
- 是一个线程安全的类
4. 总结
- 使用字面值形式创建字符串时,不一定会创建对象,但其引用一定指向位于字符串常量池的某个对象;
- 使用 new String(“…”)方式创建字符串时,一定会创建对象,甚至可能会同时创建两个对象(一个位于字符串常量池中,一个位于堆中);
- String 对象是不可变的,对String 对象的任何改变都会导致一个新的 String 对象的产生,而不会影响到原String 对象;
- StringBuilder 与 StringBuffer 具有共同的父类,具有相同的API,分别适用于单线程和多线程环境下。特别地,在单线程环境下,StringBuilder 是 StringBuffer 的替代品,前者效率相对较高;
5. 泛型
https://blog.csdn.net/s10461/article/details/53941091
泛型遇上多态
https://blog.csdn.net/lonelyroamer/article/details/7868820
6.注解
https://blog.csdn.net/briblue/article/details/73824058
https://www.cnblogs.com/Qian123/p/5256084.html
7.java io
7.1 File
7.2 字节流字符流
7.3 Pushback流
7.4 RandomAccessFile
7.5 序列化
自定义readObject函数的调用过程
https://blog.csdn.net/xiaoanian/article/details/9064635
https://www.cnblogs.com/yoohot/p/6019767.html
a.序列化算法
- 所有的对象都有一个序列化编号
- 检查对象是否已经被序列化
- 如果已经序列化,那么只输出序列化编号
note: 注意可变对象的序列化
b.反序列化创建对象
- 获取反序列化对象的元数据(Class文件) ——> 该类还没有被加载,那就执行类加载机制
- 在内存中创建内存空间
- 直接内存赋值
- 不需要调用构造函数
c.自定义序列化
- 实现
Serializable
接口,该接口就是一个标记,内部没有任何东西 - 实现
Externalizable
接口
d.注意事项
- 父类实现了序列化,子类自动实现序列化
- 基类没有实现序列化
- 如果 存在无参构造函数,那么序列化过程中不会报错,但是不会保存实例变量值
- 如果不存在无参构造函数,那么序列化过程中直接报错
- transient修饰的变量不参与序列化,类变量也不参与序列化
8 线程
8.1 创建线程的三种方式
- 继承Thread
- 实现Runnable接口
- 实现Callable接口
8.2 Daemon线程
- 需要在线程启动之前设置为后台线程,否则线程启动之后,线程状态是Runnable,而在setDaemon函数中会判断线程状态是不是new状态,不是就报错了
- 所有的前台线程退出了,那么后台线程也就退出了
- Daemon线程中再次创建线程也是Daemon线程
8.3 interrupt的理解
https://www.ibm.com/developerworks/cn/java/j-jtp05236.html
https://www.cnblogs.com/timlearn/p/4008783.html
1. java中断是一种协调机制
2. 线程对象调用interrupt函数向线程发送一个中断信号
3. 在线程内部,如果线程处于阻塞,那么就会抛出InterruptException异常;如果处于运行状态,那么就会设置一下该线程的中断状态为真
4. isInterrupted()函数返回线程现在是不是中断状态,但是不会影响中断状态
5. interrupted()静态函数,会重置中断状态
8.4 synchronized volatile
- volatile
- 保证各线程的可见性,但是不保证原子性.线程的工作内存马上同步到主内存中
- 禁止指令重排序
- 轻量级锁
https://www.cnblogs.com/wq3435/p/6220751.html
https://blog.csdn.net/justloveyou_/article/details/53672005
- synchronized可以保证
8.5 wait notify
https://www.cnblogs.com/hapjin/p/5492645.html
线程状态转移
https://blog.csdn.net/pange1991/article/details/53860651
问题1
: 为什么会假唤醒?
问题2
: 为什么需要需要同步?
synchronized(object){// 使用while防止假唤醒while(条件不满足){object.wait();}//逻辑处理;
}synchronized(object){//改变条件object.notifyAll();
}
- 对象的wait notify方法必须在同步快内部,也就是说需要获取对象锁才可以调用执行
- notify()执行,
出了同步快,那么就会唤醒该对象等待队列上的线程,进入同步队列
- wait()执行,
放弃cpu资源,释放锁,线程放进等待队列中,等待唤醒
4. Lock
5. 并发容器
6. 偏向锁,轻量锁,重量级锁
7 内存屏障
http://ifeve.com/disruptor-memory-barrier/
8 可重入锁解析 ReentrantLock
http://www.cnblogs.com/xrq730/p/4979021.html
https://blog.csdn.net/lsgqjh/article/details/63685058
1.加锁过程
final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) { //如果没有线程获取锁,则当前线程CAS获取锁。并设置自己为当前锁的独占线程if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {// 如果存在锁竞争,判断获取锁的线程是否是当前线程, 如果是 那么根据可重入的含义, 使当前state+1;int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}如果不是当前线程,则不能获取同步状态return false; }
- 获取volatile修饰的state值
- 如果state的值为0,说明还没有线程持有锁
- 使用CAS操作设置state的值
- 设置当前线程持有锁
state不为0,说明当前有线程持有该锁,那么判断是不是当前线程想重入
- 如果是,重新设置state的值
- 如果不是,获取锁失败
2.解锁过程
protected final boolean tryRelease(int releases) {int c = getState() - releases;// 只有获得锁的线程自己才能释放锁if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {//c==0说明已经无锁free = true;setExclusiveOwnerThread(null);}setState(c);//否则更新state为state-1, 也就是加锁多少次,就得释放多少次, lock unlock配对使用。return free;}
- 当前线程不持有锁,解锁异常抛出
- 获取state值
- 如果state的值为0了,那么说明解锁完就没有那个对象持有该锁了,需要设置锁没有持有任何线程
- 重新设置state
9 final
https://www.cnblogs.com/senlinyang/p/7875468.html
1. 写final域的重排序规则:禁止把final域的写重排序到构造函数之外——>对象的引用在任意线程可见之前,final域一定是已经正确初始化过的
通过下面2种方式保证
a. JMM禁止编译器把final域写重排序到构造函数之外
b. 编译器会在final域的写之后,构造函数return之前,插入一个StoreStore内存屏障
2. 读final域的重排序规则: 初次读对象引用和初次读对象包含的final域两个操作之间禁止重排序,编译器会在两个操作之间插入LoadLoad内存屏障——–>在读一个对象的final域之前,一定会先读取包含这个final域的对象的引用
3. final域是一个引用类型,final域对象内部成员的初始化和使用对象之间禁止重排序
final域可以给我们一下保证: 只要对象正确的构造,那么不需要同步,任意线程都可以看到final域在构造函数中初始化值
10 深拷贝VS浅拷贝
java 学习资料总结相关推荐
- JAVA学习资料整理
今天偶然间发现之前一个群里发过的一篇关于JAVA学习资料的东西.本着服务大众的精神,搬来了博客园: <JAVA编程思想>第四版(英文原版) 下载地址:http://115.com/file ...
- 不得不知道的一些Java学习资料
Java学习资料 下面是我们花费大量精力整理出来的 Java 学习资料,这套 Java 学习资料由 Java 书籍和 Java 视频两大部分组成,我们会根据 Java 学习路线,按照由浅至深的顺序进行 ...
- 2020最新java学习资料,全套源码无加密网盘下载
点击上方蓝字关注我们! 前言--------2020最新java学习资料完整版,全套源码无加密网盘下载 最近小编整理了三套java的学习资料(视频+资料+源码),无加密: 1.2020java会员版 ...
- Java学习资料汇总(JavaSE+JavaEE+数据库+框架+笔试题+面试题)
在写下这篇文章的时候,我还在找工作.理解每一个真正对编程感兴趣的小伙伴的转行不易,于是就把自己这几个月搜索到的学习资料一一分享给大家. 3.数据库 MySQL5.7 Reference Manual ...
- [Java学习资料] [成长之路]
[背景] 网上学习资料千千万万,成长之路千千万万,各取所需 JAVA基础 网站 https://www.runoob.com/java/java-tutorial.html https://www.w ...
- 优秀java学习资料大全
http://www-900.ibm.com/developerWorks/cn/java/index.shtml IBM的JAVA专题--永远的蓝色巨人 http://www.huihoo. ...
- 分享优秀java学习资料大全
http://www-900.ibm.com/developerWorks/cn/java/index.shtml IBM的JAVA专题--永远的蓝色巨人 http://www.huihoo.c ...
- 初学java 学习资料整理
前言 学习java已经有四天时间了,目前学习完了包括基础语法.面向对象.异常处理等java基础,但是在熟练程度以及工具使用方面都还需要继续加强.java的生态果然明显更好,高质量的学习资料也确实不少. ...
- Java学习资料汇总(吐血分享)----持续更新中
java学习攻略: 1.javase html css javascript 历经5年锤炼(史上最适合初学者入门的Java基础视频) Java基础教程(java入门学习第一免费视频下载) Jav ...
- 最新Java学习资料与思维导图分享,免费领取!
很多学 Java 的同学时常会发现,在校时学了一套东西,到大公司面试时又是另一套东西. 其实,归根结底,还是本人缺少真正的实战经验,这里整理了一份系统化学习的思维导图(完整版文末领取),大家查漏补缺, ...
最新文章
- 皮一皮:这是为什么呢???
- 浅谈中大型企业CMDB的建设
- Linux 下的tar常用命令及操作
- Existing lock /var/run/yum.pid: another copy is running as pid
- java中抽象类与接口的不同之处
- switch case的天坑
- 反直觉的一个游戏 - 三门问题 (Monty Hall problem)
- 问题 1125: 【C语言训练】委派任务*【最优解】
- 打印所有的水仙花数---初学c语言
- 微信小程序纯前端生成海报并保存本地
- 第三方应用调用高德地图
- 1Mbps带宽到底能够达到什么效果,看看下面的介绍就懂了。
- 昂达v80 plus linux,昂达(ONDA)V80 Plus平板电脑整体性能评测-ZOL中关村在线
- 杂-格签名中常见数字的意义
- Minecraft 1.18.1、1.18.2模组开发 17.自定义盾牌(shield)
- js插件动态加载js、css解决方案
- 蚂蚁金服原副总裁漆远加盟复旦大学,任人工智能院长
- 你应该考这些证书,特别是在校生
- 小米3基于android,小米手机3评测 最大最快的小米3详细评测图文介绍
- AFW短信防火墙 v1.0 beta 发布
热门文章
- 《电子元器件的可靠性》——3.3节可靠性筛选试验
- docker安装网易云音乐(yesplaymusic)
- dcs world f15c教学_烟台TSXP57353M【四点零自动化】DCS系统
- SetTimer函数
- java实现医嘱管理系统_Chis5.0医嘱管理系统业务使用手册
- 华为顶级黑客整理的399本编程电子书,整整16个G,你想学的都有
- 一周新闻纵览:谷歌浏览器信息泄露,出卖个人信息获利终落网,严查App偷窥乱象
- java 语言的介绍
- DVB 数字电视基础知识
- OGG-01433 Oracle GoldenGate Capture for Oracle, EXXX.prm: Failed to validate table <SCHEMANAME.TABLE