在源码分析系列的文档中,笔者会尽量使用CURD操作的角度来分析JDK的源码。是因为多数程序员都是CURD阶段,当然最熟悉的还是CURD操作,因此以CURD的角度来看JDK的源码,相信会容易不少,毕竟万物皆可CURD,万物离不开CURD

注1:开发工具为IntelliJ IDEA 2020.1.2 x64 

注2:  JDK版本为JDK8  版本号为 jdk1.8.0_191


talk is cheap,show me the code ---undefined


代码段如下,有清晰明了的注释

import java.util.ArrayList;
import java.util.List;public class ArrayListTest  {public static void main(String[] args) {//无参构造函数new一个ArrayListList arraylist=new ArrayList();//ArrayList的add操作arraylist.add("hello world");arraylist.add("world hello");System.out.println("当前ArrayList的容量大小"+arraylist.size());//循环增长,查看动态grow函数for (int i=0;i<10;i++){arraylist.add(i);}System.out.println("当前ArrayList的容量大小"+arraylist.size());//Arraylist的getter setter操作System.out.println("getter"+arraylist.get(3));System.out.println("setter"+arraylist.set(3,"huhu"));System.out.println("当前ArrayList的容量大小"+arraylist.size());//arraylist的addall操作arraylist.addAll(arraylist);System.out.println("当前ArrayList的容量大小"+arraylist.size());//arraylist的index操作System.out.println("这是索引"+arraylist.indexOf("world hello"));System.out.println("这是最后索引"+arraylist.lastIndexOf("world"));System.out.println("当前ArrayList的容量大小"+arraylist.size());System.out.println("是否包含有"+arraylist.contains("huhu"));System.out.println("是否包含所有"+arraylist.containsAll(arraylist));System.out.println("当前ArrayList的容量大小"+arraylist.size());//arraylist的remove操作System.out.println("删除元素"+arraylist.remove("world hello"));System.out.println("删除元素"+arraylist.remove(4));System.out.println("当前ArrayList的容量大小"+arraylist.size());//arraylist的retain操作arraylist.retainAll(arraylist);arraylist.removeAll(arraylist);System.out.println("当前ArrayList的容量大小"+arraylist.size());}}

OK,下面我们试着断点分析来看看ArrayList的源码

到此步,请保留你的耐心,因为看源码是一个非常枯燥和非常花时间的过程,如果你觉得看不下去,可以休息一会儿,再继续。毕竟看源码,如同登山,当你在山顶时,相信看的风景会非常不一样的。

1. 看new ArrayList发生了什么

         //无参构造函数new一个ArrayListList arraylist=new ArrayList();

此行打断点(ctrl+F8),启用单步调试(F7)或者强制进入(Alt+Shift+F7)可以看到

  /*** Constructs an empty list with an initial capacity of ten.*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;         //无参构造函数初始化容量为10的空数组,目前代码只是初始化为空数组,并没有指定容量?什么时候指定的容量?}

可以看见new ArrayList()调用了无参构造函数,在此构造函数中ArrayList将之前初始化过后的静态变量  DEFAULTCAPACITY_EMPTY_ELEMENTDATA  (初始化构造了一个默认容量为10的空数组列表)并将其引用赋值给了ArrayList的本地真实的存储结构即elementData。

注3:无参仅仅初始化了一个空的数组列表,并没有指定数组的大小 (此为无参构造函数做的事)那么是什么时候指定了默认容量为10呐?是在calculateCapacity方法中,当elementData为默认容量的空数组列表时,返回一个10的值表示为列表的容量大小(后文会叙述)

2. 看 ArrayList的add操作发生了什么

        //ArrayList的add操作arraylist.add("hello world");arraylist.add("world hello");System.out.println("当前ArrayList的容量大小"+arraylist.size());//循环增长,查看动态grow函数for (int i=0;i<10;i++){arraylist.add(i);}System.out.println("当前ArrayList的容量大小"+arraylist.size());

在第一个add方法代码行出打一个断点,操作如同上文,在循环中的add又打一个断点(是为了方便查看ArrayList的动态扩容机制),启用单步调试(F7)或者强制进入(Alt+Shift+F7)可以看到

  /*** Appends the specified element to the end of this list.** @param e element to be appended to this list* @return <tt>true</tt> (as specified by {@link Collection#add})*/public boolean add(E e) {                           //此函数将指定的元素放在列表末尾(以追加的方式)ensureCapacityInternal(size + 1);  // Increments modCount!!     //以当前大小+1为最小容量值为参数来判断所需要的容量大小elementData[size++] = e;return true;}private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {         //当elementData是默认容量数组列表时,则返回默认容量大小10return Math.max(DEFAULT_CAPACITY, minCapacity);             //在这儿返回指定了elementData的默认容量大小10}return minCapacity;                                             //当elementData数组元素时候。则返回最小的容量大小}private void ensureExplicitCapacity(int minCapacity) {modCount++;                                 //结构性变化+1// overflow-conscious code               //此代码可能会造成溢出if (minCapacity - elementData.length > 0)              //如果最小容量大小都大于当前数组列表的大小则调用增长函数grow(minCapacity);}/*** Increases the capacity to ensure that it can hold at least the* number of elements specified by the minimum capacity argument.** @param minCapacity the desired minimum capacity*/private void grow(int minCapacity) {// overflow-conscious codeint 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);}

代码比较复杂也比较多,所以需要耐心,不要慌,我们按照方法的调用顺序来看看,add操作都发生了什么?

add->ensureCapacityInternal->ensureExplicitCapacity->calculateCapacity

1. calculateCapacity是计算ArrayList的最小容量的

如果最开始是初始化的空数组列表,则返回10的初始化容量,如果不是,则返回代入的参数即最小容量值

注4: 在看此源码的过程中,需要分清这么几个概念,通常概念不清,就看源码比较困难

长度指的是ArrayList的长度,表示是ArrayList可以容纳的元素多少个数

最小容量值指的是ArrayList在结构性变化的过程中所需要的容纳空间

大小指的是ArrayList实际上所拥有的元素个数的大小即size方法所返回的size值,也即ArrayList中的size属性

2. ensureExplicitCapacity是用来调用grow方法和针对modCount自增的

注5: modCount表示针对ArrayList的结构性变化的指针标识,如add,remove等

3. grow实现了ArrayList的动态扩容机制(重点)(面试常问)

在grow方法体内我们可以看到

旧容量为原来的ArrayList的长度大小

而新容量则是旧容量的1.5倍

若新容量都小于所需要的最小容量,则将最小容量赋值给新容量

若新容量比极限容量要大,那么就将极限容量和最大整型数当中的最大值赋值给新容量

完成以上的步骤后,就根据新容量来初始化一个新的数组,将原来的elementData的所有元素都等位的复制到新的数组当中,然后将新的数组引用赋值给elementData,这样就完成了ArrayList的动态扩容机制

Q1:ArrayList的动态扩容机制是怎么回事?

Q2:什么时候会触发ArrayList的扩容?

Q3:为什么新容量会设置成旧容量的1.5倍?为什么会采取位运算而不是简单的乘除运算?

Q4:若需要的最小容量都达到了极限容量值,是否还需要扩容?是否会报异常?

Q5: grow方法会被哪些方法给调用?哪些是显式调用?哪些是隐式调用?

Q6:ArrayList的扩容机制的时间复杂和空间复杂度是?频繁的动态扩容会导致什么样的问题?

4. 经过了以上的动态扩容之后

elementData就是新容量的数组列表了,然后执行了size++,并将这个位置上的元素填上所传入的参数值。

注6: add操作是在数组列表末尾直接追加元素,所以才使用了size++,并元素赋值

5. 成功之后,返回真值

3. 看ArrayList的getter setter操作发生了什么

           //Arraylist的getter setter操作System.out.println("getter"+arraylist.get(3));System.out.println("setter"+arraylist.set(3,"huhu"));System.out.println("当前ArrayList的容量大小"+arraylist.size());

按照上面的方法同样的打断点进入调试,可以看见

  /*** Returns the element at the specified position in this list.*3* @param  index index of the element to return* @return the element at the specified position in this list* @throws IndexOutOfBoundsException {@inheritDoc}*/public E get(int index) {rangeCheck(index);return elementData(index);}/*** Replaces the element at the specified position in this list with* the specified element.** @param index index of the element to replace* @param element element to be stored at the specified position* @return the element previously at the specified position* @throws IndexOutOfBoundsException {@inheritDoc}*/public E set(int index, E element) {rangeCheck(index);E oldValue = elementData(index);elementData[index] = element;return oldValue;}/*** Checks if the given index is in range.  If not, throws an appropriate* runtime exception.  This method does *not* check if the index is* negative: It is always used immediately prior to an array access,* which throws an ArrayIndexOutOfBoundsException if index is negative.*/private void rangeCheck(int index) {if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}// Positional Access Operations@SuppressWarnings("unchecked")E elementData(int index) {return (E) elementData[index];}

此源码可以分3部分看,一部分是getter setter操作,一部分是rangeCheck,一部分是elementData

先看getter,可以看到

1. 先调用了rangecheck

步入rangeCheck,发现是针对传入的索引值进行合法性检查,若传入的索引值大于或者等ArrayList的大小,就抛出了 IndexOutOfBoundsException 说明了是索引溢出边界异常,在上面的注释可以发现,若索引值是负数的,就抛出 ArrayIndexOutOfBoundsException 说明了是数组索引溢出边界异常

2. 若传入索引值合法

则调用elementData方法,返回该索引位置上的元素

注7:为什么会有两个索引异常?一个是 IndexOutOfBoundsException 另外一个是 ArrayIndexOutOfBoundsException? 是针对什么情况呢?针对索引值的检查?如此代码就足够了吗?

注8:为什么要编写一个elementData方法?通过这个方法来返回元素?而不是直接使用 e=elementData(index)?

再看setter,可以看到

1. 调用rangeCheck检查索引合法性

2. 将索引值上的元素作为旧元素返回

3. 传入的新值赋值给索引值上的元素

此getter setter方法都比较简单,就不多说了

4. 看addAll操作发生了什么

           //arraylist的addall操作arraylist.addAll(arraylist);System.out.println("当前ArrayList的容量大小"+arraylist.size());

同上一样的进入调试,可以发现

/*** Appends all of the elements in the specified collection to the end of* this list, in the order that they are returned by the* specified collection's Iterator.  The behavior of this operation is* undefined if the specified collection is modified while the operation* is in progress.  (This implies that the behavior of this call is* undefined if the specified collection is this list, and this* list is nonempty.)** @param c collection containing elements to be added to this list* @return <tt>true</tt> if this list changed as a result of the call* @throws NullPointerException if the specified collection is null*/public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew);  // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;}

1. 将传入的集合通过toArray方法转为object的数组对象列表

2. 调用ensureCapacityInternal方法来计算当前size+集合中的元素大小是否能够有容纳空间?如果有,就继续,如果没有就需要调用grow方法进行扩容,直到了有容纳空间为止(grow的具体操作可以参考上文)

3. 调用System.arraycopy方法完成一次数组之间的复制,将集合中的元素追加复制到elementData中

4. size+numNew完成size大小的更新

5. 返回boolean值

5. 看index操作和contain操作都发生了什么

            //arraylist的index操作System.out.println("这是索引"+arraylist.indexOf("world hello"));System.out.println("这是最后索引"+arraylist.lastIndexOf("world"));System.out.println("当前ArrayList的容量大小"+arraylist.size());System.out.println("是否包含有"+arraylist.contains("huhu"));System.out.println("是否包含所有"+arraylist.containsAll(arraylist));System.out.println("当前ArrayList的容量大小"+arraylist.size());

同上一样的进入调试,可以发现

    /*** Returns <tt>true</tt> if this list contains the specified element.* More formally, returns <tt>true</tt> if and only if this list contains* at least one element <tt>e</tt> such that* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.** @param o element whose presence in this list is to be tested* @return <tt>true</tt> if this list contains the specified element*/public boolean contains(Object o) {return indexOf(o) >= 0;}/*** Returns the index of the first occurrence of the specified element* in this list, or -1 if this list does not contain the element.* More formally, returns the lowest index <tt>i</tt> such that* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,* or -1 if there is no such index.*/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;}/*** Returns the index of the last occurrence of the specified element* in this list, or -1 if this list does not contain the element.* More formally, returns the highest index <tt>i</tt> such that* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,* or -1 if there is no such index.*/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;}

