深入学习java源码之ArrayList.addAll()与ArrayList.retainAll()

2023-11-05

深入学习java源码之ArrayList.addAll()与ArrayList.retainAll()

引入多态

List是接口,所以实现类要把接口中的抽象方法全部重写。在重写的时候父类中的方法的时候,操作的数据类型也是要与父类保持一致的。
所以父类和子类操作的都是泛型E(此时还不确定具体操作的是什么数据类型,有使用者确定)

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}

List<String> list = new ArrayList<String>(); 	

 Java实现多态有三个必要条件:继承、重写、向上转型。
 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
 所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
 即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
 在这里我们这样理解,这里定义了一个List类型的list,它指向ArrayList对象实例。由于ArrayList是继承与List,所以ArrayList可以自动向上转型为List,所以list是可以指向ArrayList实例对象的。这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。
 但是向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们。所以父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在与子类中的方法和属性它就望尘莫及了。
 指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。        

引入泛型
使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常

         /*
         List list = new ArrayList();
         list.add("qqyumidi");
         list.add("corn");
         list.add(100);
         
         for (int i = 0; i < list.size(); i++) {
             String name = (String) list.get(i); // 1
             System.out.println("name:" + name);
         }
		 */
 
         List<String> list = new ArrayList<String>();
         list.add("qqyumidi");
         list.add("corn");
         //list.add(100);   // 1  提示编译错误
         for (int i = 0; i < list.size(); i++) {
             String name = list.get(i); // 2
             System.out.println("name:" + name);
         }

通过List<String>,直接限定了list集合中只能含有String类型的元素,从而在//2处无须进行强制类型转换,因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。         
泛型定义,我们知道在List<String>中,String是类型实参,也就是说,相应的List接口中肯定含有类型形参。且get()方法的返回结果也直接是此形参类型(也就是对应的传入的类型实参)    

Java泛型中的标记符含义: 
 E - Element (在集合中使用,因为集合中存放的是元素)
   ArrayList<Integer> list = new ArrayList<>();  
 T - Type(Java 类)

 K - Key(键)

 V - Value(值)

 N - Number(数值类型)

? -  表示不确定的java类型

泛型三种:
[1]ArrayList<T> al=new ArrayList<T>();指定集合元素只能是T类型
[2]ArrayList<?> al=new ArrayList<?>();集合元素可以是任意类型,这种没有意义,一般是方法中,只是为了说明用法
[3]ArrayList<? extends E> al=new ArrayList<? extends E>();
 泛型的限定:
 ? extends E:接收E类型或者E的子类型。
?super E:接收E类型或者E的父类型。

在具体使用时,可以分为泛型接口、泛型类和泛型方法。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
	
	    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }
	
	    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }
	
	    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

}

对于不同传入的类型实参,生成的相应对象实例的类型是不是一样的

 class Box<T> {
     private T data;
 
     public Box() {
 
     }
 
     public Box(T data) {
         this.data = data;
     }
 
     public T getData() {
         return data;
     }
 } 

 Box<String> name = new Box<String>("corn");
 Box<Integer> age = new Box<Integer>(712);

在使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,即还是原来的最基本的类型(本实例中为Box),当然,在逻辑上我们可以理解成多个不同的泛型类型。
究其原因,在于Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。
对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。

 

java源码

可调整大小的数组的实现List接口。 实现所有可选列表操作,并允许所有元素,包括null 。 除了实现List 接口之外,该类还提供了一些方法来操纵内部使用的存储列表的数组的大小。 (这个类是大致相当于Vector,不同之处在于它是不同步的)。 
该size,isEmpty,get,set,iterator和listIterator操作在固定时间内运行。 add操作以摊余常数运行 ,即添加n个元素需要O(n)个时间。 所有其他操作都以线性时间运行(粗略地说)。 与LinkedList实施相比,常数因子较低。 

每个ArrayList实例都有一个容量 。 容量是用于存储列表中的元素的数组的大小。 它总是至少与列表大小一样大。 当元素添加到ArrayList时,其容量会自动增长。 没有规定增长政策的细节,除了添加元素具有不变的摊销时间成本。 

应用程序可以添加大量使用ensureCapacity操作元件的前增大ArrayList实例的容量。 这可能会减少增量重新分配的数量。 

