java编程思想读书笔记1

经典的书再读一遍,虽然1.8有很多新特性,java12都出来了,但是真的写的不错的书,还是这几本。

一、抽象过程

所有编程语言都提供抽象机制,可以认为,人们能够解决问题的复杂性直接取决于抽象的类型和质量。C、BASIC之类的语言都是对汇编语言的抽象,他们的抽象是基于计算机结构,而不是基于要解决的问题的结构。另一种机器建模的方式就是只针对问题建模,他们针对特定问题是不错的解决方案,但是超出其特定领域,就力不从心了。

面向对象(OOP,Object Oriented Programming 面向对象的程序设计)方式通过向程序员提供问题空间中的元素的工具更进了一步,它不受限于特定问题,只要添加新类型就可以适应某个特定问题。

 

成功的面向对象的五个特性:

(1)万物皆为对象;

(2)程序是对象的集合,他们通过发送消息来告知彼此所要做的;

(3)每个对象都可以拥有其他对象;

(4)每个对象都有类型;

(5)某一类型的所有对象都可以接收同样消息。这种可替代性(substitutability)是一个强有力的概念。

 

二、每个对象都有一个接口

类具有相同的特性(数据元素)和行为(功能),实际上就是一个数据类型。

而接口(interface)类似于定义了类的某些功能。

Unified Modeling Language (UML)又称统一建模语言或标准建模语言。在IDEA中都可以画出来,技术的发展真的是很快的!而spring framework都到了5.0!

三、被隐藏的具体实现

为啥类会用权限控制来隐藏某些细节?因为这样的隐藏可以任意修改被隐藏的部分,而不用担心对其他任何人造成影响。

这也是权限控制存在的原因:

(1)不让客户端程序员访问他们不应该访问的部分;

(2)修改类内部而不用担心影响到客户端程序员;

 

在建立新类的时候首先考虑组合,过多的继承会导致过分复杂的设计。

继承时,子类包括了父类的所有成员(包括private,尽管不能访问)

 

是一个 与 像是一个

继承的关系类似于 is a,继承接口的关系类似于 is like a

 

多态:即父类接口指向子类对象,调用子类的实现。

一个非面向对象语言在调用时会引起所谓的前期绑定,然而在OOP中,程序直到运行时才能确定代码的地址,因此面向对象语言使用了后期绑定的概念。在java中,动态绑定是默认的。

将导出类看做是基类的过程就是 向上转型(upcasting);所以向下转型,就是父类变成子类。

四、单根继承结构

单根继承结构使垃圾回收器的实现变得容易得。

 

怎样才能知道何时销毁这些对象?

C++认为效率控制是最重要的议题,所以给程序员提供了选择的权力。为了追求最大的执行速度,对象的存储空间和 生命周期可以在编写程序时确定。

第二种方法:在堆(heap)的内存池中动态地创建对象。

 

Java完全采用了动态内存分配方式,创建对象时要用new 关键字。

 

五、一切都是对象

 

程序运行时,对象是怎么放置安排的呢?有五个不通的地方可以存储数据:

(1)寄存器;最快的存储区,CPU内部

(2)堆栈;位于通用RAM,但通过堆栈指针可以从处理器那里获得直接支持。Java知道确切生命周期。

堆栈指针向下移动,则分配新的内存;若向上移动,则释放内存。对象引用存放在堆栈,但是Java对象并没有存储在这里。

(3)一种通用的内存池(也位于RAM),用于存放所有的Java对象。编译器不用知道存活多长时间。

(4)常亮存储,通常直接放在程序代码内部。

(5)非RAM存储。如流对象和持久化对象。

 

 

“基本”类型,创建并非是引用的“自动”变量,放置在堆栈中。这种数据类型的大小一般是确定的。

 

高精度类型:BigInteger、BigDecimal

 

import关键字,导入包

static:静态或者类的,实际上就一个特点,同一个类共享这个成员,他们指向同一个存储空间。

 

javadoc是用来提取注释的工具,它输出的是一个html文件。

文档注释的一些标签:

(1)@see 引用其他类

