欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第九本书 Thinking in java (2018第1)

程序员文章站 2023-12-24 10:19:21
...

JAVA编程思想凡二十二章,目标1月看完。

  1. 抽象过程 : OOP根据问题来描述问题,使用UML工具
  2. 每个对象都提供服务——内聚性
  3. private隐藏实现/访问控制 ——低耦合
  4. UML:每个类用一个方框,类名在顶部,成员在中间,方法在底部
  5. 对象都提供接口:Light类方法有on() off()等接口
  6. has-a :汽车有引擎 ; 组合的关系用菱形表示
  7. is-a : 继承用三角形表示;继承会发生新增方法或者覆盖
  8. is-like-a : 子类有父类的接口但还包含其它方法
  9. 多态/动态绑定/延迟绑定: c++ 用virtual 表示 ,java默认实现不用指明 
  10. upcasting: 把子类看作基类
  11. 容器: c++ stl , 从效率上分析ArrayLit 和LinkList 
  12. 向下转型/泛型: ArrayList<Shape> shapes = new ArrayList<Shape>();
  13. 对象存放何处?
  • 栈:自动变量/静态存储区,汇编指令决定效率
  • 堆/内存池:动态管理运行那一刻才决定创建,由存储设计决定效率
  • new : java完全采用了动态内存分配

 

  • 对于栈上创建的对象,编译器可以确定生存时间
  • 堆上创建的对象,编译器无法得知;c++ 由程序员决定, java有垃圾回收器

14. 

异常是一种对象,虽然异常不是OOP特征

异常不能被忽略,要恢复程序运行

 

15. 并发编程:同一时刻处理多个任务的思想;

问题切分为多个可独立运行的部分,彼此独立运行的部分为线程。

共享资源

 

16. java->web

客户端编程

服务端编程

 

过程型语言:页面计算机,数据定义和函数调用

 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

JAVA 标识符是对象的一个引用

String s ; 创建引用
String s = "abcd"; 创建引用同时指向对象
String s = new String("abcd"); 另一种方式

 对象存放何处

寄存器:不能直接控制,而C语言可以建议编译器那样做。
栈:RAM之上,一般JAVA的对象引用
堆:RAM之上的通用内存池。存放JAVA对象。编译器不用知道存储数据存活时间。
常量:程序代码内部
非RAM:流对象和持久化;JAVA对轻量级持久化支持;jdbc hibernet 更加复杂的数据库对象操作。

 基本类型

 

自动变量同C一样,不用new 在堆里,堆里太浪费时间;;而是放在栈中。
java固定每种类型所占空间大小,数值型都有符号,不要尝试寻找无符号数。
java数组的内存开销和下标检查,换来安全性。
创建一个数据对象,实际上创建了引用数组。
数据类型=类
类——字段和方法
基本成员有默认值

方法 : 名称 , 参数 , 返回值, 方法体
方法签名= 名称+参数

 static

只想分配单一存储空间,而不考虑创建多少个对象。
希望某方法不与包含它的类对象关联,可以通过类直接引用(首选)

static main

 java.lang

java.lang 自动导入到每一个java文件中
java.lang.System.out    —— static

