JAVA编程思想读书笔记 第一章 对象导论

1.类:

每个类就是一个数据类型,某个类的变量即是该类的对象(实例)。操作这些变量就称为发送消息或请求(发送消息,对象就知道要做什么)

2.对象:

将每个对象都想成一个“服务提供者”。程序本身向用户提供服务,它将通过调用其他对象提供的服务来实现这一目的。

将对象看成是服务提供者还能助于提高对象的内聚性。

内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。)

3.复用与组合:

复用某个类最直接的方式就是使用该类的一个对象。

使用现有类合成了新的类,这种概念叫做组合。如果组合是动态发生的,那么通常被称为聚合

组合常被视为has-a关系

4.继承:

如果只简单的继承一个类而不做任何其他事,这样是没有意义的,要使导出类和基类产生差异,可以直接在导出类添加新方法,或者覆写父类的方法。

5.里氏替代原则和is-a关系:

如果导出类没有添加新方法,则导出类对象可以完全替代一个基类对象,这时基类和导出类的关系就是is-a关系。判断是否继承,就要确定能否用is-a关系来描述类之间的关系

6.is-like-a:

导出类扩展了新接口,添加了新方法,基类无法访问新添加的方法,这种情况下两者的关系就是is-like-a关系,这样导出类替代基类就并不完美了

7.关于多态:

我们总是会通过实例化子类来实例化某个抽象类或接口对象,这其实发生了向上转型。

例如:public interface Animal(){ void eat() ; }

public Cat implements animal{ public void eat(){sysout(“eat fish”) ;}}

public Dog implements animal{ public void eat(){sysout(“eat meat”) ;}}

Animal a1  = new Cat() ;

Animal a2 = new Dog() ;

这么做在编程上为的是参数类型的统一,一个方法所接受的参数类型只要是这个抽象类对象或接口对象,那么他的所有子类对象都能够被接收。在这个方法内,调用该抽象类或接口对象的方法时,实际执行的是这个抽象类或接口的子类中所覆写的方法

void doEat(Animal animal){

animal.eat() ;

}

doEat(a1) ;  //eat fish

doEat(a2) ; //eat meat

利用这种“将导出类型的对象当作其泛化基类的对象”的方法来看待时,可以改善我们的设计,轻松的扩展设计能力。这样会使程序执行子类所覆写的方法,即同一个消息对不同对象有不同的反应。那在程序中是怎么实现的呢?

——答案是面向对象程序设计中,编译器不可能产生传统意义上的函数调用。非面向对象编程的编译器会产生函数调用时会引起前期绑定,即编译器将产生一个具体函数名字的调用,运行时将这个调用解析道将要被执行的函数代码的绝对地址。而在OOP中,程序直到运行时才能确定函数执行代码的地址(即子类覆写的代码的地址),在此之前只会检查传入的基类的类型中是否存在这个函数方法。这就是后期绑定,当对向对象发送消息时,编译器只确保被调用方法的存在,并对调用参数和返回值进行类型检查,但是并不知道具体要执行的代码地址,知道运行时才知道。为了执行后期绑定,java使用一小段代码来替代绝对地址的调用。

8.单根继承:

单根继承能确保所有子类对象都具有某种功能,也可以进行参数的统一。例如所有类都是Object的子类,即Object类型可以接受一切参数,同时,Object中的方法,所有的子类对象都会有。

9.容器:

持有对其他对象引用的对象,List/Map/Set/Queue/树/堆栈等。选用不同的容器根据不同容器提供的不同接口和外部行为,以及不同容器对不同操作具有的不同效率

10.参数化类型(范型):

范型的出现是为了解决向下转型的弊端,它知道自己所保存的对象的类型,不需要向下转型。

11.对象的创建和生命周期

java完全采用了动态内存分配方式,使用new关键字构建对象的动态实例。动态内存分配是在堆(heap)中动态的创建对象,运行时才会创建对象分配内存。但是在堆上创建的对象,编译器对其生命周期一无所知,为此,java有自己的垃圾回收机制(java垃圾回收机制)。

猜你喜欢

转载自blog.csdn.net/weixin_40616523/article/details/85221032