java中数据存储及比较的思考

本文主要针对java程序中数据存储以及数据之间的比较进行总结,希望能够帮助您对这部分内容有更深的理解。

java.jpg

数据存储

java中数据类型包括基本数据类型和对象类型,以下就两种类型分别进行介绍。

基本数据类型

基本数据类型(bds)一共有八种(4+2+1+1),即(int, long, short, byte)+(double, float)+ boolean + char,具体他们所占字节数以及取值范围这里就不说了。
根据数据角色的不同,可以分为以下两种情况,不同情况下数据的存储位置也有所差异:

  1. 类成员变量
    由于其属于对象的一部分,所以这些bds会随对象一起存储在heap中。
  2. 方法体变量
    在作为方法体变量时,由于其所占空间比较小而且是固定的,不存在动态扩展的问题,所以会被存储到stack中。
    另外需要注意的是,为了节省空间,栈中数据是可以共享的(当然这里指的是线程栈内的数据),比如定义
int a = 1, b = 1;

会首先存储a,然后查找stack中是否存在值为1的区域,有的话将a指向这个区域,没有的话对1进行存储,然后将a指向这个区域;然后存储b,经查找stack已经对1进行存储过了,所以直接将b指向该区域。所以值同为1的a和b两个变量,他们指向的是同一块存储1的stack地址。

对象类型

通常来讲,我们都是通过关键字new来创建一个对象,如

Integer abc = new Integer(10);
User user = new User();

不难理解,这里会首先在stack中定义引用变量abc/user,然后在heap上创建对象,最后将引用变量指向相应的heap上对象。而且定义一个,创建一个,不论对象相同与否。
但也存在特殊情况,主要是针对bds封装而成的类,有Integer、Long、Short、Byte、Double、Float、Boolean和Char。java1.5之后允许通过直接赋值的方式来定义这些类对象,如

Integer abc = 10;

这里涉及到了装箱和拆箱的概念,装箱--把基本类型用它们相应的引用类型包装起来,使其具有对象的性质,int包装成Integer、float包装成Float;拆箱--和装箱相反,将引用类型的对象简化成值类型的数据。当通过上述方式定义一个Integer对象时,会用到装箱,然后执行下面的操作时会用到拆箱。

int test = abc;

此外,还有一个缓存的概念,先看下面的对象定义

Integer a = 10;
Integer b = 10;

当定义a时,进行装箱操作的同时会进行缓存,当定义对象b时会直接将引用b指向值为10的缓存对象,所以这种对象定义方式是与new创建对象有差别的。当然这里的缓存也不是对所有的Integer都进行缓存,默认的缓存范围为-128~127,也就是说取值在这个范围内时才会进行缓存。那么有人会问了,Long、Short等类有没有缓存呢,答案是肯定的,缓存机制如下:

  1. Integer、Long、Short的缓存范围都是-128~127;
  2. Float、Doulbe没有缓存;
  3. Boolean、Byte全部缓存;
  4. Character缓存范围是0~127;

数据存储就暂且说到这里,接下来对数据比较进行介绍,同时分析过程中也在一定程度上对上文某些内容进行了验证。

数据比较

如果说比较两个变量或者对象,你首先想到的方法是什么?这里主要从‘==’和‘equals()’两个方面对数据比较进行分析。
== 是逻辑运算符,比较的是地址,equals() 是对象方法,比较的是取值。

bds比较

bds只能通过==进行比较了,因为没有equals()方法。

int int1 = 10, int2 = 10;
System.out.println("int1 == int2 : " + (int1 == int2));
short short1 = 10, short2 = 10;
System.out.println("short1 == short2 : " + (short1 == short2));
long long1 = 10, long2 = 10;
System.out.println("long1 == long2 : " + (long1 == long2));
float float1 = 10, float2 = 10;
System.out.println("float1 == float2 : " + (float1 == float2));
double double1 = 10.0, double2 = 10.0;
System.out.println("double1 == double2 : " + (double1 == double2));
boolean boolean1 = true, boolean2 = true;
System.out.println("boolean1 == boolean2 : " + (boolean1 == boolean2));
char char1 = 'a', char2 = 'a';
System.out.println("char1 == char2 : " + (char1 == char2));

