1.数据类型分为:基本类型、引用类型
除了基本类型都是引用类型 类、接口、数组
| Java基本数据类型 | 包装类 |
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
Java中的数据类型在内存的存储原理
(1) 基本数据类型的存储原理:所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,Java语言里面八种数据类型是这种存储模型;
(2) 引用类型的存储原理:引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”(存储对象在内存堆上的地址)是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的;
基本数据类型和引用类型的区别主要在于基本数据类型是分配在栈上的,而引用类型是分配在堆上的
不论是基本数据类型还是引用类型,他们都会先在栈中分配一块内存,对于基本类型来说,这块区域包含的是基本类型的内容;而对于引用类型来说,这块区域包含的是指向真正内容的指针,真正的内容被手动的分配在堆上
判断两个变量是否相等有两种方式:一种是利用 == 运算符,另一种是利用equals方法。
① 比较java基本类型:
比较基本类型只能用"==",不能用"equals",这里的"=="比较的是两个基本类型的值;
② 比较包装类:这里拿Integer,Character 来举例
- 1
- 2 Character a = new Character('A');
- 3 Character b = new Character('A');
- 4
- 5 System.out.println(a == b);
- 6 System.out.println(a.equals(b));
- 7
- 8 Integer i1 = new Integer(10);
- 9 Integer i2 = new Integer(10);
- 10
- 11 System.out.println(i1 == i2);
- 12 System.out.println(i1.equals(i2));
- 输出结果:
-
- false
- true
- false
- true
这边"=="比较的是对象的内存地址,new了两个不同的对象所存放的地址是不一样的,这边的"equals"比较的就是值,这里为什么比较的是值呢,equals里的重写了equals的方法
③ 比较String:
"=="比较的是内存地址,"equals"比较的是值
栈区存引用和基本类型,不能存对象,而堆区存对象。==是比较地址,equals()比较对象内容。
(1) String str1 = "abcd"的实现过程:首先栈区创建str引用,然后在String池(独立于栈和堆而存在,存储不可变量)中寻找其指向的内容为"abcd"的对象,如果String池中没有,则创建一个,然后str指向String池中的对象,如果有,则直接将str1指向"abcd"";如果后来又定义了字符串变量 str2 = "abcd",则直接将str2引用指向String池中已经存在的“abcd”,不再重新创建对象;当str1进行了赋值(str1=“abc”),则str1将不再指向"abcd",而是重新指String池中的"abc",此时如果定义String str3 = "abc",进行str1 == str3操作,返回值为true,因为他们的值一样,地址一样,但是如果内容为"abc"的str1进行了字符串的+连接str1 = str1+"d";此时str1指向的是在堆中新建的内容为"abcd"的对象,即此时进行str1==str2,返回值false,因为地址不一样。
(2) String str3 = new String("abcd")的实现过程:直接在堆中创建对象。如果后来又有String str4 = new String("abcd"),str4不会指向之前的对象,而是重新创建一个对象并指向它,所以如果此时进行str3==str4返回值是false,因为两个对象的地址不一样,如果是str3.equals(str4),返回true,因为内容相同。
④ 比较对象:
这里"=="比较的是内存地址,"equals"比较的也是地址,没有重写equals方法的类都是调用的Object的equals的方法。
3.String、StringBuilder、StringBuffer的区别
相同点:底层都是通过char数组实现的
不同点:
String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的;
StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。
如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。