System.getProperties().list(out);
System.getProperty("user.name");
System.getProperty(“java.library.path");

 JavaDocs

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

操作符

java是建立 在c/c++之上的

基本类型存储了实际数值

对象赋值实际上复制了引用,结果都指向相同的对象

 

==  !=比较对象的引用。比较对象内容要用eqals; 基本类型仍然用== !=

 

类型转换cast  窄化转换 扩展转换

java允许任何基本数据类型互转

截尾,不会引发警告和异常

 

java没有sizeof

 

无条件分支 return break continue

 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

构造与析构是c/c++的难点

  • 构造器是强制重载方法

重载方法依赖参数表来区分

this关键字 , 暗地发送消息给对象,例如    A.peer(a) => A.peer(A,a);

static 关键字的真正含义:全局

finalize关键字:

(1)对象可能不会被回收

(2)标记之后,下一次回收垃圾时才会被回收(不同于析构)

(3)垃圾回收与内存有关

  • finalize存在的道理是,有类C的方式分配内存

内存引用

引用计数; 引用链;标记-清扫;-停止-复制;

JIT 及时

构造器初始化顺序 :

  • 先初始化所有成员变量,才初始化构造函数 

静态数据初始化:

  • 只在必要时才进行;
  • 只初始化一次;
  • 初始化时先静态对象,再非静态对象

 

  • 构造器方法(可以看作)是静态的
  • (1)加载 Dog.class
  • (2)new Dog() 在堆上分配空间
  • (3)空间被清0,基本类型成员初始化
  • (4)字段定义初始化
  • (5)执行构造器,继承 。
  • 数组的固定成员 length

Array.toString 是java.util标准类库

  • 数组初始化列表最后一个逗号可选的
  • 数组 可作为可变参数列表

printArray(Object...args)

可变参数列表和自动包装和谐共处

java.lang.Integer 包装类

 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

 

访问权限控制:最初的实现并不恰当

public    protected   package -- private 

 

每个编译只单元只能有一个puublic 

package 和import 将单一的全局名字空间分隔开来

 

Java编译器运行:

classpath 包含目录用途查找 class 文件根目录解释器,获取包的名称并把句点换成反斜杠,从classpath根中产生一个路径;

解释器在路径中查找与你要创建class 相关的文件

 

public : 接口访问权限 

类不可以是private T protected (事实上下一章你会发现是可以的)可以是包权限和public

构造可以是private 的用来阻止外部创建

--------------------------------------------------------------------------

--设计模式1 : 单例模式

-------------------------------------------------------------------------------

 

复用类: 使用类而不破坏现有代码(1)组合(2)继承

在何时初始化?

定义的地方

构造器

惰性初始化(用到了再说)

实例初始化

 

构建过程是从基类开始的;如果没有默认的基类构造器,或者想用一个带参的基类构造器,就必须 使用super

 

is-a  继承      has-a 组合

 

 

向上转型:如果 新类必须向上转型,则继承 是必须的,否则慎用继承

final : 编译时常量;

既是static 又是final 通常大写

final = static final  (只有一份, 常量)

 

空白final 声明为final 却又未给初值,

(1)无论何时,编译器都确保空白final  使用前初始化

(2)final域可以根据对象有所不同(构造)却又保持不变的特征

 

final方法(1)不能覆盖(2)效率考虑(大可不必)

final 的应用 : Vector  ArrayList

 

 

 

多态/动态绑定/后期绑定/运行时绑定

数据抽象 +  继承  + 多态

 

封装: 合并特征行为来创建新的类型

实现隐藏: 细节私有化,把接口和实现分开

多态: 消除类型之间的耦合关系

 

c只有前期绑定;java除了final 和static 其它都是后期绑定

多态是一项让程序员把改变的事物与未变的事物分开的技术

private 方法不会覆盖

任何域访问都是由编译器解析(编译期)不是多态的(运行期)

静态方法是与类,而不是对象关联的

 

 -------------------------------------------------------6----------------------------------------------------

接口和内部类:接口与实现分离

包含抽象方法的类叫抽象 类

abstract 重构工具,将公共方法向上移动

接口:极度抽象的类 +允许向上转型的多基类

完全解耦

 

----------------------------

设计模式2 : 策略模式

----------------------------

创建一个能根据所传参数对象的不同而具有不同行为的方法

方法:执行算法中不变的部分

策略:包含变化的部分,就是传递进去的对象,它包含要执行的代码

 

------------------------------

设计模式3:适配器模式

-------------------------------

适配器中代码将接受你拥有的接口,并产生你所需要的接口

 

只要一个方法操作的是类而非接口,那么你只能使用这个类及子类,接口可以放宽这种限制 。

复用代码的第一种方式是:客户端程序员按接口编程

使用接口的核心原因:能够向上转型为多个基类,ii: 防止客户端程序员创建该类对象

 

接口通过extends扩展接口

 

适配器-策略模式-Scanner类

你可以用任何你想要的对象来调用操作的方法;该方法将接受一个同样是你指定的接口)只要你的对象遵循我的接口。

 

java中的多重继承 

放入接口中的任何域都是自动Static  final的 域不是接口的一部分,存放在接口的静态存储区

 

接口与工厂

