死磕JDK源码之LinkedList

LinkedList

LinkedList底层是基于双向链表实现的

内置插入删除方法

linkFirst & linkLast

unlinkFirst & unlinkLast

linkBefore

unlink

源码分析

  1 package java.util;
  2 import java.util.function.Consumer;
  3 public class LinkedList<E> extends AbstractSequentialList<E> implements
  4         List<E>, Deque<E>, Cloneable, java.io.Serializable {
  5     //元素个数
  6     transient int size = 0;
  7     //第一个节点
  8     transient Node<E> first;
  9     //最后一个节点
 10     transient Node<E> last;
 11     //默认构造方法
 12     public LinkedList() {
 13     }
 14     //构造一个包含指定c元素的列表(元素按c迭代器返回的顺序排列)
 15     public LinkedList(Collection<? extends E> c) {
 16         this();
 17         addAll(c);
 18     }
 19     //把节点e置为头节点
 20     private void linkFirst(E e) {
 21         //1.得到第一个节点引用的拷贝
 22         final Node<E> f = first;
 23         //2.把e的后继节点置为f(添加e之前的第一个节点)
 24         final Node<E> newNode = new Node<>(null, e, f);
 25         //3.把e置为first
 26         first = newNode;
 27         //4.如果f为空节点,就把e也置为last,否则把f的前驱节点置为e
 28         if (f == null)
 29             last = newNode;
 30         else
 31             f.prev = newNode;
 32         //5.size modCount+1
 33         size++;
 34         modCount++;
 35     }
 36     //把节点e置为尾节点
 37     void linkLast(E e) {
 38         final Node<E> l = last;
 39         //1.把e的前驱节点置为l(添加e之前的最后一个节点)
 40         final Node<E> newNode = new Node<>(l, e, null);
 41         //2.把e置为last
 42         last = newNode;
 43         //3.如果l为空节点,就把e也置为first,否则把l的后继节点置为e
 44         if (l == null)
 45             first = newNode;
 46         else
 47             l.next = newNode;
 48         size++;
 49         modCount++;
 50     }
 51     //把e放到节点succ之前
 52     void linkBefore(E e, Node<E> succ) {
 53         //1.记录节点succ的前驱节点为pred
 54         final Node<E> pred = succ.prev;
 55         //2.把节点e插入succ之前
 56         final Node<E> newNode = new Node<>(pred, e, succ);
 57         //3.把节点succ的前驱节点置为e
 58         succ.prev = newNode;
 59         //4.如果pred为空节点,就把e也置为first,否则把pred的后继节点置为e
 60         if (pred == null)
 61             first = newNode;
 62         else
 63             pred.next = newNode;
 64         size++;
 65         modCount++;
 66     }
 67     //移除头节点f
 68     private E unlinkFirst(Node<E> f) {
 69         //1.f为第一个节点且f不为空,element为f存放的值
 70         final E element = f.item;
 71         //2.得到f的下一个节点的一个引用(在f.next置为null之前拷贝一份)
 72         final Node<E> next = f.next;
 73         //3.把f存放的值和next域置为null
 74         f.item = null;
 75         f.next = null;
 76         //4.把next引用置为first
 77         first = next;
 78         //5.如果next为空,说明没有元素了,那么把last也置为空
 79         if (next == null)
 80             last = null;
 81         //否则把next的前驱引用置为null
 82         else
 83             next.prev = null;
 84         //6.size-1 modCount+1
 85         size--;
 86         modCount++;
 87         //7.返回被移除的头节点的值
 88         return element;
 89     }
 90     //移除尾节点l
 91     private E unlinkLast(Node<E> l) {
 92         //得到尾节点存放的值
 93         final E element = l.item;
 94         //得到尾节点的前一个节点的引用的一份拷贝
 95         final Node<E> prev = l.prev;
 96         //把尾节点的值置为null
 97         l.item = null;
 98         //把尾节点的前驱引用置为null
 99         l.prev = null;
100         //把prev引用置为last
101         last = prev;
102         //如果prev为空,说明没有元素了,那么把first也置为空
103         if (prev == null)
104             first = null;
105         //否则把prev的后继引用置为null
106         else
107             prev.next = null;
108         size--;
109         modCount++;
110         //返回被移除尾节点的值
111         return element;
112     }
113     //移除x节点,x不为null
114     E unlink(Node<E> x) {
115         //1.得到节点x存放的值
116         final E element = x.item;
117         //2.得到x后继节点引用的一份拷贝
118         final Node<E> next = x.next;
119         //3.得到x前驱节点引用的一份拷贝
120         final Node<E> prev = x.prev;
121         //如果prev为空,即节点x为第一个节点
122         if (prev == null) {
123             first = next;
124         //4.prev不为空,把x前驱节点的next指向x的后继节点
125         } else {
126             prev.next = next;
127             x.prev = null;
128         }
129         //如果next为空,即节点x为最后一个元素
130         if (next == null) {
131             last = prev;
132         //5.next不为空,把x后继节点的prev指向x的前驱节点
133         } else {
134             next.prev = prev;
135             x.next = null;
136         }
137         //6.把x存放的值置为null
138         x.item = null;
139         //7.size-1 modCount+1
140         size--;
141         modCount++;
142         //8.返回被移除节点x的值
143         return element;
144     }
145     //返回列表第一个节点的值
146     public E getFirst() {
147         final Node<E> f = first;
148         if (f == null)
149             throw new NoSuchElementException();
150         return f.item;
151     }
152     //返回列表最后一个节点的值
153     public E getLast() {
154         final Node<E> l = last;
155         if (l == null)
156             throw new NoSuchElementException();
157         return l.item;
158     }
159     //移除头节点并返回其值
160     public E removeFirst() {
161         final Node<E> f = first;
162         if (f == null)
163             throw new NoSuchElementException();
164         return unlinkFirst(f);
165     }
166     //移除尾节点并返回其值
167     public E removeLast() {
168         final Node<E> l = last;
169         if (l == null)
170             throw new NoSuchElementException();
171         return unlinkLast(l);
172     }
173     //把节点e置为头节点
174     public void addFirst(E e) {
175         linkFirst(e);
176     }
177     //把节点e置为尾节点
178     public void addLast(E e) {
179         linkLast(e);
180     }
181     //判断列表是否包含元素o
182     public boolean contains(Object o) {
183         return indexOf(o) != -1;
184     }
185     //返回元素个数
186     public int size() {
187         return size;
188     }
189     //把节点e添加至列表尾部,添加完成返回true
190     public boolean add(E e) {
191         linkLast(e);
192         return true;
193     }
194     //移除列表中第一次出现的指定元素o,移除完成返回true
195     public boolean remove(Object o) {
196         if (o == null) {
197             for (Node<E> x = first; x != null; x = x.next) {
198                 if (x.item == null) {
199                     unlink(x);
200                     return true;
201                 }
202             }
203         } else {
204             for (Node<E> x = first; x != null; x = x.next) {
205                 if (o.equals(x.item)) {
206                     unlink(x);
207                     return true;
208                 }
209             }
210         }
211         return false;
212     }
213     //添加集合c中的所有元素至列表尾部(按c中迭代器的顺序)
214     public boolean addAll(Collection<? extends E> c) {
215         return addAll(size, c);
216     }
217     //把集合c中的所有元素插入index处
218     public boolean addAll(int index, Collection<? extends E> c) {
219         //1.索引检查
220         checkPositionIndex(index);
221         //2.把带插入的集合转为数组a,如果a的长度为0,直接返回false
222         Object[] a = c.toArray();
223         int numNew = a.length;
224         if (numNew == 0)
225             return false;
226         //3.succ为索引为index的节点,pred为索引为index-1的节点
227         Node<E> pred, succ;
228         //4.如果index为size,那么succ为null,pred为last节点
229         if (index == size) {
230             succ = null;
231             pred = last;
232         } else {
233             succ = node(index);
234             pred = succ.prev;
235         }
236         for (Object o : a) {
237             @SuppressWarnings("unchecked") E e = (E) o;
238             //5.建立e节点的pred引用
239             Node<E> newNode = new Node<>(pred, e, null);
240             //6.如果index=0,即pred为空节点就把first置为e
241             if (pred == null)
242                 first = newNode;
243             //否则把pred的next引用置为e
244             else
245                 pred.next = newNode;
246             pred = newNode;
247         }
248         //7.如果index处为空,就把集合c中的最后一个元素置为last
249         if (succ == null) {
250             last = pred;
251         //否则建立集合c中最后一个元素的next引用为succ,succ的prev引用为pred
252         } else {
253             pred.next = succ;
254             succ.prev = pred;
255         }
256         //8.更新size和modCount
257         size += numNew;
258         modCount++;
259         return true;
260     }
261     //移除所有元素
262     public void clear() {
263         for (Node<E> x = first; x != null;) {
264             Node<E> next = x.next;
265             x.item = null;
266             x.next = null;
267             x.prev = null;
268             x = next;
269         }
270         first = last = null;
271         size = 0;
272         modCount++;
273     }
274     //返回指定位置的元素
275     public E get(int index) {
276         checkElementIndex(index);
277         return node(index).item;
278     }
279     //替换指定index的元素为指定element,并返回被替换的值
280     public E set(int index, E element) {
281         checkElementIndex(index);
282         Node<E> x = node(index);
283         E oldVal = x.item;
284         x.item = element;
285         return oldVal;
286     }
287     //把element插入指定index处
288     public void add(int index, E element) {
289         checkPositionIndex(index);
290         if (index == size)
291             linkLast(element);
292         else
293             linkBefore(element, node(index));
294     }
295     //移除指定位置的元素
296     public E remove(int index) {
297         checkElementIndex(index);
298         return unlink(node(index));
299     }
300     //检查index是否越界
301     private boolean isElementIndex(int index) {
302         return index >= 0 && index < size;
303     }
304     //检查index是否越界
305     private boolean isPositionIndex(int index) {
306         return index >= 0 && index <= size;
307     }
308     //索引越界错误处理
309     private String outOfBoundsMsg(int index) {
310         return "Index: " + index + ", Size: " + size;
311     }
312     //索引检查
313     private void checkElementIndex(int index) {
314         if (!isElementIndex(index))
315             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
316     }
317     //索引检查
318     private void checkPositionIndex(int index) {
319         if (!isPositionIndex(index))
320             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
321     }
322     //返回index处的节点
323     Node<E> node(int index) {
324         //index在前半部分从前向后遍历
325         if (index < (size >> 1)) {
326             Node<E> x = first;
327             for (int i = 0; i < index; i++)
328                 x = x.next;
329             return x;
330         //否则从后向前遍历
331         } else {
332             Node<E> x = last;
333             for (int i = size - 1; i > index; i--)
334                 x = x.prev;
335             return x;
336         }
337     }
338     //返回列表中第一次出现指定元素o的索引,不存在返回-1
339     public int indexOf(Object o) {
340         int index = 0;
341         if (o == null) {
342             for (Node<E> x = first; x != null; x = x.next) {
343                 if (x.item == null)
344                     return index;
345                 index++;
346             }
347         } else {
348             for (Node<E> x = first; x != null; x = x.next) {
349                 if (o.equals(x.item))
350                     return index;
351                 index++;
352             }
353         }
354         return -1;
355     }
356     //返回列表中最后一次出现指定元素o的索引,不存在返回-1
357     public int lastIndexOf(Object o) {
358         int index = size;
359         if (o == null) {
360             for (Node<E> x = last; x != null; x = x.prev) {
361                 index--;
362                 if (x.item == null)
363                     return index;
364             }
365         } else {
366             for (Node<E> x = last; x != null; x = x.prev) {
367                 index--;
368                 if (o.equals(x.item))
369                     return index;
370             }
371         }
372         return -1;
373     }
374     //获取但不移除头节点的值
375     public E peek() {
376         final Node<E> f = first;
377         return (f == null) ? null : f.item;
378     }
379     //获取但不移除头节点
380     public E element() {
381         return getFirst();
382     }
383     //获取并移除头节点
384     public E poll() {
385         final Node<E> f = first;
386         return (f == null) ? null : unlinkFirst(f);
387     }
388     //移除头节点并返回其值
389     public E remove() {
390         return removeFirst();
391     }
392     //把节点e添加至末尾
393     public boolean offer(E e) {
394         return add(e);
395     }
396     //把节点e添加至开头
397     public boolean offerFirst(E e) {
398         addFirst(e);
399         return true;
400     }
401     //把节点e添加至末尾
402     public boolean offerLast(E e) {
403         addLast(e);
404         return true;
405     }
406     //获取但不移除头节点的值
407     public E peekFirst() {
408         final Node<E> f = first;
409         return (f == null) ? null : f.item;
410     }
411     //获取但不移除尾节点的值
412     public E peekLast() {
413         final Node<E> l = last;
414         return (l == null) ? null : l.item;
415     }
416     //获取并移除头节点的值
417     public E pollFirst() {
418         final Node<E> f = first;
419         return (f == null) ? null : unlinkFirst(f);
420     }
421     //获取并移除尾节点的值
422     public E pollLast() {
423         final Node<E> l = last;
424         return (l == null) ? null : unlinkLast(l);
425     }
426     //模拟堆栈
427     public void push(E e) {
428         addFirst(e);
429     }
430     //模拟堆栈
431     public E pop() {
432         return removeFirst();
433     }
434     //移除第一次出现的指定元素o
435     public boolean removeFirstOccurrence(Object o) {
436         return remove(o);
437     }
438     //移除最后一次出现的指定元素o
439     public boolean removeLastOccurrence(Object o) {
440         if (o == null) {
441             for (Node<E> x = last; x != null; x = x.prev) {
442                 if (x.item == null) {
443                     unlink(x);
444                     return true;
445                 }
446             }
447         } else {
448             for (Node<E> x = last; x != null; x = x.prev) {
449                 if (o.equals(x.item)) {
450                     unlink(x);
451                     return true;
452                 }
453             }
454         }
455         return false;
456     }
457     //返回从index开始的迭代器
458     public ListIterator<E> listIterator(int index) {
459         checkPositionIndex(index);
460         return new ListItr(index);
461     }
462     private class ListItr implements ListIterator<E> {
463         private Node<E> lastReturned;
464         private Node<E> next;
465         private int nextIndex;
466         private int expectedModCount = modCount;
467         ListItr(int index) {
468             next = (index == size) ? null : node(index);
469             nextIndex = index;
470         }
471         public boolean hasNext() {
472             return nextIndex < size;
473         }
474         public E next() {
475             checkForComodification();
476             if (!hasNext())
477                 throw new NoSuchElementException();
478             lastReturned = next;
479             next = next.next;
480             nextIndex++;
481             return lastReturned.item;
482         }
483         public boolean hasPrevious() {
484             return nextIndex > 0;
485         }
486         public E previous() {
487             checkForComodification();
488             if (!hasPrevious())
489                 throw new NoSuchElementException();
490             lastReturned = next = (next == null) ? last : next.prev;
491             nextIndex--;
492             return lastReturned.item;
493         }
494         public int nextIndex() {
495             return nextIndex;
496         }
497         public int previousIndex() {
498             return nextIndex - 1;
499         }
500         public void remove() {
501             checkForComodification();
502             if (lastReturned == null)
503                 throw new IllegalStateException();
504             Node<E> lastNext = lastReturned.next;
505             unlink(lastReturned);
506             if (next == lastReturned)
507                 next = lastNext;
508             else
509                 nextIndex--;
510             lastReturned = null;
511             expectedModCount++;
512         }
513         public void set(E e) {
514             if (lastReturned == null)
515                 throw new IllegalStateException();
516             checkForComodification();
517             lastReturned.item = e;
518         }
519         public void add(E e) {
520             checkForComodification();
521             lastReturned = null;
522             if (next == null)
523                 linkLast(e);
524             else
525                 linkBefore(e, next);
526             nextIndex++;
527             expectedModCount++;
528         }
529         public void forEachRemaining(Consumer<? super E> action) {
530             Objects.requireNonNull(action);
531             while (modCount == expectedModCount && nextIndex < size) {
532                 action.accept(next.item);
533                 lastReturned = next;
534                 next = next.next;
535                 nextIndex++;
536             }
537             checkForComodification();
538         }
539         final void checkForComodification() {
540             if (modCount != expectedModCount)
541                 throw new ConcurrentModificationException();
542         }
543     }
544     //实际存储元素的节点
545     private static class Node<E> {
546         E item;
547         Node<E> next;
548         Node<E> prev;
549         Node(Node<E> prev, E element, Node<E> next) {
550             this.item = element;
551             this.next = next;
552             this.prev = prev;
553         }
554     }
555     public Iterator<E> descendingIterator() {
556         return new DescendingIterator();
557     }
558     private class DescendingIterator implements Iterator<E> {
559         private final ListItr itr = new ListItr(size());
560         public boolean hasNext() {
561             return itr.hasPrevious();
562         }
563         public E next() {
564             return itr.previous();
565         }
566         public void remove() {
567             itr.remove();
568         }
569     }
570     @SuppressWarnings("unchecked")
571     private LinkedList<E> superClone() {
572         try {
573             return (LinkedList<E>) super.clone();
574         } catch (CloneNotSupportedException e) {
575             throw new InternalError(e);
576         }
577     }
578     public Object clone() {
579         LinkedList<E> clone = superClone();
580         clone.first = clone.last = null;
581         clone.size = 0;
582         clone.modCount = 0;
583         for (Node<E> x = first; x != null; x = x.next)
584             clone.add(x.item);
585         return clone;
586     }
587     //返回包含所有元素的数组(顺序和列表一致)
588     public Object[] toArray() {
589         Object[] result = new Object[size];
590         int i = 0;
591         for (Node<E> x = first; x != null; x = x.next)
592             result[i++] = x.item;
593         return result;
594     }
595     @SuppressWarnings("unchecked")
596     public <T> T[] toArray(T[] a) {
597         if (a.length < size)
598             a = (T[]) java.lang.reflect.Array.newInstance(a.getClass()
599                     .getComponentType(), size);
600         int i = 0;
601         Object[] result = a;
602         for (Node<E> x = first; x != null; x = x.next)
603             result[i++] = x.item;
604         if (a.length > size)
605             a[size] = null;
606         return a;
607     }
608     private static final long serialVersionUID = 876323262645176354L;
609     private void writeObject(java.io.ObjectOutputStream s)
610             throws java.io.IOException {
611         s.defaultWriteObject();
612         s.writeInt(size);
613         for (Node<E> x = first; x != null; x = x.next)
614             s.writeObject(x.item);
615     }
616     @SuppressWarnings("unchecked")
617     private void readObject(java.io.ObjectInputStream s)
618             throws java.io.IOException, ClassNotFoundException {
619         s.defaultReadObject();
620         int size = s.readInt();
621         for (int i = 0; i < size; i++)
622             linkLast((E) s.readObject());
623     }
624     @Override
625     public Spliterator<E> spliterator() {
626         return new LLSpliterator<E>(this, -1, 0);
627     }
628     static final class LLSpliterator<E> implements Spliterator<E> {
629         static final int BATCH_UNIT = 1 << 10;
630         static final int MAX_BATCH = 1 << 25;
631         final LinkedList<E> list;
632         Node<E> current;
633         int est;
634         int expectedModCount;
635         int batch;
636         LLSpliterator(LinkedList<E> list, int est, int expectedModCount) {
637             this.list = list;
638             this.est = est;
639             this.expectedModCount = expectedModCount;
640         }
641         final int getEst() {
642             int s;
643             final LinkedList<E> lst;
644             if ((s = est) < 0) {
645                 if ((lst = list) == null)
646                     s = est = 0;
647                 else {
648                     expectedModCount = lst.modCount;
649                     current = lst.first;
650                     s = est = lst.size;
651                 }
652             }
653             return s;
654         }
655         public long estimateSize() {
656             return (long) getEst();
657         }
658         public Spliterator<E> trySplit() {
659             Node<E> p;
660             int s = getEst();
661             if (s > 1 && (p = current) != null) {
662                 int n = batch + BATCH_UNIT;
663                 if (n > s)
664                     n = s;
665                 if (n > MAX_BATCH)
666                     n = MAX_BATCH;
667                 Object[] a = new Object[n];
668                 int j = 0;
669                 do {
670                     a[j++] = p.item;
671                 } while ((p = p.next) != null && j < n);
672                 current = p;
673                 batch = j;
674                 est = s - j;
675                 return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
676             }
677             return null;
678         }
679         public void forEachRemaining(Consumer<? super E> action) {
680             Node<E> p;
681             int n;
682             if (action == null)
683                 throw new NullPointerException();
684             if ((n = getEst()) > 0 && (p = current) != null) {
685                 current = null;
686                 est = 0;
687                 do {
688                     E e = p.item;
689                     p = p.next;
690                     action.accept(e);
691                 } while (p != null && --n > 0);
692             }
693             if (list.modCount != expectedModCount)
694                 throw new ConcurrentModificationException();
695         }
696         public boolean tryAdvance(Consumer<? super E> action) {
697             Node<E> p;
698             if (action == null)
699                 throw new NullPointerException();
700             if (getEst() > 0 && (p = current) != null) {
701                 --est;
702                 E e = p.item;
703                 current = p.next;
704                 action.accept(e);
705                 if (list.modCount != expectedModCount)
706                     throw new ConcurrentModificationException();
707                 return true;
708             }
709             return false;
710         }
711         public int characteristics() {
712             return Spliterator.ORDERED | Spliterator.SIZED
713                     | Spliterator.SUBSIZED;
714         }
715     }
716 }

