黑马程序员技术交流社区

标题: 一个关于Integer的问题,无意间看到的 [打印本页]

作者: 罗闯    时间: 2012-3-12 15:36
标题: 一个关于Integer的问题,无意间看到的
问题是这样的:
public class Test5 {
        public static void main(String[] args) {
                Integer in = 100;
                Integer in1= 100;
                if(in==in1)
                {
                        System.out.println("in==in1");
                }
                else
                {
                        System.out.println("in!==in1");
                }
        }
}

结果打印的true。

但是


public class Test5 {
        public static void main(String[] args) {
                Integer in = 200;
                Integer in1= 200;
                if(in==in1)
                {
                        System.out.println("in==in1");
                }
                else
                {
                        System.out.println("in!==in1");
                }
        }
}
结果打印的是false

无意间在测试程序的时候遇到的,不明原因因,求指教。

作者: 张希强    时间: 2012-3-12 15:39
这就是享元模式。只要Integer大于128就会是false.
享元模式:将许多小的对象的相同属性提取出来作为新对象的内部属性,将这些小对象不同属性作为外部方法的参数。
 享元模式(英语:Flyweight Pattern)是一种软件设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
  典型的享元模式的例子为文书处理器中以图形结构来表示字符。一个做法是,每个字形有其字型外观, 字模 metrics, 和其它格式资讯,但这会使每个字符就耗用上千字节。取而代之的是,每个字符参照到一个共享字形物件,此物件会被其它有共同特质的字符所分享;只有每个字符(文件中或页面中)的位置才需要另外储存。以下程式用来解释上述的文件例子。这个例子用来解释享元模式利用只载立执行立即小任务所必需的资料,因而减少内存使用量。

作者: 张希强    时间: 2012-3-12 15:41
刚才忘记说了一句话,张老师的java新技术视频里有详细讲解。第11段视频
作者: 段玉超    时间: 2012-3-12 16:52
         其实楼上兄弟想多了,应该还谈不上享元模式,也就是一个类似缓存的东西也可以叫做预加载吧。 我刚开始看到 这个问题也很稀奇,于是刚才看了一下 Integer类的源代码,明白了。其实楼主的结果不是必然的。根据环境的设置不同可以得到不同的结果。
         其实 就是一个缓存, 在Integer 类有一个叫 IntegerCache 的内部类,起负责缓存(预加载) 符合一定规则的 integer 对象 代码如下:
  1. private static class IntegerCache {
  2.         static final int low = -128;
  3.         static final int high;
  4.         static final Integer cache[];

  5.         static {
  6.             // high value may be configured by property
  7.             int h = 127;
  8.             String integerCacheHighPropValue =
  9.                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
  10.             if (integerCacheHighPropValue != null) {
  11.                 int i = parseInt(integerCacheHighPropValue);
  12.                 i = Math.max(i, 127);
  13.                 // Maximum array size is Integer.MAX_VALUE
  14.                 h = Math.min(i, Integer.MAX_VALUE - (-low));
  15.             }
  16.             high = h;

  17.             cache = new Integer[(high - low) + 1];
  18.             int j = low;
  19.             for(int k = 0; k < cache.length; k++)
  20.                 cache[k] = new Integer(j++);
  21.         }

  22.         private IntegerCache() {}
  23.     }
复制代码
特别注意 这一句 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
最终缓存的 数值范围可能是  -128 ~127 (默认的最大值)   -128~Integer.MAX_VALUE-128  和-128 ~ 环境变量 java.lang.Integer.IntegerCache.high  所保存的值。
起逻辑是
如果 环境变量java.lang.Integer.IntegerCache.high 保存的值小于 127 那么 缓存的 就是 -128到127 的值
如果 环境变量java.lang.Integer.IntegerCache.high 保存的值 大于127 小于Integer.MaAX_VALVE - 128  那么 缓存的就是 -128 ~ 环境变量 java.lang.Integer.IntegerCache.high  所保存的值 这个范围的值
如果 环境变量保存的值过大 那么就保存 -128 ~ Integer.MaAX_VALVE - 128 这个范围的值

也就是说 我们可以通过设置环境变量类 设置 缓存的范围,不过 不应把 缓存的值范围设置的过大,显而易见,IntegerCache 与真正的缓存是有差别的,
并不是将一已存在的 数值对象缓存 而是 在第一次加载的时候 就会创建缓存对象。所以不应该把这个值设的过大。
可以通过一下命令是 楼主的 输出结果改变
JAVA -Djava.lang.Integer.IntegerCache.high=300 Test5   
我已经测试过了,你可以试一试。





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2