接口是实现多重继承 的途径;而生成遵循某个接口的欢畅,典型就是工厂方法

------------------------------

设计模式4: 工厂方法

------------------------------------

工厂方法与直接调用的构造器不同,工厂对象上调用的是创建方法,而工厂对象将生成接口的某个实现的对象,将代码与接口的实现分离。将某个实现替换为别一个实现

如果不是工厂方法你的代码必须在某处确切地指明要创建的service类型调用合适的构造。

 

任何抽象类都是应真正需要创建的,当必须应当重构接口,而不是到处添加间接性

优化选择类而不是接口

从类开始,如果接口的需求非常强烈和明确就重构;接口是一种重要的工具,但很容易滥用

 

 

-----------------------------------------------------7---------------------------------------------------------------

 

 

 

第10章内部类

可以将一个类的定义放另一个类的内部.

与组合不同,实现了代码的隐藏

创建内部类-链接到外部类

=============================

设计模式5:  迭代器

通用的容器访问方式, 不关心窗口类型,

轻量级对象, 统一了窗口访问方式

==================================

内部类自动拥有对其外围类所有成员的访问权

.this   .new

必须使用用外部类对象来创建内部类对象,

拥有外部类对象前是不可能创建内部类对象的

内部类对象会暗暗连接到创建它的外部类对象, 但是如果嵌套类(静态内部类)不需要对外部类对象引用 ,

 

内部类与向上转型

在方法和作用(域)内的内部类

  • 实现了某类型的接口,可以创建并返回对象引用
  • 创建一个类来辅助解决方法,但不希望类是公共的

一个定义在方法中的类=局部内部类

一个定义在作用域内的类,作用域在方法内部

一个实现了接口的匿名类

一个匿名类它执行字段初始化

一个匿名类通过实例初始化 实现构造

 

匿名内部类-->工厂方法

单一的工厂对象 Static 域  更有实际意义

 

优先使用的是类而不是接口

如果你的设计中需要某个接口你必须了解它.

 

嵌套类: 如果不需要内部类与外界对象联系, 可将内部类声明为static  通常称为嵌套类

 

  • 普通的内部类保留了外部对象的一个引用
  • 嵌套类不需要外围类对象引用
  • 不能从嵌套类对象中访问非静态外围类对象
  • 嵌套类包括Static

接口内部类 public static

一个内部类被嵌套多少层, 它能透明访问所有它嵌入的外围类的所有成员

 

为什么需要内部类?

内部类提供了某种进入外部类的方法

每个内部类都能独立继承自一个接口的实现

所以无论外围类是否已经继承了某个实现, 对内部类没有影响.

可以继承多个 具体的或抽象的类的能力, 多重继承

  • 内部类可以有多个实例, 每个实例都有自己的状态信息并且与外围类对象状态相互独立
  • 单个外围类中, 可让多个内部类以不同方式实现同一个接口, 或继承同一个类
  • 创建内部类对象的时刻, 不依赖于外围对象
  • 内部类并没有is-a 它就是一个独立的实体

闭包与回调

闭包是一个可调用的对象, 以及一些信息用来创建作用域, 内部类是面向对象的闭包

java的指针功能

 

外围 类实现接口与内部类实现接口区别

创建一个内部类时并不有修改外围类的接口,

接口与接口实现完全独立

内部类实现了接口 ,提供了一个返回的钩子,并且是一个安全的钩子

GUI到外都用回调

 

内部类与控制框架(更多使用内部类的例子)

解决瓿的一个类或一组类

 

=======================================

设计模式6: 模板方法

包含算法的基本结构, 并且调用一个或多个可覆盖方法, 以完成 算法动作

=======================================================

设计模式总是将变化的事物与保持不变的事物分开, 模板方法是保持不变的事件, 可覆盖的方法是变化的.

 

控制框架的完整实现是由单个的类创建 的

从而使实现的细节被封装, 在用来的解决所需要的各个action

内部类很容易访问外围类成员,所以可以避免这种实现变得笨拙,如果没有这种能力会很讨厌

 

===============================================

设计模式7 :命令模式

============================================

继承了某个外围类时, 内部类并没有什么变化

局部内部类: 已命名的构造器需要不止一个内部类对象