请注意,此实现不同步。 如果多个线程同时访问884457282749实例,并且至少有一个线程在结构上修改列表,则必须在外部进行同步。 (结构修改是添加或删除一个或多个元素的任何操作,或明确调整后台数组的大小;仅设置元素的值不是结构修改。)这通常是通过在一些自然地封装了列表。 如果没有这样的对象存在,列表应该使用Collections.synchronizedList方法“包装”。 这最好在创建时完成,以防止意外的不同步访问列表: 

  List list = Collections.synchronizedList(new ArrayList(...)); The iterators returned by this class's个 iterator和listIterator方法是快速失败的 :如果列表在任何时间从结构上修改创建迭代器之后,以任何方式除非通过迭代器自身remove种或add方法,迭代器都将抛出一个ConcurrentModificationException 。 因此,面对并发修改,迭代器将快速而干净地失败,而不是在未来未确定的时间冒着任意的非确定性行为。 

请注意,迭代器的故障快速行为无法保证,因为一般来说,在不同步并发修改的情况下,无法做出任何硬性保证。 失败快速迭代器尽力投入ConcurrentModificationException 。 因此,编写依赖于此异常的程序的正确性将是错误的:迭代器的故障快速行为应仅用于检测错误。 

Modifier and Type Method and Description
boolean add(E e)

将指定的元素追加到此列表的末尾。

void add(int index, E element)

在此列表中的指定位置插入指定的元素。

boolean addAll(Collection<? extends E> c)

按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。

boolean addAll(int index, Collection<? extends E> c)

将指定集合中的所有元素插入到此列表中,从指定的位置开始。

void clear()

从列表中删除所有元素。

Object clone()

返回此 ArrayList实例的浅拷贝。

boolean contains(Object o)

如果此列表包含指定的元素,则返回 true 。

void ensureCapacity(int minCapacity)

如果需要,增加此 ArrayList实例的容量,以确保它可以至少保存最小容量参数指定的元素数。

void forEach(Consumer<? super E> action)

Iterable的每个元素执行给定的操作,直到所有元素都被处理或动作引发异常。

E get(int index)

返回此列表中指定位置的元素。

int indexOf(Object o)

返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。

boolean isEmpty()

如果此列表不包含元素,则返回 true 。

int lastIndexOf(Object o)

返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。

E remove(int index)

删除该列表中指定位置的元素。

boolean remove(Object o)

从列表中删除指定元素的第一个出现(如果存在)。

boolean removeAll(Collection<?> c)

从此列表中删除指定集合中包含的所有元素。

boolean removeIf(Predicate<? super E> filter)

删除满足给定谓词的此集合的所有元素。

protected void removeRange(int fromIndex, int toIndex)

从这个列表中删除所有索引在 fromIndex (含)和 toIndex之间的元素。

void replaceAll(UnaryOperator<E> operator)

将该列表的每个元素替换为将该运算符应用于该元素的结果。

boolean retainAll(Collection<?> c)

仅保留此列表中包含在指定集合中的元素。

E set(int index, E element)

用指定的元素替换此列表中指定位置的元素。

int size()

返回此列表中的元素数。

void sort(Comparator<? super E> c)

使用提供的 Comparator对此列表进行排序以比较元素。

Object[] toArray()

以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。

<T> T[] toArray(T[] a)

以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。

void trimToSize()

修改这个 ArrayList实例的容量是列表的当前大小。

package java.util;

