zoukankan      html  css  js  c++  java
  • 【踩坑记录】一个类型错误引发的溢出

    前几天写递归运算时候,报了一个错误--->内存溢出,代码如下:

    /**
    	 * 获取所有乘积为n的小于n的数字,1只能出现一次
    	 * 		n可以拆解成各个小数相乘,每次/ 一个小于n的数字看结果是不是 1
    	 * 		同时验证 % 余数
    	 * 
    	 * @param 
    	 * @return void
    	 * @author kongzhi
    	 * @date 2019年2月26日下午3:28:12
    	 *
    	 */
    	public static void getAllNumber(ArrayList<Long> result, Long targetNum) {
    		if (targetNum == 1) {
    			//contains 用的是 equals比较值  --->
    			if (!result.contains(1L)) {
    				result.add(Long.valueOf(1));
    			}
    			System.out.println(result);
    			return;
    		} else {
    			for (long jj = 1; jj <= targetNum; jj++) {
    				if (targetNum % jj != 0) {
    					continue;
    				}
    				//避免1添加
    				//特别注意下:这里 contains后面必须写 1L,如果ArrayList<Long> 是Long的话,因为会转Object,1 默认对应 Integer
    				if (jj == 1L && result.contains(1)) {
    					continue;
    				}
    				@SuppressWarnings({ "unchecked" })
    				ArrayList<Long> resultNew = (ArrayList<Long>)result.clone();
    				resultNew.add(Long.valueOf(jj));	
    				getAllPlusResult(resultNew, targetNum / jj);
    			}
    		}
    	}
    

      原因出在这里:

    if (jj == 1L && result.contains(1))  
    

      原始整数类型 short int long如果不加标识符,默认是int类型,而ArrayList.contains源码如下:

    /**
         * 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 ? e==null : 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 ? get(i)==null : 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;
        }
    

      而equals的执行如下:

     /**
         * Compares this object to the specified object.  The result is
         * {@code true} if and only if the argument is not
         * {@code null} and is a {@code Long} object that
         * contains the same {@code long} value as this object.
         *
         * @param   obj   the object to compare with.
         * @return  {@code true} if the objects are the same;
         *          {@code false} otherwise.
         */
        public boolean equals(Object obj) {
            if (obj instanceof Long) {
                return value == ((Long)obj).longValue();
            }
            return false;
        }
    

      会先去判断是否是同一种类型,再去比较数值。

      前面说了默认是int类型,自动装箱后变为Integer类型,而递归代码中的为 ArrayList<Long> 所以第一步判断就因为类型不一致而不通过。

      之后会一直循环递归调用直到内存溢出。

  • 相关阅读:
    舒迅:微信商业模式的挑战点
    标签Tag列表的实现
    UITableView下拉更新/上提加载的实现
    一张背景图实现的漂亮黄色CSS菜单
    纯CSS打造漂亮的圆角边界导航
    CSS打造立体按钮式的竖向导航菜单代码
    纯CSS实现蓝色圆角下拉菜单
    用于用户中心或后台左侧的JS折叠菜单
    滑动鼠标放大带阴影的纯CSS菜单
    JavaScript打造超酷很动感的鼠标特效菜单
  • 原文地址:https://www.cnblogs.com/whaleX/p/10446913.html
Copyright © 2011-2022 走看看