一、Java数据类型
分为基本数据类型与引用数据类型
基本数据类型:
- byte:Java中最小的数据类型,在内存中占1个字节(8 bit),取值范围-128~127,默认值0
- short:短整型,2个字节(16 bit),取值范围-2^15~2^15-1,默认值0
- int:整型,用于存储整数,在内存中占4个字节,取值范围-2^31~2^31-1,默认值0
- long:长整型,在内存中占8个字节-2^63~2^63-1,默认值0L
- float:浮点型,在内存中占4个字节,用于存储带小数点的数字(与double的区别在于float类型有效小数点只有6~7位),默认值0
- double:双精度浮点型,用于存储带有小数点的数字,在内存中占8个字节,默认值0
- char:字符型,用于存储单个字符,内存中占2个字节,取值范围0~65535,默认值为空
- boolean:布尔类型,占1个字节,用于判断真或假(仅有两个值,即true、false),默认值false
基本类型转换
- 自动类型转换:当把一个范围小的数值或变量直接赋给另一个范围大的变量时,则这种方式被称为自动类型转换
- 强制类型转换:当把一个范围大的数值或变量赋给另一个范围小的变量时,需要进行强制转换
以上代码会报错,把大范围的数值赋给小范围的变量,需要强制转换,这样才能通过编译,且大范围的数值会丢失精度。
类型转换 & 运算符
小范围数据 与 大范围数据做计算时,会自动提升类型,如图 s+1会自动提升为int型。所以等号右边是int,int直接赋值给short ,所以报错
下图的计算是ok的。
Java中的数据类型在内存的存储原理
- 基本数据类型:所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的栈上的,数据本身的值就是存储在栈空间里面
- 引用类型:引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”(存储对象在内存堆上的地址)是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的
二、java中都是值传递
- 基本数据类型:方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值
- 引用数据类型:也称为传地址。方法调用时,实际参数的引用的拷贝(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象
三、四种引用类型
强引用:
如果一个对象具有强引用,GC绝不会回收它;当内存空间不足,JVM宁愿抛出OutOfMemoryError错误
Object obj = new Object();
软引用:
软引用的强度是仅次于强引用的,如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存
我们可以使用java.lang.ref.SoftReference来创建软引用:
String str=new String("abc"); // 强引用 SoftReference<String> softRef=new SoftReference<String>(str); // 软引用
当内存不足时,等价于
If(JVM.内存不足()) { str = null; // 转换为软引用 System.gc(); // 垃圾回收器进行回收 }
弱引用:
在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象
String str=new String("abc"); WeakReference<String> abcWeakRef = new WeakReference<String>(str); str=null;
如果你想把这个对象变成强引用的话可以使用
String abc = abcWeakRef.get();
应用:jdk中的ThreadLocal
虚引用:
如果一个对象仅持有虚引用,在任何时候都可能被垃圾回收,虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列联合使用,虚引用主要用来跟踪对象 被垃圾回收的活动。
//虚引用 PhantomReference<User> phantomReference=new PhantomReference<User>(new User(),new ReferenceQueue<User>());
四、String
public final class String
继承自java.lang.Object类。
实现了接口:
java.io.Serializable, Comparable<String>, CharSequence
String类是不能被修改的字符串。因为String类里面的数据是final类型的
创建String对象的两种方式:
① String s = "abc";
只在常量池中创建,然后返回对象地址。之后所有“aaaa"都是这个地址。常量池中不能有重复的字符串
② String s = new String("abc");
首先我们要明白两个概念,引用变量和对象,对象一般通过new在堆中创建,s只是一个引用变量。
所有的字符串都是String对象,由于字符串文字的大量使用,java中为了节省时间,在编译阶段,会把字符串文字放在常量池中,常量池的一个好处就是可以把相同的字符串合并,占用一个空间,我们可以用==判断一下两个引用变量是否指向了一个地址即一个对象。
String s = new String("abc")实际上是"abc"本身就是文字池中的一个对象,在运行 new
String()时,把常量池即pool中的字符串"abc"复制到堆中,并把这个对象的应用交给s,所以创建了两个String对象,一个在pool中,一个在堆中。
(java.lang.String的intern()方法s1.intern()方法的返回值还是字符串"abc",表面上看起来好像这个方法没什么用处。但实际上,它做了个小动作:检查字符串池里是否存在"aaaa"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会 把"abc"添加到字符串池中,然后再返回它的引用。
String StringBuffer StringBuilder
String :常量
StringBuffer:线程安全
StringBuilder:线程不安全