【Java编程思想】一切都是对象

一、用引用操作对象

    在Java中,一切都是对象,但是操作对象的标识符是对象的一个“引用”,这一关系可以理解为电视机与遥控器的关系。我们通过遥控器控制电视机,我们在房间里不管在哪都可以使用遥控器操作电视机。同时,遥控器又可以独立存在,即引用可以独立存在,有如下代码:

1
String s;

    上一行代码仅仅是创建了一个引用,而并非是一个对象。如果此时我们向s发送消息的话,将报出运行时异常的错误。因为前文讲到Java中消息的传递是建立在对象之间来完成的。因此我们需要在建立引用的时候对其进行初始化,使其指向一个对象:

1
String s = "abc"

    这里使用了Java语言的特性,字符串可以使用引号引起来用来进行初始化操作。

二、必须由你创建所有的对象

    我们创建了一个操作对象的引用,通常希望它与一个对象相关联,以便我们可以进行消息的传递,完成业务功能。Java语言中使用new关键字来完成这个操作,它的含义是“给我创建一个对象与我的引用关联”。所以上述代码可以改为:

1
String s = new String(abc");

    它表示为给我一个String类型的对象,并且初始化为“abc”。

    当我们创建好对象时,他们是怎么样进行内存分配的呢?程序在计算机中有如下五个地方可以分配内存:

    1.寄存器:这是最快的存储区,他在处理器的内部,并且数量非常有限。因此它是根据需求进行分配,你基本不能自己控制他的分配。

    2.堆栈:位于通用(RAM)随机存储器中,通过堆栈指针的移动进行内存分配,速度仅次于寄存器。在堆栈中分配内存空间的项,Java系统必须明确知道其声明周期,以便更好地进行指针的移动。这也从一定程度上进行了限制,因此Java中,对象的引用存在堆栈中,但是对象并不存在堆栈中。

    3.堆:一种同样存放在RAM的内存池,存放Java中所有的对象,且不需要知道其声明周期。是Java程序中主要的内存分配区域,只需要new关键字即可获得内存,但这种效率要比在堆栈上低很多。

    4.常量存储:常量池通常存在程序代码内部,这样使得他们永远不会被改变。在部分嵌入式系统中,常量本身会与其它部分分离,这种情况通常将常量存在(ROM)只读存储器中。

    5.非RAM存储:数据可以完全脱离程序存储在外部,从而不受程序的控制。比如文件流对象和持久化对象,文件流通常发给另外一台机器,而持久化对象则通常是存储在硬盘中。

    Java中有一种特殊的类型称作是基本类型,通常情况下,new将对象存储在堆里,当创建一个简单的小的对象时,显得不是很有效,因此Java采用跟C或者C++相同的方式,不用new创建变量,而创建一个并非是引用的自动变量,这个变量直接存储值,并将其存储在堆栈中。与其他语言不同的是,Java中所有的基本类型的大小在各个平台都相同,这使得Java程序有更好的跨平台移植性。

png1

    所有的数值类型都有正负号,所以Java中不存在无符号类型。基本类型具有包装器类,使得可以在堆中创建一个非基本对象,用来表示对应的基本类型。例如:

1
2
char c = ‘x’;
Character ch = new Character(c);

也可以这样用:

1
Character ch = new Character(‘x’);

Java SE5的自动包装功能可以自动的将基本类型转换为包装器类型:

1
Character ch = ‘x’;

也可以反向转换:

1
char c = ch;

    Java中还提供了两个用于高精度计算的类:BigInteger和BigDecimal,他们大体属于“包装器类”,但是他们没有对应的基本类型,不过可以通过方法调用的方式与int 和 float进行交互操作。BigInteger支持任意精度的整数,BigDecimal支持任意精度的浮点数。

    Java与其他语言一样都提供了数组的功能,不同的是,Java语言保证了数组的安全性,会确保数组被初始化才使用,不会出现其他语言中的访问没有被初始化的内存区域。当创建了一个数组对象时,实际上就创建了一个引用数组,并且每个引用会自动初始化一个特定的值,该值拥有自己的关键字null,一旦Java看到了null,就知道这个引用还有指向对象,也就是没有被初始化。这个过程称为下标检查。

三、永远不需要销毁对象

    Java语言与其它语言一样都有作用域的概念,作用域决定了定义在其内部的变量的可见性和生命周期。作用域使用一对花括号表示。这里需要注意的是,Java对象与其它基本类型不同,它可以存活于作用域外部,如:

1
2
3
{
String s = new String("x");
}

    引用s在作用域结束时就已经失去了意义,但是String对象仍然存活,只是我们暂时无法使用它。因为它的唯一引用已经超出了范围。后面会讲程序的执行过程,如何传递和复制引用。Java中只要你需要,对象会一直存在,Java与其它语言不同的是自带了垃圾回收机制,会自动识别不需要的对象进行回收以达到释放内存的目的。因此你无需担心忘了释放对象的内存。

四、创建新的数据类型:类

    前文说到,同一种对象的集合我们称作是类,类表示所有由它实例化的对象都有相同的基本属性。Java中使用class关键字创建类,class后跟类的名字。这里不存在类似先有鸡还是先有蛋的问题,对象是一系列集合中的一个具体实例,也就是对象是一个类的具体实例化,因此在创建对象之前,一定先存在了这个对象所属的类:

1
class Students{}

如上我们定义了一个新的类,它是一个空类,没有属性也没有方法,所以还不能传递消息。但是我们可以用它实例化一个对象了:

1
Students student = new Student();

    类中有两种数据类型,一种是字段属性,另一种是方法。字段用来表示这个类的一些属性,方法用来表示这个类的一些行为,可以做哪些事情。每个对象都有存储字段的空间,并且类内部的普通属性的字段不可以共享。我们定义如下字段属性:

1
2
3
4
5
class Students{
int i;
double j;
boolean k;
}

    定义好了字段属性之后就可以创建一个对象,并通过对象引用操作对象内的字段属性,使用对象引用“.”方法的形式为对象内的字段属性赋值:

1
2
3
4
Students student = new Students();
student.i=1;
student.j=1.1;
student.k=true;

    Java会为类中的基本类型成员提供一个默认的初始值,以确保可以有效的初始化,防止程序运行出错。如果这个初始值不符合业务要求,那么需要开发者自行初始化。如果不是类中的基本类型数据变量,那么它的初始值就是随机的。

png2

五、方法、参数和返回值

    Java类中的方法决定了能做哪些事情,传递哪些消息。方法的组成包括:名称、参数、返回值和方法体,其基本形式如下:

1
2
3
ReturnType methodName(Arg arg){
/*Method Body*/
}

其中ReturuType是方法返回给调用方的返回值类型,methodName是方法名,Arg是参数类型,arg是参数,注释中的是方法要做的事情。

    Java中对象的调用同样是通过对象引用“.”方法名来完成的。并且要保证这个对象可以执行这个方法,否则编译器会提示错误:

1
2
objectName.methodName(arg,arg1,arg2);
ReturnType x = obejctName.methodName(arg,arg1,arg2);

如上分别是有返回值和无返回值的调用方式。

六、构建一个Java程序

    Java中为了解决命名冲突的问题,采用了分包的形式。将相同类型,或者相同作用,相同业务场景的类放在一个包中,不同的包彼此隔离,并且不同包中可以出现同名的类。使用import关键字导入相关的包即可访问对应包中的类,若导入后出现同名的类,则需要指明对应类的包名。通常情况下,我们必须创建一个类的实例对象来访问类中的属性和方法,而有一种特殊的情况,就是当被static修饰的属性和方法时,不需要对象进行访问。直接使用类名.属性/方法的形式进行访问。也就是说,这个属性和方法属于这个类了:

1
2
3
class TestStatic(){
static int i = 4;
}

    现在即使我们创建两个对象,对于属性i仍然只有一个值,也就是说这个被static修饰了的域变成了一个公共的属性。不同对象之间共享同一个变量。

1
2
TestStatic ts1 = new TestStatic();
TestStatic ts2 = new TestStatic();

关于static关键字的作用,下一章详细学习。

七、你的第一个Java程序

1
2
3
4
5
6
import java.util.*
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World");
}
}

    import是导入java.util工具包下的所有类,HelloWorld是类名,类名需要与文件名相同,main方法是程序的入口,虽然这里没有用到参数列表,但是对于main函数来说这是必须的。使用开发工具如Eclipse运行程序即可看到控制台打印“HelloWorld”