1、万物皆为对象。将对象视为奇特的变量,它可以存储数据,除此之外,你还可以要求它在自身上执行操作。理论上讲,你可以抽取待求解问题的任何概念化构件(狗、建筑物、服务等),将其表示为程序中的对象。
2、程序是对象的集合,它们通过彼此发送消息来告知彼此所要做的。要想请求一个对象,就必须对该对象发送一条请求消息。更具体的说,可以把消息想象成对某个特定对象的方法的调用请求。
3、每个对象都由自己或其他的对象所构成的存储。换句话说,可以通过创建包含现有对象的包的方式来创建新类型的对象(组合)。因此,可以在程序中构件复杂的体系,同时将其复杂性隐藏在对象的简单性背后。
4、每个对象都拥有其类型。按照通常的说法,“每个对象都是某个类的实例”,这个类就是类型的同义词。每个类最重要的区别于其他类的特性就是“可以发送什么样的消息给它”。
5、某一特定类型的所有对象都可以接收接收同样的信息。这是一句意味深长的表述,因为“圆形“类型的对象也可以”几何形“类型的对象,所以一个”圆形“对象必定能够接收发送给”几何形“对象的消息。这意味着可以编写与”几何形“交互并自动处理所有与几何形性质相关的事务代码。这种可替代性是OOP中最强有力的概念之一。
对象具有状态、行为和标识。这意味着每一个对象都可以拥有内部数据(它们给出了该对象的状态)和方法(它们产生的行为),并且每一个对象都可以唯一地与其他对象区分开来,具体来说就是每一个对象在内存中都有一个唯一的地址。
类描述了具有相同特性(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型。
String s;
这里面的s就是引用。
String s= "abc";
这里用到了java语言的一个特性,字符串可以用带引号的文本初始化。通常,必须对对象采用一种更通用的初始化方法。
关于引用,我自己看到过一个很好的解释,对象相当于一个气球,而引用就是气球上的绳子,可以用这个例子去解释很多东西。
在应该使用String值的地方使用了布尔值,布尔值就会自动转换为合适的文本形式。
JAVA允许我们把任何基本数据类型转换成别的基本数据类型,但布尔型除外,后者根本不允许任何类型转换处理。
Java里唯一用到逗号操作符的地方就是for循环的控制表达式。
Banana a = new Banana(), b = new Banana();
a.peel(1);
b.peel(2);
为了能方便使用,面对对象的语法来编写代码-即”发送消息给对象“,编译器做了一些幕后工作。它暗自把”所操作对象的引用“作为第一个参数传递给peel()。所以上述两个方法的调用变成了这样。
a.peel(a,1);
b.peel(b,2);
1、对象可能不被垃圾回收。
2、垃圾回收并不等于析构。
3、垃圾回收只和内存有关。
初始化顺序是先静态对象后非静态对象。
总结一下对象的创建过程,假设有个Dog的类:
1、即使没有显式地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以被成静态方法),或者Dog类的静态方法/静态域首次被访问时,JAVA解释器必须查找类路径,以定位Dog.class文件。
2、然后载入Dog.class(这将创造一个class对象),有关静态初始化的所有动作都会被执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
3、当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4、这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(对数字来说就是0,对布尔型和字符型也相同),而引用则被置成了null。
5、执行所有出现于字段定义处的初始化动作。
6、执行构造器。
控制成员访问权限有两个原因。
1、为了使用户不要碰触那些他们不该触碰的部分,这些部分对于类内部操作是必要的,但是它不属于客户端程序员所需要的接口之一。实现接口和实现分离,简化对类的理解。
2、为了让类库设计者可以更改类的内部工作方式,而不必担心这样会对客户端程序员产生重大影响。访问控制权限控制可以确保不会有任何客户端程序员依赖于某个类的底层实现的任何部分。
复用代码是JAVA众多注目的功能之一。但是想要成为极具革命性的语言,仅能复制代码并加以改变是不够的,它还必须能够做更多的事情。
复用类有两种常见的方式:组合、继承。
组合:只需在新的类中产生现有类的对象。由于新类是由现有类的对象所组成,所以这种方法称为组合。该方法只是复用了现有程序代码的功能,而非它的形式。
继承:它按照现有类的类型来创造新类。无需改变现有类的形式,采用现有类的形式并在其中添加新代码。这种神奇的方式称之为继承,而且编译器可以完成大部分工作。
组合和继承都允许在的新的类中放置子对象,组合是显式地这样做,而继承则是隐式这样做。
组合和继承都允许在新的类中放置子对象,组合是显式地这样做,而继承则是隐式的这样做。组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形。而继承的时候,使用某个现有的类,并开发一个它的特殊版本。
继承另一个重要的特点是支持向上转型。
1、一个永不改变的编译时常量。
2、一个在运行时被初始化的值,而你不希望它改变。
使用final方法的原因有两个,第一个原因是方法锁定,以防任何继承类修改它的含义。第二个原因是效率。当编译器发现一个final方法,就会将针对该方法的所有调用都转为内嵌调用。当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳过插入程序代码这种正常方式而执行方法调用机制(将参数压入栈,跳至方法代码处并执行,然后跳回并清理栈中的参数,处理返回值),并以方法体中的实际代码的副本来替代方法调用。但是最新的虚拟机已经可以探测这些情况了,应该让虚拟机去处理这些事情。
类中所有private方法都隐式的指定为final的。
多态通过分离做什么和怎么做,从另一角度将接口和实现分离开。多态不但能改善代码的组织结构和可读性,还能够创建可扩展的程序。”封装“通过合并特征和行为来创建新的数据类型。”实现隐藏“则通过细节”私有化“把接口和实现分离开。多态作用是消除类型之间的耦合关心。
多态的一个特点就是可以用基类的引用去接受任意导出类类型。而实现这一特点的就是后期动态绑定。将一个方法和调用方联起来被称为绑定。
在程序执行前绑定,被称作前期绑定,java除了static方法和final方法(包括private方法)之外,其他所有方法都是属于后期绑定,后期绑定是在程序运行期间进行绑定。编译器一直不知道对象类型,只到方法被调用,可参考this这个章节。
为了执行后期绑定,Java使用一小段特殊的代码来替代绝对的地址调用。这段代码使用在对象中存储的信息来计算方法体的地址。这样根据这一小段代码的内容,每一个对象都可以有具体不同的行为表现。
构造器有一项特殊的任务:检查对象是否被正确地构造。导出类只能访问它自己的成员,不能访问基类的成员(基类的成员通常是private ),只有基类的构造器才具有恰当的知识和权限来对自己的元素进行初始化。因此必须令所有的构造器都得到调用,否则就不可能正确地构造对象。
顺序
1、调用基类构造器。这个步骤会反复递归下去。
2、按声明的顺序调用成员的初始化方法。
3、调用导出类构造器的主体。