import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    private static final int DEFAULT_CAPACITY = 10;

    private static final Object[] EMPTY_ELEMENTDATA = {};

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    transient Object[] elementData; // non-private to simplify nested class access

    private int size;

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

    // Positional Access Operations

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

    public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

    /**
     * Removes all of the elements from this list.  The list will
     * be empty after this call returns.
     */
    public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

    private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        int 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();
        }
    }

    /**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not 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();
            }
        }
    }

    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        // figure out which elements are to be removed
        // any exception thrown from the filter predicate at this stage
        // will leave the collection unmodified
        int removeCount = 0;
        final BitSet removeSet = new BitSet(size);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if (filter.test(element)) {
                removeSet.set(i);
                removeCount++;
            }
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }

        // shift surviving elements left over the spaces left by removed elements
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            final int newSize = size - removeCount;
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            elementData[i] = operator.apply((E) elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入学习java源码之ArrayList.addAll()与ArrayList.retainAll() 的相关文章

  • 深入学习java源码之Integer.parseInt()与Integer.valueOf()

    深入学习java源码之Integer parseInt 与Integer valueOf 一般我们创建一个类的时候是通过new关键字 比如 Object obj new Object 但是对于 Integer 类 我们却可以这样 Integ
  • 深入学习java源码之Math.scalb()与 Math.powerOfTwoF()

    深入学习java源码之Math scalb 与 Math powerOfTwoF final关键字 final在Java中是一个保留的关键字 可以声明成员变量 方法 类以及本地变量 一旦你将引用声明作final 你将不能改变这个引用了 编译
  • java泛型代码编写

    java泛型代码编写 泛型的由来 我们先看下面这段代码 List list new ArrayList list add 24 向集合中添加一个 Integer 类型的数据 list add Tom 向集合中添加一个 String 类型的数
  • Unsafe初探

    Unsafe Unsafe 是sun misc Unsafe下的一个包 通过这个类可以直接使用底层native方法来获取和操作底层的数据 例如获取一个字段在内存中的偏移量 利用偏移量直接获取或修改一个字段的数据等等 当然这个类正如他的名字一
  • 深入学习java源码之ArrayList.addAll()与ArrayList.retainAll()

    深入学习java源码之ArrayList addAll 与ArrayList retainAll 引入多态 List是接口 所以实现类要把接口中的抽象方法全部重写 在重写的时候父类中的方法的时候 操作的数据类型也是要与父类保持一致的 所以父
  • Spring Bean生命周期doCreateBean源码阅读

    bean的生命周期的几个后置接口都是在这个方法里面调用 所以单独开一篇该方法的源码阅读 下面从两个点来阅读 1 何时调用 只看容器启动 2 梳理这个方法的流程 跟上一节对应上 先贴上源码 protected Object doCreateB
  • 深入学习java源码之ArrayList.iterator()与ArrayList.listIterator()

    深入学习java源码之ArrayList iterator 与ArrayList listIterator 内部类的使用典型的情况是 内部类继承自某个类或实现某个接口 内部类的代码操作创建其的外层类的对象 所以你可以认为内部类提供了某种进入
  • 深入学习java源码之Byte.decode()与Byte.toUnsignedInt()

    深入学习java源码之Byte decode 与Byte toUnsignedInt 异常 异常就是有异于常态 和正常情况不一样 有错误出错 在java中 阻止当前方法或作用域的情况 称之为异常 其中Error类中包括虚拟机错误和线程死锁
  • Java多线程代码编写

    Java多线程代码编写 什么是多线程 并发和并行 并行 指两个或多个时间在同一时刻发生 同时发生 并发 指两个或多个事件在一个时间段内发生 在操作系统中 安装了多个程序 并发指的是在一段时间内宏观上有多个程序同时运行 这在单 CPU 系统中
  • Java动态代理代码编写

    Java动态代理代码编写 代理的概念 动态代理技术是整个java技术中最重要的一个技术 它是学习java框架的基础 不会动态代理技术 那么在学习Spring这些框架时是学不明白的 动态代理技术就是用来产生一个对象的代理对象的 在开发中为什么
  • 堵塞队列之ArrayBlockingQueue和LinkedBlockingQueue解析

    在线程池创建的时候 需要传一个堵塞队列来维护需要执行的线程任务 其中最常用的是ArrayBlockingQueue和LinkedBlockingQueue 他们都继承了BlockingQueue接口 ArrayBlockingQueue 一
  • 使用java关键字编写代码

    使用java关键字编写代码 java的关键字 java的基本数据类型 Java是一种强类型语言 必须为每一个变量声明一种类型 Java共包含8中基本类型 其中4种整型 2种浮点型 1种用于表示Unicode编码的字符单元的字符类型char和
  • 线程池面试题

    线程池面试题 1 Executor 框架三大组成部分 2 ThreadPoolExecutor 类 线程池执行器 核心 2 1 ThreadPoolExecutor 3 个最重要的参数 2 2 ThreadPoolExecutor 饱和策略
  • 基于springboot+微信小程序实现校园互助平台项目演示【附项目源码+论文说明】

    基于springboot 微信小程序实现校园互助平台项目演示 摘要 随着我国经济迅速发展 人们对手机的需求越来越大 各种手机软件也都在被广泛应用 但是对于手机进行数据信息管理 对于手机的各种软件也是备受用户的喜爱 校园互助平台被用户普遍使用
  • 基于java中SSM框架+小程序实现乐器商城程序设计演示【附项目源码】

    基于java中SSM框架 小程序实现乐器商城程序设计演示 JAVA简介 JAVA语言是目前软件市场上应用最广泛的语言开发程序 可以在多种平台上运用的 兼容性比较强 适应市面上大多数操作系统 不会出现乱码的现像 其扩展性和维护性都更好 具有分
  • 基于springboot+vue实现汽车改装方案网站演示【附项目源码+论文说明】

    基于springboot vue实现汽车改装方案网站演示 摘要 本文主要讲述了基于SpringBoot MySql开发技术开发的汽车改装方案网站的设计与实现 这里的汽车改装方案网站是通过一个平台使所有的汽车爱好者们可以不用出门就可以体验到专
  • 基于springboot+vue实现实企业任务管理追踪系统【附项目源码+论文说明】

    基于springboot vue实现实企业任务管理追踪系统 摘要 随着时代的进步 人们现在通过计算机线上化的办公方式成功的提升了日常办公的效率 通过线上办公能够有效地提升信息传递的效率 可以快速的完成任务的流程处理 邮件的发送等等功能 并且
  • 基于springboot+vue实现流浪动物救助平台演示【附项目源码+论文说明】

    基于springboot vue实现流浪动物救助平台演示 摘要 随着人们对于动物及环境保护的意识越来越强 流浪动物的救助与保护涉及到了健康卫生以及城市容貌等多个方面 流浪动物保护是一个全球性的问题 不同的国家和地区都出台了形式多样的保护办法
  • 基于springboot+vue实现食品安全管理系统演示【附项目源码+论文说明】

    基于springboot vue实现食品安全管理系统演示 摘要 食品行业同其他行业有很多的差别 食品行业不仅要管食品的生产和销售 还要管食品的库存和保质期 那么对于食品管理者来说 就存在着一定的难度 况且食品的种类复杂 存储条件各不相同 存
  • 基springboot+vue实现开放实验室管理系统子系统【附项目源码+论文说明】

    基springboot vue实现开放实验室管理系统子系统 摘要 信息技术永远是改变生活的第一种创新方式 各种行业的发展更是脱离不了科技化的支持 原本传统的行业正在被科技行业的切入悄悄的发生变化 就拿我们生活当中常见的事情举例而言 在外卖行

随机推荐

  • 使用jquery解析XML的方法,很简单

    尽量使用高版本的的jquery 有的jquery版本会报没有parseXML属性的错误 我用的jquery 1 7 2 min js xml文件格式
  • 多阶段构建Golang程序Docker镜像方法详解

    为什么要多阶段构建 大家都知道Golang是编译型语言 源码需要先编译再运行 编译过程中需要下载依赖包 最终编译成可执行的二进制文件 只需要部署这个二进制文件即可运行 现在基本都是采用容器化部署方式 打包出的镜像体积越小越好 和程序运行无关
  • Django入门之定义模型和表迁移

    django3 0 定义表模型并通过定义好的模型实现源代码创建数据表 目录 概述 定义表模型 引入模型类 继承 创建表模型 注意 创建数据表 1 生成迁移文件 2 执行迁移 3 更新表文件 总结 概述 模型是一个用于表示数据的Python类
  • 《算法和数据结构》从语言到算法的过渡篇

    本文已收录于专栏 夜深人静写算法 前言 看到太多爆肝熬夜整合的内容 又是几万字 又是爆肝 我也来试试看能不能扛得住 试完后发现 果然还是扛不住啊 但是既然整理完了 那就把我的 算法学习路线 发出来吧 我把整个算法学习的阶段总结成了五个步骤
  • 现代C++教程 笔记

    写在前面 记录一下 现代C 教程 中的要点 现代C 是指C 11之后的语法特性 如无特别说明 下面的语法特性均是C 11后才可使用 一 语言可用性的强化 1 常量 1 1 nullptr 作用 代替NULL赋空指针 使用 char a nu
  • 《ESP32 学习笔记》 之 ESP32 引脚图 及 个引脚特定功能 概览

    ESP32 S 模组 NODEMCU 32S 原理图 各个IO口功能
  • Qt 多线程之线程事件循环(深入理解)

    Qt支持三种类型的信号 槽连接 1 直接连接 当signal发射时 slot立即调用 此slot在发射signal的那个线程中被执行 不一定是接收对象生存的那个线程 2 队列连接 当控制权回到对象属于的那个线程的事件循环时 slot被调用
  • 在pl/sql中执行动态sql

    动态sql就是把sql写在一个字符串里 在存储过程中解析字符串执行sql 这种动态sql很多时候会在别的语言里写 再连接数据库进行操作 这样的确方便很多 例如在java中使用JDBC 但是如果涉及到sql变化很多次 直接在存储过程中写动态s
  • Linux嵌入汇编1- 详解

    Linux上的 GNU C 编译器 GCC 使用 AT T UNIX 汇编语法 源操作数与目的操作数顺序 AT T 语法的操作数方向和 Intel 语法的刚好相反 在Intel 语法中 第一操作数为目的操作数 第二操作数为源操作数 然而在
  • python 使用node_vm2执行js

    有时候 一些js需要调用 之前都是用nodejs比较多 但是有些js会验证是否使用的是node 就比如某头条的加密 为了能本地调用扣下来的js 这里就不能用nodejs或者execjs 需要用到vm2 步骤 1 下载vm2 pip inst
  • 排序与查找代码总结-数据结构与算法python版

    代码来源于北京大学的数据结构与算法课 Python版 注释为本人自己加上的 可供学习使用 不可用于商业转载 有错误烦请指出 感谢 目录 二分查找 普通版 递归版 冒泡排序 普通版 加了是否发生交换的监测 选择排序 插入排序 希尔排序 归并排
  • C语言

    C 菜鸟教程 C 结构体位域
  • win7搭建虚拟pppoe服务器,Win7在桌面建立一个pppoe宽带自动连接器的方法

    本教程告诉大家如何在Win7在桌面建立一个pppoe宽带自动连接器教程 现在电脑已经普及使用了 每次开机都要连接宽带上网 很多用户说如何快速在Windows桌面建立一个PPPOE宽带连接 方便直接连接 之前在xp系统可以建立pppoe宽带自
  • 合并两个有序链表 c++

    LeetCode 21 合并两个有序链表 题目 21 合并两个有序链表 代码 Definition for singly linked list struct ListNode int val ListNode next ListNode
  • 哪些工具可以实现在线ps的需求

    在线Photoshop有哪些工具可以选择 在 Adobe 的官网上就能够实现 很惊讶吧 其实 Adobe 官方推出了在线版本的 Photoshop 的 尽管目前还是 Beta版本 但其实也开放了蛮久了 编辑切换为居中 添加图片注释 不超过
  • TCP协议及特性详解

    文章目录 TCP 确认应答 超时重传 连接建立与断开 三次挥手 四次挥手 四种常见状态 效率提升机制 滑动窗口 流量控制 拥塞控制 延时应答 捎带应答 粘包问题 TCP TCP 协议是一个有连接 可靠传输 面向字节流 全双工的传输层通信协议
  • Hive中数组的使用

    基本操作 创建文本 gt cat test txt 输入文本数据 12 23 23 34 what are this 34 45 34 23 12 who am i are 打开Hive 创建表 hive gt create table t
  • 常见几种滤波器的比较

    经典的数字滤波器有巴特沃斯滤波器 切比雪夫滤波器 椭圆滤波器和贝塞尔滤波器等 巴特沃斯滤波器的特点是通频带内的频率响应曲线最大限度平坦 没有起伏 而在阻频带则逐渐下降为零 在振幅的对数对角频率的波特图上 从某一边界角频率开始 振幅随着角频率
  • Linux FTP服务(只允许白名单用户访问FTP)

    目录 一 FTP服务器 二 FTP文化传输协议 FTP的传输模式有两种 三 Vsftpd服务程序 四 实验步骤 1 安装vsftpd软件包 2 备份主配置文件 3 去掉 号开头的行 4 创建黑 白名单的目的 约束 允许某些特定用户登录系统
  • 深入学习java源码之ArrayList.addAll()与ArrayList.retainAll()

    深入学习java源码之ArrayList addAll 与ArrayList retainAll 引入多态 List是接口 所以实现类要把接口中的抽象方法全部重写 在重写的时候父类中的方法的时候 操作的数据类型也是要与父类保持一致的 所以父