- 浏览: 887977 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
小宇宙_WZY:
膜拜一下大神,解决了我一个大问题,非常感谢 orz
【解惑】深入jar包:从jar包中读取资源文件 -
JKL852qaz:
感谢,遇到相同的问题!
【解惑】深入jar包:从jar包中读取资源文件 -
lgh1992314:
为什么java中调用final方法是用invokevirtua ...
【解惑】Java动态绑定机制的内幕 -
鲁曼1991:
说的都有道理,protected只能被同一级包的类所调用
【解惑】真正理解了protected的作用范围 -
鲁曼1991:
...
【总结】String in Java
我们首先来看一段代码:
Integer i=100; Integer j=100; System.out.println(i==j); //true Integer i=200; Integer j=200; System.out.println(i==j); //false
差不多的两段代码,怎么结果完全不同呢。我们分两步来说明这个问题:
首先 Integer i=100; 编译器会自动将int类型常数100包装成Interger,采用的是Integer.valueOf(100); 这个方法。
然后我们看看valueOf(int)这个方法的源代码:
/* * 返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,则 * 通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过 * 缓存经常请求的值而显著提高空间和时间性能。 * @param i an <code>int</code> value. * @return a <tt>Integer</tt> instance representing <tt>i</tt>. * @since 1.5 */ public static Integer valueOf(int i) { final int offset = 128; if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); } /* * IntegerCache内部类 * 其中cache[]数组用于存放从-128到127一共256个整数 */ private static class IntegerCache { private IntegerCache(){} static final Integer cache[] = new Integer[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Integer(i - 128); } }
原来如此,当-128=<i<=127的时候,返回的是IntegerCache中的数组的值;当 i>127 或 i<-128 时,返回的是Integer类对象。 这就好解释:
Integer i=100; Integer j=100; System.out.println(i==j); //(1)
此时的 i=IntegerCache.cache[228],因此 Integer引用i中存储的是cache数组第228号元素的地址。同理j也是同一个cache数组的第228号元素的地址(因为cache是Integer的静态数组,只有一个)。i==j比较的是引用地址,因此相等。
Integer i=200; Integer j=200; System.out.println(i==j); //(2)
此时的 i=new Integer(200); 同样j=new Integer(200) 。两次都在堆中开辟了Integer的对象。i 和 j 中存储的堆得对象地址是完全不同的。i==j 自然不相等了。
那么这样做有什么意义呢? 我们来看看API的解释:
返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例, 则通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能 通过缓存经常请求的值而显著提高空间和时间性能。
假如我们在编程时大量需要值为100的Integer对象,如果只能通过new来创建的话。是不是需要在堆中开辟大量值一样的Integer对象呢!这是相当不划算的。既然如此,Java中的字符串常量池的应用是不是可以提醒我们点什么呢?是的,IntegerCache.cache就相当于这样一个字符串常量池。
当我们需要Integer i=100的时候,直接从cache中取出第[100+128]号元素的地址赋值引用i,再次需要Integer j=100时,还是直接去这个地址赋给j .....
是不是省去了再堆中不停的创建对象的代价了(空间,时间上的消耗都很大)。
评论
这是JAVA的一个享元模式
String也用到了
目的在于,对于经常用的数据,进行缓存,避免平凡的创建,销毁对象所带来的开销
类似于做了一个cach
所以你可以发现
String a = "1";
String b = "1";
第一步就不说了。第二部,会去检查常量池里是否已经有这个了,如果有,就直接让B指向他,否则,创建b,然后放入常量池(所以,常量池应该是随时在更新的,我在想,既然这样,那么这个常量池可以自定义么?改JVM?这样我就可以想缓存自己喜欢的东西,当然是简单的,经常用的,非常小的,毕竟常量池是常驻内存的)
不过,并不是所有String都会这样,也是有个范围的,我记得好像也是-127 -- 128
具体我忘了
如果有错大家给我指出来啊。。。我觉得应该是放常量池里了,但是不敢保证
这是JAVA的一个享元模式
String也用到了
目的在于,对于经常用的数据,进行缓存,避免平凡的创建,销毁对象所带来的开销
类似于做了一个cach
有IDE直接用IDE打开,MyEclipse和NetBean都可以,也可以用开发包的命令。命令我忘了,去网上查查。
NetBean打开不了,我用的是6.5的,是不是还要安装什么插件的?
MyEclipse 6.5 直接把.class文件拖进MyEclipse即可。如果是Eclipse,好像是要插件,但具体是什么我忘了。
有IDE直接用IDE打开,MyEclipse和NetBean都可以,也可以用开发包的命令。命令我忘了,去网上查查。
NetBean打开不了,我用的是6.5的,是不是还要安装什么插件的?
有IDE直接用IDE打开,MyEclipse和NetBean都可以,也可以用开发包的命令。命令我忘了,去网上查查。
==只是比较是否是同一个对象。
如果代码中存在楼主说的情况,只能说是隐藏的问题没有被发现而已。
就如用==比较string一样。
public static void main(String[] args) { Integer a=200; Integer b=200; int c=200; System.out.println("a==c "+(a==c)); System.out.println("b==c "+(b==c)); System.out.println("a==b "+(a==b)); }
请问LZ,对于这段代码的运行结果是:
a==c true b==c true a==b false
既然a和b都是通过Integer新建的对象,而c是在栈中的常量,为什么a、b会和c的地址相等,而a和b的地址又不相等呢?
我绝对大家要学会看.class文件
Integer a=200;
int c=200;
System.out.println("a==c");
被编译器这样编译:
Integer a=Integer.valueOf(200); 这个时候引用a存储的是堆栈中Integer对象的地址 (注意a是对象引用)
int c=200; 编译器把常量200写进常量池,然后栈中的变量c里面存放的就是这个值200 (注意c是变量名)
int temp=a.intValue(); 大家可以去看看intValue()的源代码,实际上编译器并没有temp这样的变量,而直接把intValue()的返回结构压入操作数栈。我这些写实为了大家明白过程(不存在temp的).
System.out.println(temp==c);
大致的过程就是这样
总结一下:
(1) 当把一个整形常量或变量直接赋值给Integer引用时,比如 Integer a=200, 或 int b=200; Integer a=b;
这是编译器会调用Integer.valueOf()方法来自动打包int基本类型。
(2) 当比较一个Integer对象和一个int基本类型变量的时候,编译器会调用Integer对象.intValue()将Integer对象自动拆包,然后比较两个整形变量。
注意编译器给我们做了很多工作,大家不要忘记了他的辛苦。要把它的汗水记得明明白白它的心!
楼主啊,我也想研究class,但是能说一下用什么编辑器打开class文件么?一般的文本编辑器打开都是乱码。难道是看反编译的结果?
public static void main(String[] args) { Integer a=200; Integer b=200; int c=200; System.out.println("a==c "+(a==c)); System.out.println("b==c "+(b==c)); System.out.println("a==b "+(a==b)); }
请问LZ,对于这段代码的运行结果是:
a==c true b==c true a==b false
既然a和b都是通过Integer新建的对象,而c是在栈中的常量,为什么a、b会和c的地址相等,而a和b的地址又不相等呢?
我绝对大家要学会看.class文件
Integer a=200;
int c=200;
System.out.println("a==c");
被编译器这样编译:
Integer a=Integer.valueOf(200); 这个时候引用a存储的是堆栈中Integer对象的地址 (注意a是对象引用)
int c=200; 编译器把常量200写进常量池,然后栈中的变量c里面存放的就是这个值200 (注意c是变量名)
int temp=a.intValue(); 大家可以去看看intValue()的源代码,实际上编译器并没有temp这样的变量,而直接把intValue()的返回结构压入操作数栈。我这些写实为了大家明白过程(不存在temp的).
System.out.println(temp==c);
大致的过程就是这样
总结一下:
(1) 当把一个整形常量或变量直接赋值给Integer引用时,比如 Integer a=200, 或 int b=200; Integer a=b;
这是编译器会调用Integer.valueOf()方法来自动打包int基本类型。
(2) 当比较一个Integer对象和一个int基本类型变量的时候,编译器会调用Integer对象.intValue()将Integer对象自动拆包,然后比较两个整形变量。
注意编译器给我们做了很多工作,大家不要忘记了他的辛苦。要把它的汗水记得明明白白它的心!
分析有二:
一、避免用包装类将基本数据直接赋值。
二、包装类也是对象,因此对象比较应该用equals方法。
public static void main(String[] args) { Integer a=200; Integer b=200; int c=200; System.out.println("a==c "+(a==c)); System.out.println("b==c "+(b==c)); System.out.println("a==b "+(a==b)); }
请问LZ,对于这段代码的运行结果是:
a==c true b==c true a==b false
既然a和b都是通过Integer新建的对象,而c是在栈中的常量,为什么a、b会和c的地址相等,而a和b的地址又不相等呢?
前两个比较应该是进行了自动的装箱与拆箱,
相当于比较的是a.intValue==200和b.intValue==200
所以相等
而第三个比较是比较的两个对象的地址,所以不相等
public static void main(String[] args) { Integer a=200; Integer b=200; int c=200; System.out.println("a==c "+(a==c)); System.out.println("b==c "+(b==c)); System.out.println("a==b "+(a==b)); }
请问LZ,对于这段代码的运行结果是:
a==c true b==c true a==b false
既然a和b都是通过Integer新建的对象,而c是在栈中的常量,为什么a、b会和c的地址相等,而a和b的地址又不相等呢?
个人觉得也有问题,那些数字虽然比一些大数字出现的概率大点,但也占用了那些空间,而且这个依据没有什么说服力!如果想真正提高性能最好还是用基本数据类型
byte值范围大家都知道是-128~127
Byte,Long,Short都有它自己的缓存!
不是为了Byte来的。
byte值范围大家都知道是-128~127
Integer i=Integer.valueOf(100); 这里面没有比值的,全部比地址。Integer i,j永远是引用,i==j 永远比的是地址。
LZ探讨的不是比值和比地址的问题,而是一种小的优化策略。
发表评论
-
NIO
2010-08-05 10:36 0在JDK1.4以前,I/O输入输出处理,我们把它称为旧 ... -
【总结】Java线程同步机制深刻阐述
2010-05-16 10:21 5931全文转载:http://www.iteye ... -
【JDK优化】java.util.Arrays的排序研究
2010-05-12 21:06 9112作者题记:JDK中有很多算法具有优化的闪光点,值得好好研究。 ... -
【总结】Java与字符编码问题详谈
2009-12-30 09:11 9348一、字符集和字符编码方式 计算机只懂得0/1两种信号 ... -
【解惑】 正确理解线程等待和释放(wait/notify)
2009-12-29 13:40 19653对于初学者来说,下面这个例子是一个非常常见的错误。 /** ... -
【解惑】JVM如何理解Java泛型类
2009-12-16 11:08 12223//泛型代码 public class Pair<T& ... -
【解惑】正确的理解this 和 super
2009-12-05 09:46 4413转载: 《无聊 ... -
【解惑】真正理解了protected的作用范围
2009-11-21 18:00 4999一提到访问控 ... -
【总结】String in Java
2009-11-21 17:52 10812作者:每次上网冲杯Java时,都能看到关于String无休无止 ... -
【解惑】真正理解了protected的作用范围
2009-11-16 17:11 585一提到访问控制符protected,即使是初学者 ... -
总结Java标准类库中类型相互转化的方法
2009-11-09 21:57 210组一: ☆ String → byte[ ... -
方法没覆盖住带来的烦恼
2009-11-05 09:18 100Object类是所有类的祖宗,它的equals方法比较的 ... -
【解惑】数组向上转型的陷阱
2009-11-03 11:44 1836问题提出: 有两个类Manager和Em ... -
【总结】java命令解析以及编译器,虚拟机如何定位类
2009-11-01 16:25 5745学Java有些日子了,一直都使用IDE来写程序。这 ... -
【解惑】剖析float型的内存存储和精度丢失问题
2009-10-26 15:10 15822问题提出:12.0f-11.9f=0.10 ... -
【解惑】领略内部类的“内部”
2009-10-19 15:38 3535内部类有两种情况: (1) 在类中定义一个类(私有内部类 ... -
【解惑】深入jar包:从jar包中读取资源文件
2009-10-08 21:13 65420我们常常在代码中读取一些资源文件(比如图片,音乐,文 ... -
【解惑】理解java枚举类型
2009-09-26 09:37 3354枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字e ... -
编写自己的equals方法
2009-09-20 14:18 129在我的《令人头疼的"相等"关 ... -
【解惑】Java类型间的转型
2009-09-11 16:03 5591★ 基本数据类型间的转换 1、Java要做到平台无关 ...
相关推荐
Jenkins 支持jdk1.7+jdk1.8打包,包括兼容组件、maven包,JDK建议用:jdk-8u11-linux-x64、jdk-7u80-linux-x64。 安装前将plugins放到/root/.jenkins/路径下,再启动Jenkins,首次启动跳过安装插件步骤,直接进入...
Inno Setup集成mysql和JDK,将jar包打包成exe,里面有mysql初始化脚本和Java项目启动等脚本,可以直接使用,非常全面。
模拟JDK AWT的事件处理机制模拟JDK AWT的事件处理机制
Jdk7解压打包版本 Jdk7解压打包版本 Jdk7解压打包版本 Jdk7解压打包版本
exe4j jdk1.7=======================================
NULL 博文链接:https://576512181-qq-com.iteye.com/blog/1472422
可以自动配置jdk环境变量及自动切换不懂版本的jdk,方便多套开发环境切换
Jdk6解压打包版本
不会配置jdk环境的朋友有福了,这款工具是目前最好用的jdk环境自动配置工具,安装jdk后一键便能配置
JDK环境变量自动配置工具v1.4.2.25 可以自动配置jdk环境变量,无需手动配置,新手入门、IT运维推荐
NULL 博文链接:https://grey2.iteye.com/blog/1662139
在安装了JDK之后直接运行,即可自动配置环境变量,不用再自己配置。
Jdk8解压打包版本
总是有人让我帮忙配置JDK环境变量,我自己换系统也要配置,觉得很麻烦,今天花了点时间用C#写了个自动配置环境变量的程序,拿出来给大家分享,顺便说下,win10有点蛋疼,path变量不能用%java_home%,只能指定全路径...
重新打包了Mac下的JDK7的安装包,避免了提示macbook安装低版本的jdk,提示“Oracle 的 Java 要求 Mac OS X 10.7.3 或更高版本”的问题
JDK(Java Development Kit)是Sun Microsystems针对Java开发员的产品。自从Java推出以来,JDK已经成为使用最广泛的Java SDK。JDK 是整个Java的核心,包括了Java运行环境、Java工具和Java基础类库。JDK是学好Java的...
一次编译,到处使用,shell实现全自动化下载jdk.不足之处大家可以提出来。谢谢
自己测试通过用nsis实现打包Tomcat JDK MYSQL及应用的程序包;本人上传了“ webapp_Tomcat_JDK_MYSQL.nsi ”有需要的可以下载参考;
java打包,可以将jdk集成进去,而且不用全部打入用什么打什么
jdk8自动安装脚本