打印结果如下

int1 == int2 : true
short1 == short2 : true
long1 == long2 : true
float1 == float2 : true
double1 == double2 : true
boolean1 == boolean2 : true
char1 == char2 : true

结果不出我们的意料,都是相等的关系。

对象比较

这里的对象比较,主要是基于Integer、Long、Short、Byte、Double、Float、Boolean和Char这八种bds的包装类,主要从以下几个方面进行分析。

基于new创建对象之比较
Integer Integer1 = new Integer(10), Integer2 = new Integer(10);
System.out.println("Integer1 == Integer2 : " + (Integer1 == Integer2));
System.out.println("Integer1.equals(Integer2) : " + (Integer1.equals(Integer2)));
Short Short1 = new Short("10"), Short2 = new Short("10");
System.out.println("Short1 == Short2 : " + (Short1 == Short2));
System.out.println("Short1.equals(Short2) : " + (Short1.equals(Short2)));
Long Long1 = new Long(10), Long2 = new Long(10);
System.out.println("Long1 == Long2 : " + (Long1 == Long2));
System.out.println("Long1.equals(Long2) : " + (Long1.equals(Long2)));
Float Float1 = new Float(10), Float2 = new Float(10);
System.out.println("Float1 == Float2 : " + (Float1 == Float2));
System.out.println("Float1.equals(Float2) : " + (Float1.equals(Float2)));
Double Double1 = new Double(10.0), Double2 = new Double(10.0);
System.out.println("Double1 == Double2 : " + (Double1 == Double2));
System.out.println("Double1.equals(Double2) : " + (Double1.equals(Double2)));
Boolean Boolean1 = new Boolean(true), Boolean2 = new Boolean(true);
System.out.println("Boolean1 == Boolean2 : " + (Boolean1 == Boolean2));
System.out.println("Boolean1.equals(Boolean2) : " + (Boolean1.equals(Boolean2)));
Character Char1 = new Character('a'), Char2 = new Character('a');
System.out.println("Char1 == Char2 : " + (Char1 == Char2));
System.out.println("Char1.equals(Char2) : " + (Char1.equals(Char2)));

打印结果如下

Integer1 == Integer2 : false
Integer1.equals(Integer2) : true
Short1 == Short2 : false
Short1.equals(Short2) : true
Long1 == Long2 : false
Long1.equals(Long2) : true
Float1 == Float2 : false
Float1.equals(Float2) : true
Double1 == Double2 : false
Double1.equals(Double2) : true
Boolean1 == Boolean2 : false
Boolean1.equals(Boolean2) : true
Char1 == Char2 : false
Char1.equals(Char2) : true

从打印结果可以看到,通过new创建的两个取值相同的对象,通过==比较结果是false,而通过equals()方法比较结果是true。这是由于定义的两个引用指向了heap中不同的对象地址,而==比较的恰恰是地址,equals()方法比较的却是取值,所以就会出现上面的打印结果。