(2){@link package.class#member laber} 与@see极其类似,只是它用于行内

(3){@docRoot} 用来搞路径的

(4){@inheritDoc} 继承的注释

(5)@version 版本信息

(6)@author 作者

(7)@since 最早使用版本

(8)@param 参数说明

(9)@return 返回值

(10)@throws 抛出异常

(11)@deprecated 过时的 被@Deprecated取代

 

六、操作符

引用,注意引用传的是地址

++a a++ 前缀式和后缀式,差别在于++a先自增再赋值,a++先赋值再自增

 

== 与 equals()方法

比较有趣的是"aa" == "aa"

 

短路运算符: && ||

按位操作符:& | ^ ~

移位操作符:<< >> >>>

三元操作符: ? :

 

 

七、控制执行流程

 

foreach语法:

for(val : list)

switch注意一点,default如果没写break,结果也是default后面的语句会运行。

rand.nextInt(26) 里产生的随机数是0~25间的

 

八、初始化与清理

static方法就是没有this 的方法,在static方法内不能调用非静态方法,反过来是可以的

 

关于垃圾回收:

1,对象可能不被垃圾回收;

2,垃圾回收并不等于“析构”;

3,垃圾回收只与内存有关;

 

finalize方法用来对付java语言中的本地方法。

System.gc() 用于强制进行终结动作。

 

垃圾回收器并非基于引用记数技术,它的基本思想是:对任何“活”的对象,一定能追溯到其存活的堆栈或静态存储区之中的引用。这种方式下,Java虚拟机采取一种自适应的回收技术。

静态初始化只有在必要时刻才会进行,没有调用这个类的时候,当然也就不会调用这个类的静态方法了。初始化的顺序也是先静态对象初始化,然后才是非静态对象。

注意:即使没有显示地使用static,构造器实际上也是静态方法。

 

九、访问权限控制

重构即重写代码,以使得它更可读、更易理解,并因此而更具备可维护性。在面向对象编程中需要考虑一个基本问题:“如何把变动的事物与保持不变的事物区分开来”。

Java解释器的运行过程如下:首先,查找系统变量CLASSPATH

 

java的访问权限控制符:public 包访问 protected private

十、复用类

final表示这是无法改变的,无法改变通常出于两种理由:设计或效率。

final在三种情况下可能被用到:数据、方法和类。

1,数据

(1)作为编译时常量;(2)运行时初始化的值,而且不希望改变。

对(1),减轻运行时负担,一个static + final的对象,只占用一段不能改变的存储空间。注意一点,不是说final的值都在运行时就可以知道,比如 final static ran = new Random(37)。

注意final变量必须在定义的地方或者构造方法中进行赋值。

另外,final可以做参数,这样的参数,只可以读,但不能修改。

2,方法

为啥要用final修饰方法?一是锁定方法,继承之后也不能改,二是可以提升效率。为啥final修饰的方法可以提升效率?因为早期的final,可以跳过一些步骤,现在不建议使用了。

final和private,有个有意思的地方,所有private方法隐式都是final。同名也只是新建了一个方法。

3,类

对类而言,final的含义也很好猜,就是不让其他类继承。

 

再次明确一个概念,加载,类的代码只有在第一次使用时才会被加载。

 

十一、多态

多态的作用在于消除类型之间的耦合关系。

Java中除了static和final(private也属于final的一种)之外的方法,都是后期绑定的。这样有个好处,我们和基类打交道就可以了。

多态有一个特殊场景(以后都用sup表示supper父类,sub表示子类),sup和sub都有field,这时候sup.field和sup.getField的多态表现不同,sup.field指向父类的属性,而getField方法指向子类的属性。简单说,父类藏着自己的钱,除非你直接找他,他是不认这个账的。

静态方法也是很有趣的,调用父类的静态方法,不会进行多态表现,这就像总部已经划分好了岗位序列,你在省分也是操作不了的。

构造器是隐式静态的,它会依次生成父类对象,就像基因它是一代代传下来的,要是寻觅你的肤色,就要一代代回溯到祖宗的基因。这个东东,可以在聊天的时候吹一吹,说java类的构造的时候唬一唬小朋友。

要注意多态在销毁对象和调用顺序上可能产生的问题,销毁对象有一点,一般是要先销毁导出类,再销毁基类;调用顺序上,导出类,可能会调用到没有初始化的对象。这就好像顺拐,想走正常路,却走出了搞笑的一路。这个知识点,可能会在查找问题中有用。这就对构造器的初始化有一个要求,尽可能简单,有其他的方法,也采用final形式的。

在书中,对组合的推崇远胜于继承,因为继承会让事情变得更加复杂。然后继承中可以通过字段来表示状态。

多态一般针对的是向上转型,而向下转型通常容易得多,就是打个括号。

 

十二、接口

和接口相关的有抽象类,还有内部类。

interface有个变化,可以有static、default方法。interface的方法默认是public,另外java不允许继承(实现)后的权限变小。

策略设计模式,通过一个对象或者参数控制行为:

 

这个模式,将固定的部分写在方法里,变化的部分通过策略来表现。就像鼠标,按左键或者右键,他们的行为是不一样的。这种模式在跳转过程中可以参照,但是不一定写成类,写成枚举的参数好像更好用。

适配器设计模式,接受所有接口,然后再产生需要的接口。这就像家里电脑的白色转接口,好像一般很少会用到适配器模式,它在重新设计代码时可以用到。

对于接口,很有趣的一句话:接口是没有相关的存储!但是我可以看到接口实际上也是以类的方式存储:

 

java不支持多继承,支持interface的多实现,类似于父亲只能有一个,而亲戚可以有很多个。写接口的时候,可以同时实现几个接口。

对于interface中的域,自动是static、final的,因此,在interface中定义的东东就是:

int JANUARY=1

而更加常见的变量定义是enum,没错,这两个的域都是static、final的。

工厂方法,是用来生成实现某接口对象的典型方法。这种方式的好处在于,将接口和实现完全隔离!就像哪个隔着,吃东西的人是不用知道怎么做出来罐头的,只要符合工厂的规范就可以了。这样会有什么好处?当然是你换了一个实现,用户跟不上就没有感知。

 

 

 

 

你可能感兴趣的:(java)