小结

1. ArrayList底层为数组,查找操作复杂度为O(1),添加删除操作复杂度为O(N),而LinkedList底层为链表,查找操作复杂度为O(N),添加删除操作复杂度为O(1)
2. LinkedList和ArrayList一样,都是线程非安全的容器,如果需要同步操作,可以考虑用Collections.synchronizedList方法装饰一下
3. LinkedList源码末尾部分的Spliterator是JDK1.8引入的新接口,可以理解为Iterator的Split版本,它能把容器中的元素分割成多份再交给多个线程去遍历,从而提高效率

原文地址:https://www.cnblogs.com/sakura1027/p/8901520.html

时间: 2024-10-09 22:26:58

死磕JDK源码之LinkedList的相关文章

死磕JDK源码之ArrayList

ArrayList即动态数组,实现了动态的添加和减少元素 RandomAccess接口 标记接口,实现RandomAccess接口的类支持快速随机访问 Cloneable接口 没有实现Cloneable接口的类调用clone方法会抛出CloneNotSupportedException Object提供的clone方法是浅度复制 Serializable接口 标记接口,实现Serializable接口的类可以被序列化 Iterable接口 实现Iterable接口的类支持for-each循环 A

JDK源码学习LinkedList

LinkedList是List接口的子类,它底层数据结构是双向循环链表.LinkedList还实现了Deque接口(double-end-queue双端队列,线性collection,支持在两端插入和移除元素).所以LinkedList既可以被当作双向链表,还可以当做栈.队列或双端队列进行操作.文章目录如下: 1.LinkedList的存储实现(jdk 1.7.0_51) 2.LinkedList的读取实现 3.LinkedList的性能分析 下面我们进入正题,开始学习LinkedList. L