先看indexOf,可以看出

1. 对传入的object对象引用判空

2. 如果是空,就for循环来获取整个ArrayList中第一次出现null的值,如果有,就返回该处索引值,如果循环完了,都没有,就返回-1

3. 如果object不是空,一样的for循环遍历整个ArrayList,查找第一次出现该值相同的位置,并返回该值所处的索引值,若遍历完了,都没有,就返回-1

再看lastindexOf,可以看出

实现的逻辑是跟indexOf是差不多的,都是遍历整个ArrayList来查找object,唯一不同是,遍历是倒序遍历,返回自然是最后一次出现该值的索引

再看contain,也可以发现

调用了indexOf,只不过是是通过indexOf来查找该元素的索引值,然后比对索引值是否大于等于0,若是就返回真,否则就是假,表示该元素在整个ArrayList中不存在

注9:为什么需要对传入的object判空?空值和非空值对判断查找是否有区别?

6. 看remove操作发生了什么

//arraylist的remove操作System.out.println("删除元素"+arraylist.remove("world hello"));System.out.println("删除元素"+arraylist.remove(4));System.out.println("当前ArrayList的容量大小"+arraylist.size());

同上一样,调试进入源代码,可以看出

  /*** Removes the element at the specified position in this list.* Shifts any subsequent elements to the left (subtracts one from their* indices).** @param index the index of the element to be removed* @return the element that was removed from the list* @throws IndexOutOfBoundsException {@inheritDoc}*/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 workreturn oldValue;}/*** Removes the first occurrence of the specified element from this list,* if it is present.  If the list does not contain the element, it is* unchanged.  More formally, removes the element with the lowest index* <tt>i</tt> such that* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>* (if such an element exists).  Returns <tt>true</tt> if this list* contained the specified element (or equivalently, if this list* changed as a result of the call).** @param o element to be removed from this list, if present* @return <tt>true</tt> if this list contained the specified element*/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 remove method that skips bounds checking and does not* return the value removed.*/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}