匿名类只能用于实例初始化

内部类标识符Count$1.class

C++没有这些概念

 

 

 

 -----------------------------------------------8--------------------------------------------------------

 

 

 

第11章容器

 

这是一种对象持有术

泛型 和类型安全的容器

容器类是用来保存对象的

collection 独立元素序列   list  set queue

Map  键值对  ArrayList   映射表  关联数组

 

List<Apple>   app = new ArrayList<Apple>();

创建时需要精确类型

保用接口的目的在于, 如果你决定了修改实现, 只是在创建处修改, 因此只是创建具体类对象转型为接口

 

java.util   Arrays.asList   数组 ===> List

                Collection.addAll

添加 一组元素的方法

addAll 速度快, 不灵活只接受collection

Arrays.asList 表示数组, 不能调尺寸, 类型限制了

 

窗口打印

 

使用接口描述的一个理由是使我们能够创建更通用的代码, 针对接口而非具体实现

 

Foreach

======================================

设计模式8  适配器

你必须提供特定接口, 满足foreach语句

当你有一个接口并需要另一个时

================================================

 

 

 

  12异常

 

发现错误的理想时间在编译阶段;

 

java异常处理 --- C++  ----Ada

 

使用异常,降低错误代码复杂度

 

如果不使用异常,必须检查指定错误

 

如果使用异常,不必在方法调用处检查异常

 

 

 

Throwable 异常类型的根

 

java.util.logging

 

编译时被强制检查的异常,称为检查的异常

 

 

 

Error

 

Exception  可抛出来的基本类型

 

 

 

不受检查异常 RuntimeException  不用捕获

 

  *
12 通过异常处理错误
发现错误的理想时间是在编译阶段。
:没有未处理的异常
1.
JAVA异常处理机制>C++>Ada
使用异常,降低错误代码处理的复杂度

如果不使用异常, 就必须检查特定的错误.
如果使用了异常,就不必在方法调用处理检查.因为异常将保证捕捉这个错误->异常处理程序中.
把"正常程序中做什么事"和"出了问题怎么办"分离开来

2.基本异常
异常发生了后,他不允许沿着正常的路径走下去.
(1)异常类有2个构造函数:一个默认构造和一个接受字符串参数(这个字符串提取出来有多种方法)
跨越方法调用栈层次
Throwable对象, 异常类型的根类
异常对象中的信息仅有异常类型,

3.捕获异常
try{
}catch(Exception e){
}

终止模型 和恢复模型(耦合大,不适用)

4.创建自定义异常
(1)异常与记录日志
java.util.logging

5.异常说明
throws 潜在异常类型列表

编译时,被强制检查的异常 称为被检查的异常.

6.捕获所有异常
(1)栈轨迹
(2)重新抛出异常
(3)异常链

7.JAVA标准异常
Throwable 类   (1)Error 编译时和系统错误 (2) Exception 可抛出的基本类型
对异常来说,关键是理解概念以及如何使用
不受检查异常 RuntimeException 这类属于错误,不用捕获 

8.使用finally清理
(1)finally作什么 : 除内存之外的资源恢复到初始态,需要清理的资源
(2)异常丢失

9.异常限制
派生类不能捕获基类异常
在继承和覆盖过程中,异常说明的接口不是变大,而是变小了

10.构造器
对于构造器可能异常,最好使用try catch

11.异常匹配

12.
在恰当的级别处理问题
解决问题并重新调用产生异常的方法(向外传递)
少许修补后绕过异常继续执行
农业替代方法预计会返回的值
当前环境下整改尽量做完,把相同异常抛到更高层
把不同异常抛到更高层
终止程序
进行简化 
让类库更安全

 

13章字符串

 

String 对象是不可变的

 

每一个看起来会修改String值的方法,都创建了一个全新的String 传递引用拷贝

 

参数是传递信息的,而不是想让方法改变自己的

 

 

 

java不允许操作员重载操作符

 

 

 

通过反编译比较String效率

 

如果要构造循环,请使用StringBuild 不仅编译的程序更短,且只new一个对象

 

insert  replace substring reverse append toString

 

无意识的递归

 

Super.toString

 

String StringBuild StringBuffer

 

格式化

 

