OnJava8学习笔记(一)
对象创建
标识符是对对象的引用,为标识符赋值使其指向对象。
对象实例的创建使用new关键字:
String s = new String("asdf"); //创建字符串对象
数据存储
存储数据:
1.寄存器(Registers):寄存器位于CPU内部,是最快的存储区域,但数量有限,所以一般按需分配。(Java没有对寄存器的直接控制权,C/C++有)
2.栈内存(Stack):栈内存在常规内存RAM(随机访问处理器)中,可通过栈指针获得RAM的直接支持,栈指针下移分配内存,上移释放内存,速度仅次于寄存器。由于栈内保存项的生命周期的约束会限制Java程序的灵活性,Java对象保存在堆内存中,栈内存中只存储了一些Java数据。
3.堆内存(Heap):堆内存是一种通用的内存池(也在RAM中),所有的Java对象都存在里面,编译器不需要知道对象必须在堆内存上停留多长时间,因此用堆内存保存数据更灵活。 执行new命令实例化对象时,会自动在堆中进行内存分配。这种灵活性的代价在于分配和清理堆内存的时间较长(现在已经非常快了,无需考虑)。
4.常量存储(Constant storage):常量值通常直接放在程序代码中,因为它们永不改变,如需严格保护可考虑放在ROM(只读存储器)中。
5.非RAM存储(Non-RAM storage):数据完全存在于程序之外,在程序未运行以及脱离程序控制后依然存在。例如:
(1)序列化对象:对象被转化为字节流,通常被发送到另一台机器。
(2)持久化对象:对象被放置在磁盘上,程序终止后数据依然存在。
这两种存储方式都是将对象转存在另一个介质中,并在需要时恢复成常规的基于RAM的对象。Java支持轻量级持久化,而JDBC和Hibernate这些类库为使用数据库存储和检索对象信息提供了更复杂的支持。
基本类型的存储
Java的基本类型不是通过new关键字创建的,通常new出来的对象都保存在堆内存中,这样创建小而简单的变量不划算,所以对基本类型的创建,Java和C/C++一样,使用“自动”变量直接存储值,并保存在栈内存中,因此更加高效。
基本类型的内存占用大小:
所有的数值类型都是有正负号的,boolean类型的大小没有明确规定,通常定义为取字面值“true”或“false”。如果要在堆内存中表示基本类型的数据,就要使用到包装类(各类型的包装类见上图)。
高精度数值
BigInteger 和 BigDemical 类型的数据可以用于高精度的计算,类似于包装类型,但是没有对应的基本类型。
能对int或者float做的运算,对 BigIneger 和 BigDemical也能用,不过不能使用运算符,要用相关的方法。涉及到的计算量更多,运算速度会慢一些。BigInteger 支持任意精度的整数,可用于精确表示任意大小的整数值,同时在运算过程中不会丢失精度。 BigDemical支持任意精度的定点数字,可以用来进行精确的货币计算。
数组的存储
在Java中,数组使用前需要被初始化,并且不能访问数组长度以外的数据(会进行范围检查,产生少量内存开销和时间开销),创建对象数组时,实际上是创建了一个引用数组,并且每个引用的初始值都为 null 。基本类型的数组创建时编译器将数组的内存全部置零来保证初始化。
对象清理
作用域
在C/C++和Java中,作用域由大括号{ }的位置决定。Java的变量只有在其作用域内才可用,但注意以下操作在C/C++中合法,在Java中不可用:
{
int x = 12;
{
int x = 96; //非法,会提示x已被定义过
}
}
对象作用域
Java对象和基本类型有不同的生命周期,当我们使用 new 关键字创建Java对象时,它的生命周期将会超出作用域。
{
String s = new String("a string");
}
// 作用域终点
上例中,引用s在作用域终点就已经结束了,但是,引用s指向的字符串对象依然还在占用内存,在这段代码中,我们无法在这个作用域之后访问这个对象,因为唯一对它的引用s已超出了作用域的范围,在后续内容中会学到在编程中传递和复制对象的引用。只要你需要,new出来的对象会一直存活下去,Java提供垃圾回收机制,垃圾收集器会检查所有new出来的对象并判断哪些不再可达,继而释放内存。有效避免了内存泄漏问题。
类的创建
类型
class ATypeName {
// 这里是类的内部
}
ATypeName a = new ATypeName();
字段
上一篇: Java学习第二节第1章
下一篇: 打印流