这篇文章的问题是在java中==与equals的应用-CSDN博客这一篇中衍生出来的。
当我们创建多个相同类型的引用变量,并赋予它们一个相同的常量时,jvm会在常量池中寻找这个常量是否存在,如果存在则会直接指向该地址,如果不存在则会在内存中创建一个新的常量并指向它,但是这个不绝对。
在使用==与equals时他们比较的内容是不一样的,==比较的是变量指向的内存地址,而重写后的equals(封装类都重写了equals)比较的是指向地址的内容。
常用的封装类有Integer,Short,Byte,Long 和 String,Boolean,Character 还有 Float,Double。
分三种颜色是因为给不同封装类进行相同常量赋值时,他们指向内存的地址是有不同的。
Integer,Short,Byte,Long这四种类变量在进行常量赋值时会到常量池去找赋值的常量是否存在,如果存在会执行他们自带的一个方法valueOf(),该方法就很操蛋,这四个都是整形,如果常量值在-128-127之间会直接返回常量池的地址,如果不在这个范围会new一个新的Integer返回(这里我也有个疑问,new的新的包装类应该是放在堆中了,而不再是放在常量池中,不知道这样理解对不对),也就是只要常量在-128-127之间,那么的变量指向的内存地址都一样,否者就不一样。
下面是该方法,我在电脑上Ctrl+点击类 后跳转失败,报错说我jre里面没有找到有关jar包,不清楚为什么,往后再一探究竟先用别人截图糊弄一下。
String,Boolean,Character这三个就没有这么多规矩,常量池有就会直接指向。
Float,Double这两个根据我的少量测试不管赋值什么样的相同常量,地址指向都不一样,由于报错没法查看Float/Double.class文件没法看他的valueOf()方法,目前只能先存疑,往后再继续修改和补充。
下面是一些测试代码:
public static void main(String[] args) {
Integer a=1000;
Integer b=1000;
// Short a=1;
// Short b=1;
// Byte a=1;
// Byte b=1;
// Long a=1l;
// Long b=1l;
// Float a=10.5F;
// Float b=10.5F;
// Double a=10.5d;
// Double b=10.5d;
// String a="1";
// String b="1";
a.valueOf(a);
System.out.println(System.identityHashCode(a));
System.out.println(System.identityHashCode(b));
if(a==b) {
System.out.println("==相等");
}
if(a.equals(b)) {
System.out.println("equals相等");
}
}
---------------------------------------------------------------------------------------------------------------------------------
后续~
首先不能查看jar包里面的源文件是因为缺少反编译器,需要下载后再配置:这两篇结合着看就能搞定。
Eclipse无法查看jar包里的源码解决_eclipse 提示作业在jar中没有源代码-CSDN博客
Eclipse 无法查看第三方jar包文件源代码解决方法_eclipse 没有跳转到对应的jar包-CSDN博客
这是文件下载地址:
jar包下载地址:
JadClipse - Eclipse plugin download | SourceForge.net
jad.exe文件下载地址,选第一个适用于windows9x开头的那个就可以:
我么接下来查看每个封装类的valueOf()方法,就可以真相大白了:
//Double的valueOf()方法
public static Double valueOf(double d)
{
return new Double(d);
}
//String的valueOf()方法
public static String valueOf(Object obj)
{
return obj != null ? obj.toString() : "null";
}
//Short的valueOf()方法
public static Short valueOf(short word0)
{
short word1 = word0;
if(word1 >= -128 && word1 <= 127)
return ShortCache.cache[word1 + 128];
else
return new Short(word0);
}
由此可见Float/Double全部都会new所以变量指向地址一定不会一样
String在常量池找到后不为空就会直接toString(),下面是源码,我是没看明白,也不想深究了,折磨~
public String toString()
{
return (new StringBuilder()).append(getClass().getName()).append("@").append(Integer.toHexString(hashCode())).toString();
}
Short和Integer等的valueOf()方法是一样的和上面叙述相同不再赘述。
写到这里感觉深究这些东西没有什么意义,因为java有垃圾清理机制,不管是常量池还是堆都不用我们管,他们指向地址一不一样对于开发者来说貌似不重要,只要知道==和equals的区别就可以。
参考文章:
Java中打印对象内存地址_java打印内存地址-CSDN博客
JAVA常量池,一篇文章就足够入门了。(含图解)_javaclass常量池-CSDN博客
Java中equals与“==”的区别详解_java == 与equals-CSDN博客
java堆、栈、堆栈,常量池的区别,史上最全总结-腾讯云开发者社区-腾讯云 (tencent.com)