非new创建对象之比较
Integer Integer1 = 10, Integer2 = 10;
System.out.println("Integer1 == Integer2 : " + (Integer1 == Integer2));
System.out.println("Integer1.equals(Integer2) : " + (Integer1.equals(Integer2)));
Integer Integer3 = 128, Integer4 = 128;
System.out.println("Integer3 == Integer4 : " + (Integer3 == Integer4));
System.out.println("Integer3.equals(Integer4) : " + (Integer3.equals(Integer4)));
Short Short1 = new Short("10"), Short2 = new Short("10");
System.out.println("Short1 == Short2 : " + (Short1 == Short2));
System.out.println("Short1.equals(Short2) : " + (Short1.equals(Short2)));
Short Short3 = 128, Short4 = 128;
System.out.println("Short3 == Short4 : " + (Short3 == Short4));
System.out.println("Short3.equals(Short4) : " + (Short3.equals(Short4)));
Long Long1 = new Long(10), Long2 = new Long(10);
System.out.println("Long1 == Long2 : " + (Long1 == Long2));
System.out.println("Long1.equals(Long2) : " + (Long1.equals(Long2)));
Long Long3 = 128L, Long4 = 128L;
System.out.println("Long3 == Long4 : " + (Long3 == Long4));
System.out.println("Long3.equals(Long4) : " + (Long3.equals(Long4)));
Float Float1 = new Float(10), Float2 = new Float(10);
System.out.println("Float1 == Float2 : " + (Float1 == Float2));
System.out.println("Float1.equals(Float2) : " + (Float1.equals(Float2)));
Float Float3 = 10f, Float4 = 10f;
System.out.println("Float3 == Float4 : " + (Float3 == Float4));
System.out.println("Float3.equals(Float4) : " + (Float3.equals(Float4)));
Double Double1 = new Double(10.0), Double2 = new Double(10.0);
System.out.println("Double1 == Double2 : " + (Double1 == Double2));
System.out.println("Double1.equals(Double2) : " + (Double1.equals(Double2)));
Double Double3 = 10.0, Double4 = 10.0;
System.out.println("Double3 == Double4 : " + (Double3 == Double4));
System.out.println("Double3.equals(Double4) : " + (Double3.equals(Double4)));
Boolean Boolean1 = new Boolean(true), Boolean2 = new Boolean(true);
System.out.println("Boolean1 == Boolean2 : " + (Boolean1 == Boolean2));
System.out.println("Boolean1.equals(Boolean2) : " + (Boolean1.equals(Boolean2)));
Boolean Boolean3 = true, Boolean4 = true;System.out.println("Boolean3 == Boolean4 : " + (Boolean3 == Boolean4));
System.out.println("Boolean3.equals(Boolean4) : " + (Boolean3.equals(Boolean4)));
Character Char1 = new Character('a'), Char2 = new Character('a');
System.out.println("Char1 == Char2 : " + (Char1 == Char2));
System.out.println("Char1.equals(Char2) : " + (Char1.equals(Char2)));
Character Char3 = 'a', Char4 = 'a';
System.out.println("Char3 == Char4 : " + (Char3 == Char4));
System.out.println("Char3.equals(Char4) : " + (Char3.equals(Char4)));

打印结果如下

Integer1.equals(Integer2) : true
Integer3 == Integer4 : false
Integer3.equals(Integer4) : true
Short1 == Short2 : false
Short1.equals(Short2) : true
Short3 == Short4 : false
Short3.equals(Short4) : true
Long1 == Long2 : false
Long1.equals(Long2) : true
Long3 == Long4 : false
Long3.equals(Long4) : true
Float1 == Float2 : false
Float1.equals(Float2) : true
Float3 == Float4 : false
Float3.equals(Float4) : true
Double1 == Double2 : false
Double1.equals(Double2) : true
Double3 == Double4 : false
Double3.equals(Double4) : true
Boolean1 == Boolean2 : false
Boolean1.equals(Boolean2) : true
Boolean3 == Boolean4 : true
Boolean3.equals(Boolean4) : true
Char1 == Char2 : false
Char1.equals(Char2) : true
Char3 == Char4 : true
Char3.equals(Char4) : true

从打印结果可以看出,同样的对象定义方式,赋值的大小不一样,==比较的结果是不一样的,而这也正是缓存起作用所致。

结束语

本文主要是针对java中数据的存储以及比较进行了相应的分析,属于比较基础的东西,如果您对某些地方有异议,欢迎留言。

你可能感兴趣的:(java中数据存储及比较的思考)