BUG1610

来源:互联网 发布:阿里云首席科学家泉州 编辑:程序博客网 时间:2024/06/15 22:01

[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 CSDN_两个栈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再进行比较        true126弹出之后保存为int再进行比较true126直接peek再进行比较        true127弹出之后保存为int再进行比较true127直接peek再进行比较        true128弹出之后保存为int再进行比较true128直接peek再进行比较        false129弹出之后保存为int再进行比较true129直接peek再进行比较        false130弹出之后保存为int再进行比较true130直接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));}

执行结果如下;

12Integer.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:true128Integer.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));}

执行结果如下:

12Integer.valueOf两个对象,直接使用==判断两个对象在内存中是不是一个对象:false128Integer.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没有缓存


















0 0
原创粉丝点击