remove这个操作有两个重载函数,一个是根据索引来remove,一个是根据对象来remove

先看根据索引来remove的代码

1. 检验索引是否合法

2. 结构性标识变化加1

3. 计算需要开始移动的索引位置

4. 如果索引位置大于0,就调用System.arraycopy从需要移动的索引位置开始从后往前覆盖复制

5. elementData的最后一个元素位置设置为null

6. 返回旧值

注10:为什么要对elementData最后一个末尾元素设置为null?注释解释为了让gc能工作,那么仅仅是为了让gc工作么?gc又是什么时候发生gc的呢?若对不需要的元素引用设置为null,是否能马上gc?

再看根据object来remove的代码

1. 很显然首先需要判断object是否为null

2. 根据是否为null值,分两种方法,循环遍历查找对应的值

3. 调用fastremove方法

4. fastremove方法中的代码跟上文的remove(int index)步骤下2到5一致,也就是2到5封装成了一个fastremove方法

注11:为什么步骤2到5封装成了一个fastremove方法?是否能快速删除?

7. 看retainAll和removeAll发生了什么

        //arraylist的retain操作arraylist.retainAll(arraylist);arraylist.removeAll(arraylist);System.out.println("当前ArrayList的容量大小"+arraylist.size());

同上一样,调试进入源代码,可以发现

    /*** Removes from this list all of its elements that are contained in the* specified collection.** @param c collection containing elements to be removed from this list* @return {@code true} if this list changed as a result of the call* @throws ClassCastException if the class of an element of this list*         is incompatible with the specified collection* (<a href="Collection.html#optional-restrictions">optional</a>)* @throws NullPointerException if this list contains a null element and the*         specified collection does not permit null elements* (<a href="Collection.html#optional-restrictions">optional</a>),*         or if the specified collection is null* @see Collection#contains(Object)*/public boolean removeAll(Collection<?> c) {Objects.requireNonNull(c);return batchRemove(c, false);}/*** Retains only the elements in this list that are contained in the* specified collection.  In other words, removes from this list all* of its elements that are not contained in the specified collection.** @param c collection containing elements to be retained in this list* @return {@code true} if this list changed as a result of the call* @throws ClassCastException if the class of an element of this list*         is incompatible with the specified collection* (<a href="Collection.html#optional-restrictions">optional</a>)* @throws NullPointerException if this list contains a null element and the*         specified collection does not permit null elements* (<a href="Collection.html#optional-restrictions">optional</a>),*         or if the specified collection is null* @see Collection#contains(Object)*/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 workfor (int i = w; i < size; i++)elementData[i] = null;modCount += size - w;size = w;modified = true;}}return modified;}

