• java变量-未分类


    成员变量和局部变量

    两者定义

    成员变量:类内方法外的变量
    局部变量:方法中的变量

    两者区别

    区别成员变量局部变量
    编写位置不同类内方法外方法内或方法声明上
    内存位置不同堆内存栈内存
    生命周期不同随着对象的存在而存在,随着对象的消失而消失随着方法的调用而存在,随着方法的调用完毕而消失
    初始化值不同有默认的初始值没有默认的初始值,必须先定义,赋值,才能使用

    理解:
    ①类中位置不同。
    局部变量在方法内或方法申明上,方法申明上指的是:定义方法时形参的位置,也就是括号中的变量。

    并发修改异常

    ConcurrentModificationException 异常

    • 软件包是java.util包
    • 该异常类继承自RuntimeException异常
    • 当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常
    • 理解xhj:并发修改异常

    并发修改异常:ConcurrentModificationException 发生问题的案例

    // 29-ListDemo3
    public class ListDemo3 {
        //需求:
        /*
        有一个集合,
        添加三个元素 hello、world、java,
        遍历集合,得到每一个元素,看有没有world这个元素,如果有则添加元素javaee
        * */
        public static void main(String[] args){
            List<String> list = new ArrayList<String>();  分析步骤1
    
            String s1 = "hello";
            String s2 = "world";
            String s3 = "java";
    
            list.add(s1);
            list.add(s2);
            list.add(s3);
    
            //采用for循环的形式遍历集合元素不报错
    /*        for (int i = 0 ; i <list.size() ; i++){
                String s = list.get(i);
                if(s.equals("world")){
                    list.add("javaee");
                }
            }*/
    
            //采用迭代器的形式
            Iterator<String> it = list.iterator();  分析步骤1
            while (it.hasNext()) {
                String s = it.next();
                if(s.equals("world")){
                    list.add("javaee");  分析步骤1
                }
            }
            // 使用迭代器遍历集合元素会报错:ConcurrentModificationException
            System.out.println(list);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    原因分析:采用迭代器出现异常
    主要:采用迭代器的形式,对集合进行add添加元素操作之后,modCount变量的数值会增加,exceptedModCount变量不变,集合对象.next方法获取集合变量的时候会执行checkForComodification()方法,比较modCount和exceptedModCount的数值,不相等会报ConcurrentModificationException异常。

    1 首先是List接口,接着使用接口中定义的两个方法:iterator、add
    public interface List<E> {
    		Iterator<E> iterator();
    		boolean add(E e);
    }
    
    2 最终创建对象,new的是ArrayList这个实现类的对象
    
    public abstract class AbstractList<E>{
    	protected transient int modCount = 0;
    	此变量在AbstractList<E>类中
    }
    
    public class ArrayList<E> extends AbstractList<E>  implements List<E> {
    	ArrayList实现了List这个接口,就需要重写List中的方法,例如:iterator、add
    
       public boolean add(E e) {
           ensureCapacityInternal(size + 1);  //自己测试显示内容
           elementData[size++] = e;
           return true;
           //视频显示内容
           modCount++;
           add(e,elementData,size);
           return true;
       }
    	
    	
       public Iterator<E> iterator() {
            return new Itr();
        }
        private class Itr implements Iterator<E> {
        	int expectedModCount = modCount;
        	/*
        	expectedModCound:预期修改集合的次数
        	modCount:实际修改集合的次数
        	最开始执行时,两者数量相同
        	变量modCount来自AbstractList<E>中,且用protected修饰,则子类可以直接访问到父类的成员变量,所以最开始两个变量的值都是0
        	*/
        	/*
        	在实际代码运行中,
        	 if(s.equals("world")){
                    list.add("javaee");  分析步骤1
                }
             上述代码一旦条件满足,就会执行集合添加元素的操作,
             按照视频内容理解:每执行一次add方法,modCount会自加一,但是expectedModCount变量不变,接着执行next方法就会执行checkForComodification方法判断两者不相同时就会抛出异常。
    */
            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
            final void checkForComodification() {
                if (modCount != expectedModCount)
                // 此处出现问题的原因是 modCount = 修改集合的次数、expectedModCount = 预期修改集合的次数
                    throw new ConcurrentModificationException();
            }
        }
    }
    
    3 分析 抛出异常的原因是it.next()方法执行,又调取checkForComodification()方法出现问题。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    原因分析:采用for循环遍历集合元素不报错分析

    使用for循环遍历,获取元素使用的是集合对象.get方法。
    public class ArrayList<E> extends AbstractList<E> implements List<E> {
        public E get(int index) {
            rangeCheck(index);
            return elementData(index);
        }
        调用get方法并没有对modCount、exceptedModCount变量进行比较,即使更改了modCount变量的值,但是也不影响执行。
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    关于视频和自己练习中add方法不相同问题理解:

    public class ArrayList<E> extends AbstractList<E>  implements List<E> {
    	// ArrayList实现了List这个接口,就需要重写List中的方法,例如:iterator、add
    
    //自己测试显示内容
       public boolean add(E e) {
           ensureCapacityInternal(size + 1);  
           elementData[size++] = e;
           return true;
       }
    分析是否相同:主要通过追述方法具体实现
        private void ensureCapacityInternal(int minCapacity) {
            ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
        }
        private void ensureExplicitCapacity(int minCapacity) {
          modCount++;
          别的没有看懂,但是有关于变量modCount的++
    
          // overflow-conscious code
          if (minCapacity - elementData.length > 0)
              grow(minCapacity);
      }
       private static int calculateCapacity(Object[] elementData, int minCapacity) {
         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
             return Math.max(DEFAULT_CAPACITY, minCapacity);
         }
         return minCapacity;
     }
     //视频显示内容
      public boolean add(E e) {
           modCount++;
           add(e,elementData,size);
           return true;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    并发修改异常解决及分析总结
    并发修改异常:ConcurrentModificationException
    产生原因:迭代器遍历的过程中,通过集合对象修改集合中的元素,比如添加元素(对象.add),造成了迭代器获取元素中判断预期修改值和实际修改值不一致
    解决方法:用for循环遍历,然后用集合对象做对应的操作(对象.get)

  • 相关阅读:
    几种出色的游戏开发艺术技巧
    如何将“龙”插入到富文本编辑器中?
    2022年亚太杯APMCM数学建模大赛E题有多少核弹可以摧毁地球求解全过程文档及程序
    docker-compose安装ES7.14和Kibana7.14(有账号密码)
    基于中间件的密码泛在化保障技术研究
    嵌入式系统的应用与发展
    LeetCode —— 链表
    linux+c语言杂记(二)
    Java从零学起(十一)----LinkedList集合
    Rust 和 ScyllaDB NoSQL:提高性能的 3 种方法
  • 原文地址:https://blog.csdn.net/LXMXHJ/article/details/125514970