死磕Tomcat7源码之二:web组件初始化

经过死磕Tomcat7源码之一:解析web.xml,已经知道webapp的配置信息是如何解析到内存中.接下来,就是如何将对应的组件对象初始化化.分析所有的组件初始化过程,根本不可能.本文重点针对阐明3个主要组件的初始化过程,分别是:servlet,listener,filter.通过本文,你可以掌握以下知识点 了解组件初始化调用序列 组件servlet,listener,filter组件的初始化顺序 listener的初始化过程 servlet的初始化过程 filter的初始化过程 1.组件初始

JDK源码分析– LinkedList

LinkedList类的申明 1 public class LinkedList<E> 2 extends AbstractSequentialList<E> 3 implements List<E>, Deque<E>, Cloneable, java.io.Serializable 4 { 5 } LinkedList实现的接口与ArrayList大同小异,其中一个重要的接口Deque<E>,这个接口表示一个双向队列,也就是说LinkedLi

【JDK】JDK源码分析-LinkedList

概述 相较于 ArrayList,LinkedList 在平时使用少一些. LinkedList 内部是一个双向链表,并且实现了 List 接口和 Deque 接口,因此它也具有 List 的操作以及双端队列和栈的性质.双向链表的结构如下: 前文分析了 Queue 和 Deque 接口,正是因为 LinkedList 实现了 Deque 接口.LinkedList 的继承结构如下: 结点类 Node 查看 LinkedList 的源码可发现它内部有个嵌套类 Node,代码如下: private

