Start:第二章
Page:21
Date:20190128,20190201
Title:一切都是对象
一切都被视为对象,因此可采用单一固定的语法。尽管一切都看作对象,但操纵的标识符实际上是对象的一个引用。
你拥有一个引用,但不一定要有一个对象来与它关联。
String str; //创建一个引用,类似于c中的指针。
String str = new String(); // new String()为调用String类的构造器,构造一个对象。创建一个引用str指向刚刚构造出来的对象。
创建引用的时候如果对引用进行操作,会报错,此时实际上没有关联任何的对象。
因此,一种安全的做法是:创建一个引用的同时便进行初始化:String s = "asd";
一旦创建了一个引用,就希望它能与一个新的对象关联。通常用new来实现这一目的。//String str = new ("asd");
下面五个不同的地方可以用于存储数据,解答你的疑问,对象是怎么进行防治安排的,内存是怎么分配的:
1.寄存器
这是最快的存储区,它不同于其他存储区的地方--处理器内部。但是寄存器的数量机器有限,所以寄存器根据需求进行分配。无法直接控制,也不能在程序中感觉到寄存器存在的任何痕迹。
2.堆栈
位于通用RAM(随机访问存储器)中,但通过堆栈指针可以从处理器那里获取直接支持。堆栈指针下移则分配新的内存,上移则释放内存。这是一种快速有效的存储方法,仅次于寄存器。创建程序的时候,java系统必须知道存储在堆栈内所有项的生命周期,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些数据存储在堆栈中---特别是对象的引用,但是java对象并不存储在其中。
3.堆
一种通用的内存池(也在RAM区),用于存放所有的JAVA对象。
堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆里活多长时间。因此,在堆里分配存储有很大的灵活性。当需要一个对象的时候,只需要new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。这种灵活性的代价是:用堆进行存储分配和清理可能比用堆栈进行存储分配需要更多时间。
4.常量存储
常量值通常直接存放在程序代码内部,这样做是安全的,因为他们永远不会被改变。在嵌入式系统中,常量本身回合其他部分隔离开,所以在这种情况下,可以选择将其存放在ROM(只读存储器)中。
5.非RAM存储
如果数据完全存活在程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。两个最简单的例子:流对象和持久化对象。流对象中,对象转化成字节流,通常被发送给另一台机器。在持久化对象中,对象被存放在磁盘上,因此即使程序终止,他们仍然可以保存自己的状态。--将对象转换成可以存储在其他介质上的食物,在需要时可以恢复成常规的,基于RAM的对象。
(RAM,ROM)
RAM:random access memory--随机存储内存(内存)
ROM:read only memory--只读内存(硬盘)
在程序设计中常用的一系列类型需要特殊对待--基本类型。因为new将对象存储在堆中,故用new创建一个对象--特别是晓得,简单的变量,往往不是很有效。java针对这些类型,创建了一个并非是引用的“自动”变量。这个变量直接存储值、并置于堆栈中,因此更加高效。
他们的固定所占存储空间的大小是java比其他大多数语言编写的程序更加具有可移植性的原因之一。
基本类型 大小 最小值 最大值 包装器类型
boolean -- -- -- Boolean
char 16bit(2字节) Unicode o Unicode 2^16 -1 Character
byte 8bit -128 +128 Byte
short 16bit(2字节) -2^15 +2^15 +1 Short
int 32bit -2^31 +2^31 - 1 Int
long 64bit -2^63 +2^63-1 Long
float 32bit IEEE754 IEEE754 Float
double 64bit IEEE754 IEEE754 Double
boolean所占存储空间的大小没有明确指定,今定义为能够取字面值true或false。
基本数据类型都具有包装器类,是的可以再堆中创建一个非基本对象,用来表示对应的基本类型。
JavaSE5的自动拆箱,自动装箱能够转换包装类和基本类型。
高精度数字
BigInteger、BigDecimal。虽然属于包装类的范畴,但是没有对应的基本类型。可以堆这两种类型进行基本的数据操作,但是需要用方法调用的方式取代运算符方式,所以速度会慢下来。(速度和精度的取舍)
BigInteger 支持任何精度的整数。也就是说,在运算中可以准确得表示任何大小的整数而不会丢失任何信息。
BigDecimal支持任何精度的定点数,例如可以把他进行精确的货币计算。
数组
JAVA确保数组会被初始化,且不能在他的范围之外被访问。这种范围检查,是以每个数组上少量的内存开销及运行时的下标检查为代价的。但由此换来的事安全性和效率的提高,这样的付出是值得的。
创建一个数组对象的时候,事实上是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定的值,该值拥有自己的关键字null。一旦Java看到null,就知道这个引用还没有指向某个对象。
在使用任何引用前必须为其指定一个对象,如果试图使用一个null的引用,在运行时会报错。这样可以避免很多在C。C++中常出现的数组错误。
创建用来存放基本数据类型的数组,编译器能确保这种数组的初始化,因为它会将这种数组所占内存全部置零。
作用域
作用域决定了在其内定义的变量名可见性和生命周期。
在作用于里定义的变量只可用于作用于结束之前。
Java是自由格式的语言,空格、制表符、换行都不会影响程序的执行结果。
Java的引用在作用域外将会失效,但对象不会立即删除,而C/C++则需要手动释放空间。在C/C++中如果不释放空间,则会出现对象填满内存空间,进而阻塞程序。Java有一个垃圾回收器,用来监视用new 创建的所有对象,并辨别那些不再被引用的对象,随后释放这些对象的内存空间。
也就是你根本不需要担心内存泄露问题(程序员忘记释放内存导致的)。
方法,参数,返回值
一旦定义一个类,就可以在类中设置两种类型的元素:字段(数据成员)、方法(成员函数)。字段可以使任何类型的对象,可以通过其引用域其进行沟通。
如果一个字段是某个对象的引用,则必须初始化这个引用。
每个对象都有用来存储其字段的空间,普通自断不能在对象间共享。
当某个成员变量是基本数据类型的时候,java会自动初始化。但初始化结果很可能和预期不同,所以使用者应该自己初始化。
boolean(false)、char('\u0000'--null,这里是两个字节)、byte((byte)0)、short((short)0)、int(0)、long(0L)、float(0.0f)、double(0.0d)
如果是在某个局部变量中,则不会初始化。
Java的方法决定了一个对象能够接受什么样的消息。方法的基本组成部分包括:名称、参数、返回值、方法体。方法名和参数列表(总称方法签名)能够唯一的表示出某个方法。
返回类型描述的是在调用方法之后从方法会返回的值。方法只有通过对象才能够调用,切这个对象必须能够执行这个方法调用。试图调用不具备的方法,编译器就会抛出错误。
链式调用通常被称为发送消息给对象。
参数列表
参数列表指定要传送什么信息给方法。,这些信息可以是基本数据类型,也可以是对象。并且传递的数据类型必须正确,否则编译器就会抛出错误。
return 不一定要返回什么数据,可以用于中断方法。
如果方法类型不是void,编译器强制返回一个正确类型的返回值。
为了不和别的同类名的类相冲突,java希望程序员将自己的域名翻转作为包名。
import关键字与*通配符。
static关键字
当下面两种情况的时候,就适合使用static关键字:
只想为某特定域分配但以存储空间,而不去考虑究竟要创建多少个对象,甚至根本不想创建任何对象。
希望某个方法不与包含它的类的任何对象关联在一起--即使不创建对象,也可以调用这个方法。
即使创建了两个类,static关键字修饰的变量也只有一份存储空间。
System.out.println
System是java.lang包的一个类。调用System中的静态对象 PrintStream out。自带的非静态方法println。
println 其实就是print() + newLine();print底层还是调用write方法,write又是调用了Writer类的同步方法write。且write和newLine的内容是同步代码块修饰的。用的是this为同步锁。也就是System.out.println可以看作是一个同步的方法。
javac ClassName.java//编译产生字节码文件
java ClassName//运行
常用文档注释:
@since、@version、@author、@param、@return、@throws、@Deprecated
驼峰编码风格