1. 调用object.requireNonNull检查元素object是否为空

2. 不管是retainAll还是removeAll都调用了batchRemove方法,只不过传入参数一个正一个负

3. 来看看batchRemove究竟发生了什么

 

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. mybatis大于小于等于的写法

    目录mybatis中大于等于小于等于的写法 mybatis中大于等于小于等于的写法 替换1: < < <= <= > > >= >= & &amp;&apos; " &quot;替换2: 借助XML语法,在CDATA内部的内容会被解析器忽略。<![CDATA[ 符号 ]]>例: &…...

    2024/4/15 3:05:41
  2. python 类中类里底层类访问修改外层类的方法

    由于某种原因需要用到类中类的结构(比如类中的某个功能要用到多进程继承类的实现),但是按照平常的写法会存在底层类无法访问修改外层类的self里的变量的情况(底层类继承外层类仅能实现获得值,不能修改外层类的值).class Mother: # 外层类def __init__(self):self.x = 0self.ru…...

    2024/4/28 3:05:23
  3. 上传图片测试点

    1.功能测试 (1)选择符合要求的图片,上传--------上传成功; (2)上传成功的图片名称显示----------显示正常(根据需求) (3)查看,下载上传成功的图片--------上传的图片可查看或下载 (4)删除上传成功的图片-------------可删除 (5)替换上传成功的图片-------------…...

    2024/4/15 3:05:39
  4. GitHub中的license选择问题

    https://www.zhihu.com/question/27114031...

    2024/4/18 1:36:06
  5. MySQL相关概念-03

    1、约束 1.1、唯一性约束(unique) * 唯一约束修饰的字段具有唯一性,不能重复。但可以为NULL。 * 案例:给某一列添加uniquedrop table if exists t_user;create table t_user(id int,username varchar(255) unique // 列级约束);insert into t_user values(1,zhangsan);ins…...

    2024/4/24 14:45:29
  6. 小程序微信授权登入 对接客服

    uniapp之小程序微信授权登陆通过button open-type="getPhoneNumber" 触发方法。首先要获取code,根据code获取用户的openid,unionid在方法里定义getPhoneNumber如果需要前端处理code来获取openid和unionid。可以通过以下方式 先在方法util.js文件中定义方法在需要调用…...

    2024/4/24 14:45:27
  7. 拖拽事件--select外边框拖拽

    序:工作中突然接到新需求,管理系统需要嵌入地图,作为前端,我负责出页面,老大说,地图上面的搜索框要可拖拽 但是搜索框是有点击事件的,点击显隐下拉菜单,如果拖拽的事件源选择select框的话,会有样式(十字拖动符cursor:move与selelt默认点击的箭头)冲突 思索良久,就用…...

    2024/4/24 14:45:29
  8. 阿里云 OSS 海思交叉编译

    Git 源码地址: https://github.com/aliyun/aliyun-oss-cpp-sdk 编译参考1: https://github.com/aliyun/aliyun-oss-cpp-sdk/blob/master/README_zh.md 编译参考2: https://help.aliyun.com/document_detail/106216.html?spm=a2c4g.11186623.6.995.23173ecaTQbF7c 下载最新发…...

    2024/4/28 5:22:31
  9. 移动端

    html { font-size: 20px; font-size: 5.33334vw; } @media screen and (max-width:320px){html {font-size: 17.06667px;} } @media screen and (min-width:750px){html {font-size: 40px;} }body {max-width: 750px; margin: auto; }...

    2024/4/24 14:45:28
  10. post请求下载excel文档解决方法

    原文链接:https://blog.csdn.net/Sunny__wei/article/details/70214103post请求无法直接发送请求下载excel文档,是因为我们在后台改变了响应头的内容: Content-Type: application/vnd.ms-excel 导致post请求无法识别这种消息头,导致无法直接下载。解决方法: 改成使用form表…...

    2024/4/26 11:52:55
  11. uni-app微信小程序用户拒绝授权后,重新调起授权页

    我们以地理位置为例// #ifdef MP-WEIXINuni.authorize({scope: scope.userLocation,success(){ //1.1 允许授权uni.getLocation()},fail(){ //1.2 拒绝授权uni.showModal({content:检测到您没打开获取信息功能权限,是否去设置打开?,confirmText: "确认",cancelT…...

    2024/4/24 14:45:22
  12. JavaSE中Object类equals方法

    1、equals方法的源代码? public boolean equals(Object obj){ return (this == obj); } 以上这个方法是Object类的默认实现 2、SUN公司设计equals方法的目的是什么? 以后编程的过程当中,都要通过equals方法判断两个对象是否相等(相当于等于号) equals方法是判断两个对象是…...

    2024/4/24 14:45:21
  13. Java中的数组

    https://www.cnblogs.com/fylong/p/8677804.html Java中的数组...

    2024/4/24 14:45:21
  14. golang之结构体

    指针结构体结构体与数组一样,都是值传递。当把数组或结构体当作实参传给函数的形参时,会赋值一个副本。所以为了提高性能,一般不会直接把数组传递给函数,而是使用切片代替。而把结构体传给函数时,可以使用指针结构体。如果将结构体转给函数,只是复制结构体的副本,如果在…...

    2024/4/24 14:45:21
  15. java基础面试题(Servlet生命周期)

    Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示 Servlet的生命周期包含了下面4个阶段: 1.加载和实例化 2.初始化 3.请求处理 4.服务终止 Web服务器在与客户端交互时Servlet…...

    2024/4/24 14:45:18
  16. 在vue web移动端中使用滑动事件

    滑动事件 touchstart 手指开始滑动的位置 touchmove 手指滑动的位置 touchend 手指离开的位置监听滑动事件 <div @touchstart=touchstart @touchmove=touchmove> </div>touchstart (e) {// 如果你要阻止点击事件,请反注释下一行代码// e.preventDefault()this.sta…...

    2024/4/24 14:45:17
  17. 文件上传和下载的常用测试点

    文件上传: 1.页面页面美观性、易用性(键盘和鼠标的操作、tab跳转的顺序是否正确) 按钮文字正确性 说明文字是否正确 正确/错误的提示文字是否正确 提示当前位置是否正确,并且和其他页面保持一致格式 必填项的标示是否正确2.功能路径是否可以手工输入(手工输入的时候有没有…...

    2024/4/24 14:45:20
  18. 在Linux系统中,编写一个shell脚本进行tomcat的启动,关闭和重启

    在Linux系统中,编写一个shell脚本进行tomcat的启动,关闭和重启 打开Linux虚拟机,新建并编写一个start_app.sh的可执行文件 根据执行start_app.sh时,后面输入的参数:start,stop,restart 分别进行tomcat的启动,关闭和重启。 话不多说,直接上代码 #!/bin/bash #"cd&…...

    2024/4/24 1:19:29
  19. 上下协同,用友IPD的研发管理之道(下)

    建设和运作IPD本身并不是最终的目的,是达成目的的手段。不管何时何境,企业稳定运行与发展自始至终都应该最为关键的。流程的定义与企业的目标、业务模式及企业所处的竞争环境等因素紧密相关。如果企业本身对其业务的内在规律不加以考察的话,所谓最完整的管理体系所能起到的效…...

    2024/4/24 14:45:17
  20. 计算机小白实习记(6.22)

    好久没写写日志了,今天写下。 项目进入测试环节。 之前追溯功能查看要在trace-sql.xml里面写sql语句, 产品条码功能打印条码打印多个我不会写,带我的师傅帮我写的 追溯功能中的搜索订单条码我也不会写,也是带我的师傅帮我写的 产品条码搜索和产品查看是自己独立完成的, 剩…...

    2024/4/24 14:45:13

最新文章

  1. Redis篇:缓存雪崩及解决方案

    1.何为缓存雪崩 缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力。 2.缓存雪崩的解决方案 解决方案&#xff1a; 给不同的Key的TTL添加随机值 利用Redis集群提高服务的可用性 给缓存业务添加降级…...

    2024/4/28 8:02:50
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. javaWeb网上零食销售系统

    1 绪 论 目前&#xff0c;我国的网民数量已经达到7.31亿人&#xff0c;随着互联网购物和互联网支付的普及&#xff0c;使得人类的经济活动进入了一个崭新的时代。淘宝&#xff0c;京东等网络消费平台功能的日益完善&#xff0c;使得人们足不出户就可以得到自己想要的东西。如今…...

    2024/4/27 19:08:10
  4. k8s_入门_kubelet安装

    安装 在大致了解了一些k8s的基本概念之后&#xff0c;我们实际部署一个k8s集群&#xff0c;做进一步的了解 1. 裸机安装 采用三台机器&#xff0c;一台机器为Master&#xff08;控制面板组件&#xff09;两台机器为Node&#xff08;工作节点&#xff09; 机器的准备有两种方式…...

    2024/4/23 6:23:48
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/26 18:09:39
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/28 3:28:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/27 4:00:35
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/27 9:01:45
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/28 1:22:35
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57