欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OnJava8学习笔记(一)

程序员文章站 2022-04-03 17:14:30
...

对象创建

标识符是对对象的引用,为标识符赋值使其指向对象。

对象实例的创建使用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++一样,使用“自动”变量直接存储值,并保存在栈内存中,因此更加高效。

基本类型的内存占用大小:

OnJava8学习笔记(一)

所有的数值类型都是有正负号的,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();

字段