【死磕jeestie源码】类型后面三个点(String...)和数组(String[])的区别

类型后面三个点(String...),是从Java 5开始,Java语言对方法参数支持一种新写法,叫可变长度参数列表,其语法就是类型后跟...,表示此处接受的参数为0到多个Object类型的对象,或者是一个Object[]. 例如我们有一个方法叫做test(String...strings),那么你还可以写方法test(),但你不能写test(String[] strings),这样会出编译错误,系统提示出现重复的方法. 在使用的时候,对于test(String...strings),你可以直接

死磕itchat源码--config.py

itchat的配置文件,源码: import os, platform # 版本及微信的url,二维码等 VERSION = '1.3.10' BASE_URL = 'https://login.weixin.qq.com' OS = platform.system() # Windows, Linux, Darwin DIR = os.getcwd() DEFAULT_QR = 'QR.png' TIMEOUT = (10, 60) # 代理配置 USER_AGENT = 'Mozilla/5

死磕itchat源码--core.py

core.py文件中的Core类定义了itchat的所有接口.且,仅仅是定义了接口,全部在component包中实现重构.其用法如下表述: 缺省 源码如下: # -*- encoding: utf-8 -*- import logging import requests from . import config, storage, utils, log from .components import load_components class Core(object): """

死磕Tomcat7源码之一:解析web.xml

熟悉java web开发的同学都清楚,tomcat作为一款非常流行的servlet容器,开源,流行,配置简单,不需要赘述.个人认为,web.xml作为webapp的入口,弄清楚该文件的底层解析过程,进而可以窥探tomcat的底层工作机制,搞明白tomcat对servlert规范的实现机理. 通过本文,可以知道以下部分内容 webapp部署3种部署方式 webapp web.xml解析流程 webapp Context对象信息的生成(不包括对象的生成) 总体来说,webapp部署有三种方式:XML