BUG1610

[BUG01]

在做hibernate和spring整合的时候,出现如下错误,第一次碰到。

org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [beans.xml]; nested exception is java.lang.IllegalStateException: Context namespace element 'component-scan' and its parser class [org.springframework.context.annotation.ComponentScanBeanDefinitionParser]are only available on JDK 1.5 and higher

重点在后面红色部分。

解决方法一:一级一级往下试JAVA版本,例如JAVA8更改到JAVA7,没准这个BUG就消失了。

解决方法二:JAVA进行版本检查的类是:org.springframework.core.JdkVersion;

参考源代码,建立如下代码

package org.springframework.core;

public abstract class JdkVersion {
    public static final int JAVA_13 = 0;
    public static final int JAVA_14 = 1;
    public static final int JAVA_15 = 2;
    public static final int JAVA_16 = 3;
    public static final int JAVA_17 = 4;
    //下行是增加的代码
    public static final int JAVA_18 = 5;
    private static final String javaVersion = System
            .getProperty("java.version");
    private static final int majorJavaVersion;
    public static String getJavaVersion() {
        return javaVersion;
    }
    public static int getMajorJavaVersion() {
        return majorJavaVersion;
    }
    public static boolean isAtLeastJava14() {
        return true;
    }
    public static boolean isAtLeastJava15() {
        return getMajorJavaVersion() >= 2;
    }
    public static boolean isAtLeastJava16() {
        return getMajorJavaVersion() >= 3;
    }
    static {
        //下行是增加的代码
        if (javaVersion.indexOf("1.8.") != -1) {
            majorJavaVersion = 5;
        }else if (javaVersion.indexOf("1.7.") != -1) {
            majorJavaVersion = 4;
        } else if (javaVersion.indexOf("1.6.") != -1) {
            majorJavaVersion = 3;
        } else if (javaVersion.indexOf("1.5.") != -1) {
            majorJavaVersion = 2;
        } else {
            majorJavaVersion = 1;
        }
    }
}
使用控制台javac或者eclipse编译得到对应JdkVersion.class文件。

找到对应的jar包,如spring.jar。用解压软件解压,替换对应文件就行。

javac如下:



javac运行之后的文件如下:


替换jar包之前的文件:


将JdkVersion.class直接拖入,替换文件得到:

这样BUG就消失了。

[BUG02]

纪录一个非常无语的坏习惯:
        写Java代码的时候,为了Eclipse不报错,我常常先写一个return null;
        比如,在写SpringMVC代码时,写自己的Handler即Controller的时候,
        写到最后忘了改写成return modelAndView,写的还是return null;
        自己调试的时候,总是以为访问不到modelAndView的viewName,乱折腾一大堆。。。诶。。。
同样的原因导致的运行不正常,在很多地方碰到了。。这个习惯得改。。。

[BUG03]

还是Integer的缓存问题;

看代码:

package csdn;

import java.util.Stack;

public class 优快云_两个栈peek的比较 {
	public static void main(String[] args) {
		int[] arr = {-130, -129, -128, -127, -126, 126, 127, 128, 129, 130};
		for (int val : arr) {
			test(val);
		}
	}
	static void test(int pushVal) {
		Stack<Integer> stk1 = new Stack<>();
		Stack<Integer> stk2 = new Stack<>();
		stk1.push(pushVal);
		stk2.push(pushVal);
		int val1 = stk1.peek();
		int val2 = stk2.peek();
		System.out.println(pushVal + "\t弹出之后保存为int再进行比较\t\t" + (val1 == val2));
		System.out.println(pushVal + "\t直接peek再进行比较        \t\t" + (stk1.peek() == stk2.peek()));
	}
}

运行结果如下:

-130	弹出之后保存为int再进行比较		true
-130	直接peek再进行比较        		false
-129	弹出之后保存为int再进行比较		true
-129	直接peek再进行比较        		false
-128	弹出之后保存为int再进行比较		true
-128	直接peek再进行比较        		true
-127	弹出之后保存为int再进行比较		true
-127	直接peek再进行比较        		true
-126	弹出之后保存为int再进行比较		true
-126	直接peek再进行比较        		true
126	弹出之后保存为int再进行比较		true
126	直接peek再进行比较        		true
127	弹出之后保存为int再进行比较		true
127	直接peek再进行比较        		true
128	弹出之后保存为int再进行比较		true
128	直接peek再进行比较        		false
129	弹出之后保存为int再进行比较		true
129	直接peek再进行比较        		false
130	弹出之后保存为int再进行比较		true
130	直接peek再进行比较        		false

原因还是Integer的缓存,看Integer的源代码:

    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

代码里面非常清楚,-128~127封装成Integer之后,对应的是一个对象。

编写,小测试代码如下:

	static void newInteger1() {
		Integer i1 = Integer.valueOf(12);
		Integer i2 = Integer.valueOf(12);
		System.out.println(i1 + "\tInteger.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:" + (i1 == i2));
		i1 = Integer.valueOf(128);
		i2 = Integer.valueOf(128);
		System.out.println(i1 + "\tInteger.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:" + (i1 == i2));
	}

执行结果如下;

12	Integer.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:true
128	Integer.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:false

但是,如果是新建Integer的方法呢?

	static void newInteger2() {
		Integer i1 = new Integer(12);
		Integer i2 = new Integer(12);
		System.out.println(i1 + "\tInteger.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:" + (i1 == i2));
		i1 = new Integer(128);
		i2 = new Integer(128);
		System.out.println(i1 + "\tInteger.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:" + (i1 == i2));
	}

执行结果如下:

12	Integer.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:false
128	Integer.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:false

原因还是看源代码:

    /**
     * Constructs a newly allocated {@code Integer} object that
     * represents the specified {@code int} value.
     *
     * @param   value   the value to be represented by the
     *                  {@code Integer} object.
     */
    public Integer(int value) {
        this.value = value;
    }
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
可以知道,自动装箱是采用类似valueOf的方法,

在使用Integer进行自动装箱的时候,一定要小心。

如果需要进行判断,最好用个int做中间拆箱。

同样存在 缓存的还有

Character:[0-127] new Character[127 + 1];
Short:[-128-127] new Short[-(-128) + 127 + 1];
Long:[-128-127] new Long[-(-128) + 127 + 1];
Float和Double没有缓存


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值