对象操纵
编程语言都会操纵内存中的元素,在C/C++中,对象的操纵是通过指针来完成的,Java是通过引用完成对象的操纵,个人认为Java的引用实际上就是阉割功能后比较安全的指针。
示例1:
String s;//创建了一个字符串对象引用s,这时直接使用会报错,因为s没有指向任何对象,常用做法是:创建一个引用的同时进行初始化
System.out.println(s.length());//执行报错,控制台打印:java: 可能尚未初始化变量s
示例2:
String s1 = new String("hello world1");
System.out.println(s1); //控制台打印:hello world1
String s2 = "hello world2";
System.out.println(s2); //控制台打印:hello world2
对象创建
通常可以使用new操作符创建对象,new关键字表示创建一个新的对象实例,如示例2所示。
数据存储
内存中5个地方可以存储数据
1.寄存器
最快的存储区域,位于cpu内部,但是数量有限,Java对其没有控制权,也无法在程序中找到寄存器存在的踪迹。
2.栈内存
存于常规内存RAM区域中,栈指针下移分配内存,上移释放内存,速度比寄存器慢,但是高于其他存储方式。Java程序要求必须准确知道栈内保存的所有项的生命周期,这种约束限制程序的灵活性。注:引用存在栈内存,对象存在堆内存。
3.堆内存
也存在RAM区域,是一种通用内存池,Java对象都存在堆内存中,Java不要求知道对象在堆内存的生命周期。清理和分配堆内存比栈内存需要更多时间。
4.常量存储
常量值一般直接写在程序代码中,永远不会变。
5.非RAM存储
数据完全存在于程序之外,在程序未运行以及脱离程序控制后依然存在。两个主要的例子:(1)序列化对象:对象被转换为字节流,通常被发送到另一台机器;(2)持久化对象:对象被放置在磁盘上,即使程序终止,数据依然存在。这些存储的方式都是将对象转存于另一个介质中,并在需要时恢复成常规的、基于 RAM 的对象。Java 为轻量级持久化提供了支持。而诸如 JDBC 和 Hibernate 这些类库为使用数据库存储和检索对象信息提供了更复杂的支持
基本类型的存储
基本数据类型不需要new来创建对象,可以直接赋值,这种变量都存放在栈空间中,常用的基本类型和C语言的变量类型基本相同。
基本类型 | 大小 | 最小值 | 最大值 | 包装类型 |
---|---|---|---|---|
boolean | — | — | — | Boolean |
char | 16 bits | Unicode 0 | Unicode 216 -1 | Character |
byte | 8 bits | -128 | +127 | Byte |
short | 16 bits | - 215 | + 215 -1 | Short |
int | 32 bits | - 231 | + 231 -1 | Integer |
long | 64 bits | - 263 | + 263 -1 | Long |
float | 32 bits | IEEE754 | IEEE754 | Float |
double | 64 bits | IEEE754 | IEEE754 | Double |
void | — | — | — | Void |
基本类型都对应一个包装类型,拥有自动装箱和自动拆箱的特性,如下所示:
示例3:
char c1 = 'a';
Character c2 = c1; //自动装箱,char类型转变为Character类型
Character c3 = 'b'; //自动装箱,char类型转变为Character类型
char c4 = c3; //自动拆箱,Character类型转变为char类型
高精度数值
在 Java 中有两种类型的数据可用于高精度的计算。它们是 BigInteger 和 BigDecimal。BigInteger 支持任意精度的整数。可用于精确表示任意大小的整数值,同时在运算过程中不会丢失精度。 BigDecimal 支持任意精度的定点数字。例如,可用它进行精确的货币计算。这两个类提供的操作虽然可以保证精度,不过速度会下降,在交易系统中是否应该使用这两种类型有待商榷。
数组的存储
个人认为Java中有两种数据,分别为基本类型数组和对象数组。
基本类型数组在创建后如果不初始化,默认会将数组中的元素全部置为0;
创建对象数组时,实际上是创建了一个引用数组,并且每个引用的初始值都为 null 。在使用该数组之前,我们必须为每个引用指定一个对象 。如果我们尝试使用为 null 的引用,则会在运行时报错。因此,在 Java 中就防止了数组操作的常规错误。
对象清理
基本类型作用域
和在 C、 C++ 和相同,Java 中基本类型的作用域是由大括号 {} 的位置决定的。如下所示:
示例4:
{
int a = 12;
{
int a = 22;//非法,编译器会报错
int b = 96;
// a 和 b 变量皆可用
}
// 变量 b 不在作用域内,b不再可用
}
//变量a不在作用域内,a不再可用
对象作用域
Java 对象与基本类型具有不同的生命周期。使用 new 关键字来创建 Java 对象后,它的生命周期将会超出作用域。如下实例所示,引用s在}之后失效,没有主动回收s指向的对象,所对象依然存在于堆内存中,后续由垃圾收集器判断该对象不再被需要后才进行释放。
示例5:
{
String s = new String("hello");
}
类的创建
类型
Java使用 class 关键字类来描述一种新的对象。 通常在 class 关键字的后面的紧跟类的的名称。如下代码示例,引入了一个新的类型ATypeName,通过 new 关键字来创建一个这种类型的对象。
示例6:
class ATypeName {
// 这里是类的内部
}
//创建对象
ATypeName a = new ATypeName();
字段/成员变量
类中存放两种元素:方法和字段,方法其实就是C/C++中的函数,字段大多数时候应该习惯叫做成员变量,个人更喜欢成员变量的叫法。成员变量可以是基本类型,也可以是引用类型,如下所示,
示例7:
class Student {
int num; //学号
int age; //年龄
String name;//姓名
}
//创建学生对象
Student s = new Student();
//对成员变量进行赋值
s.num = 1;
s.age = 18;
s.name = "Tom";
如果成员变量是基本类型,则在类初始化时,这些成员变量会被赋予一个初始值,这些初始值对于程序来说并不一定是合法或者正确的,所以最好始终显式地初始化变量。
基本类型 | 初始值 |
---|---|
boolean | false |
char | \u0000 (null) |
byte | (byte) 0 |
short | (short) 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
方法使用
Java中的方法就是C/C++中的函数,定义形式也和C/C++一样,如下所示。
[返回类型] [方法名](/*参数列表*/){
// 方法体
}
调用对象方法的格式为:[对象引用].[方法名](参数1, 参数2, 参数3,…);
如下所示,在Student类中增加study函数,并进行函数调用。
示例8:
class Student {
int num;
int age;
String name;
void study(){
System.out.println(name + "开始学习");
}
}
//测试study方法
public static void main(String[] args) {
Student s = new Student();
s.name = "Tom";
s.study();
}
//控制台打印结果:Tom开始学习
static关键字
类是对象的外观及行为方式的描述。通常只有在使用 new
创建那个类的对象后,数据存储空间才被分配,对象的方法才能供外界调用。这种方式在两种情况下是不足的。
-
有时你只想为特定字段(注:也称为属性、域)分配一个共享存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建对象。
-
创建一个与此类的任何对象无关的方法。也就是说,即使没有创建对象,也能调用该方法。
static 关键字(从 C++ 采用)就符合上述两点要求。当我们说某个事物是静态时,就意味着该字段或方法不依赖于任何特定的对象实例 。 即使我们从未创建过该类的对象,也可以调用其静态方法或访问其静态字段。相反,对于普通的非静态字段和方法,我们必须要先创建一个对象并使用该对象来访问字段或方法,因为非静态字段和方法必须与特定对象关联。static定义的东西都是类级别的,而非对象级别。但是对象也可以调用static声明的函数和变量,如下所示:
class Student {
int num;
int age;
static String name; //静态函数不能调用非静态成员变量
static void study(){
System.out.println(name + "开始学习");
}
}
//测试study方法
public static void main(String[] args) {
//类名直接引用静态变量/方法是首选方法,强调了静态属性
Student.name = "Tom";
Student.study();
//创建对象后同样可以使用静态变量/方法
Student s = new Student();
s.name = "Lucy";
s.study();
}
控制台打印结果:
Tom开始学习
Lucy开始学习