System.out.format    printf     println

 

Java.util.Formatter

 

 

 

格式b 转换:只要参数不是null 结果总是True

 

String.format

 

正则:强大而灵活的文本处理工具

 

简洁  动态  匹配选择  编辑验证

 

 

 

Java.util.regex.Pattern 你应该将这一页加收书签中

 

Java.util.regex.Matter

 

 

 

第十四章 RTTI和反射

 

面向对象编程的基本目的是让代码只操作对基类引用

 

多态是面向对象编程基本目标

 

 

 

动态绑定;泛化;多态;

 

 

 

RTTI 在运行时识别一个对象的类型

 

Class 对象是用来创建类的所有常规对象java使用class 对象来执行RTTI

 

每个类都有一个class 对象,为了生成这个对象, JVM运行使用类加载器子系统

 

只有一个原生类加载器,它是JVM实现的一部分

 

 

 

所有类第一次使用,动态加载JVM

 

对类的静态成员引用,证明构造器

 

JAVA开始运行前,并非完全加载必须加载时才加载这是C++静态加载语言跪舔的技能。

 

 

 

类加载器首先检查这个类的class 对象加载

 

如果未加载默认的类加载器根据类名检查 class 这个类的字节码加载时,它们接受验证,不包含不安全代码。

 

 

 

Class.forName 如果类还没有被加载就加载它

 

 

 

加载查找字节码,创建一个class对象

 

链接验证,静态域分配存储空间

 

初始化如果有超类初始化,静态初始化器,

 

初始化被延迟到了对静态方法(构造器)非常数静态域首次引用才执行。

 

 

 

泛化的class引用

 

Class引用总是指向某个Class对象它可以创建类的实例,表示它所指向的对象确切类型

 

Class添加泛型语法的原因:编译期类型检查

 

 

 

新的转型语法

 

类型转换前先做检查

 

RTTI

 

传统类型转换  经典转换安全向下

 

代表对象的类型的 class对象可获取运行时的信息

 

 

 

使用字面常量

 

instanceOf 动态

 

 

 

递归计数

 

与预加载映射表不同

 

 

 

注册工厂:将对象的创建工作交给类自己去完成;工厂方法可以被多态调用,从而创建恰当类型的对象

 

 

 

协变返回类型

 

 

 

反射:运行时的类信息

 

基于构件的编程架构

 

远程平台上创建和运行对象RMI

 

Class java.lang.reflect

 

Field      get/set 

 

 

 

Method   invoke

 

Constructor  

 

 

 

RTTI vs reflect

 

1.      Rtti 来说,编译器在编译时打开和检查 class

 

2.      Reflect 运行时才打开和检查 class

 

 

 

反射:序列化和javaBean

 

类方法提取器

 

 

 

=========================

 

P8动态代理

 

为了提供额外的或不同的操作,而插入的用来代替实际对象的对象,这些操作通常涉及与实际对象通信,因此,代理充当中间人。

 

 

 

在任何时刻,只要你想将额外的操作从实际对象中分享到不同的地方,特别当你能够很容易作出修改,从没有使用额外操作转为使用这些操作,或反之代理

 

 

 

Java动态代理上所做的让你的要么团都会重定向到单一的调用处理器上

 

 

 

 

 

通过静态方法Proxy.new ProxyInstance 可以创建动态代理;这个方法需要

 

1.      一个类加载器(可以从已被加载的对象中获取然后传递给它)

 

2.      一个希望线程实现的接口列表(不是类,抽象类)

 

3.      invocationHandler接口的一个实现

 

 

 

空对象

 

 

 

接口与类型信息

 

Interface 并没有提供保护

 

对实现使用它包访问权限

 

反编译-反射 

 

Javap –private C

 

 

 

内部类  匿名类

 

没有任何方式可以阻止反射到达并调用那些非公共访问权限的方法

 

 

 

RTTI允许通过匿名基类引用来发现类型信息,但这样在代码开发和维护中损失了多态。

 

OOB的基本目的是凡是可以使用的地方都多态,只要必要使用RTTI

 

不要太早关注效率,要让程序快快运行起来;

 

动态代码是JAVAC++区别之一

 

相关标签: java

上一篇:

下一篇: