Java编程思想经典总结摘录

1.在设计一个系统时,目标应该是找到或创建某些类,其中每个类都有具体的用途,而且既不会太大(包含太多的功能而难以复用),也不会太小(不添加其他功能就无法使用).如果你的设计太过于复杂,通过将现有类拆分为更小的部分而添加更多的对象,通常会很有帮助.

当你一开始设计一个系统时,应该认识到程序开发是一个增量过程,犹如人类学习一样,这一点很重要.程序开发依赖于实验,你可以尽己所能去分享,当当你开始执行一个项目时,你仍然无法知道所有的答案.如果将项目视作是一种有机的,进化着的生命体去培养,而不是打算盖摩天大楼一样快速见效,就会获得更多的成功和更迅速的回馈.(第七章总结)

  2.抽象类和抽象方法非常有用,因为他们可以是类的抽象性明确起来,并告诉用户和编译器怎么使用它们.另外抽象类还是很有用的重构工具,因为他们使得我们可以很容易的将公共方法沿着继承层次结构向上移动.

翻译一下,就是继承一个抽象类时,你明确知道要实现拿些方法,这些方法可能就是继承这个类的理由;另外说它是很有用的重构工具,当你写完很复杂的代码,要回过头来精简代码,提高质量时,你会想到重构一下,这时抽象类能减少改动代码行数(171页)

3.

      接口与工厂:接口是实现多重继承的重要途径,而生成遵循某个接口胡对象胡典型方式就是工厂方法设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象。理论上通过这种方式,我们的代码将完成与接口的实现分离,这就使得我们可以透明地将某个实现替换为另一个实现。(186-187页)

       确定接口是理想选择,因而应该总是选择接口而不是具体的类" ,这其实是一种引诱.当然,对于创建类,几乎在任何时刻.都可以替代为创建一个接口和一个工厂.

       许多人都掉进了这种诱惑的陷阱,只要有可能就去创建接口和工厂.这种逻辑看起来好像是因为需要使用不同的具体实现,因此总是应该添加这种抽象性.这实际上已经变成了一种草率的设计优化.

        任何抽象性都应该是真正的需求而产生的.当必需时,你应该重构接口而不是导出添加额外级别的间接性,并由此带来额外的复杂性.这种额外的复杂性非常显著,如果你让某人去处理这种复杂性,只是因为你意识到由于以防万一而添加了接口,而没有其他更有说服力的原因,那么好吧,如果我碰上了这种事,那么就会质疑此人所作的所有设计了.

        恰当的原则应该是优先选择类而不是接口.从类开始,如果接口的必需性变得非常明确,那么就进行重构.接口是一种重要的工具,但是他们容易被乱用.(第九章总结)

 

4.匿名内部类与正规继承相比有些受限,因为匿名內部类既可以扩展类,也可以实现接口,但是不能两者兼备。而且如果是实现接口,也只能实现一个接口 (199页)

Fields and methods in ordinary inner classes can only be at the outer level of a class, so ordinary inner classes cannot have static data, static fields, or nested classes. However, nested classes can have all of these. (201页英语原文)

 5.内部类和匿名内部类具有相同的行为和能力。既然局部内部类的名字在方法处是不可见的,那为什么我们仍然使用局部内部类而不是匿名内部类呢?唯一的理由是,我们需要一个已命名的构造器,或者是需要重载构造器,而匿名内部类只能用于实例化(215页)。

    所以使用局部内部类而不是匿名内部类的另一个理由就是,需要不止一次使用该内部类创建对象。

第十一章245页

3.像数组一样,List也建立数字索引与对象的关联,因此,数组和List都是排好序的容器.List能够自动扩容.

5.各种Queue以及栈的行为,由linkedList提供支持

6.Map是一种对象和对象关联的设计.HashMap设计用来快速访问;而TreeMap保持"键"始终处于排序状态,所以没有HashMap快.LinkedHashMap保持元素插入的顺序,但是也通过散列提供了快速访问能力

7.Set不接受重复元素.HashSet提供最快的查询速度,而TreeSet保持元素处于排序状态.LinkedHashSet以插入顺序保存元素.

8.新程序中不应该使用过时的Vector HashTable Stack 

 第十二章 278

    过去,我曾坚定地认为"被检查异常"和强静态类型检查对开发健壮的程序是非常有必要

的.但是,我看到的以及我使用一些动态(类型检查)语言的亲身经历告诉我,这些好处实际

上来自于:

    1)不在于编译器是否会强制程序员去处理错误,而是要有一致的使用异常来报告错误的

模型.

    2)不在于什么时候进行检查,而是一定要有类型检查.也就是说,必须强制程序使用正确

的类型,至于这种强制施加于编译时还是运行时,那倒没关系

    此外,减少编译时施加的约束能显著提高程序员的编程效率.事实上,反射和泛型就是用来

补偿静态类型检查所带来的过多限制,在本书很多例子中都会见到这种情形.

281页

总结:

   异常处理的优点之一就是它使得你可以在某处集中精力处理你要解决的问题,而在另一处

处理你编写的这段代码中产生的错误.尽管异常通常被认为是一种工具,使得你可以在运行时

报告错误并从错误中恢复,但是我一直怀疑到底有多少时候"恢复"真正得以实现了,或者能

够得以实行.我认为这种情况少于10%,并且即便达到10%,也只是将栈展开到某个已知的稳

定状态,而并没有实际执行任何种类的恢复性行为.无论这是否正确,我一直相信"报告"功

能是异常的精髓所在.Java坚定的强调将所有的错误都以异常形式报告的这一事实,正是它远

远超过诸如C++这类语言的长处之一,因为在C++这类语言中,需要以大量不同的方式来报告

错误,或者根本就没有提供错误报告的功能.一致的错误报告系统一味着,你再也不必对所写的

每一段代码,都质问自己"错误是否正在成为漏网之鱼?"(只要你没有"吞咽"异常,这是关键所在!)

第十四章

总结(350页)

    面向对象编程语言的目的是让我们在凡是可以使用的地方都使用多态机制,

只有在必需的时候使用RTTI

    然而使用多态机制的方法调用,要求我们拥有基类定义的控制权,因为在你扩展程序时

候,可能会发现基类并未包含我们想要的方法.如果基类来自别人的类,或者由别人控制,这时

候RTTI便是一种解决之道:可继承一个新类,然后添加你需要的方法.在代码的其他地方,可

以检查你自己的特定类型,并调用你自己的方法.这样做不会破坏多态性以及程序的扩展能力,

因为这样添加一个新的类并不需要在程序中搜索SWITCH语句.但如果在程序主题中添加需要的新

特性的代码,就必须使用RTTI来检查你的特定类型.

    如果只是为了某个特定类的利益,而将某个特性放进基类里,这意味着从那个基类派生出

的所有其他子类都带有这些可能无意义的东西.这会使得接口更不清晰,因为我们必须覆盖由

基类继承而来的所有抽象方法,这是很闹人的.例如,考虑一个表示乐器Instrument的类层次

机构.假设我们想清洁管弦乐器中某些乐器残留的口水,一种办法是在基类Instrument中放入

clearSpitValve()方法.但这样做会造成混淆,因为它以为着打击乐器Percussion、弦乐器

Strnged和电子乐器Electronic也需要清洁口水.在这个例子中,RTTI可以提供一种更合理的

解决方案.可以将clearSpitValve()置于适当的特定类中,在这个例子中是Wind(管弦乐).同时,

你可能会发现还有更恰当的解决方法.在这里,就是将prepareInstrument()置于基类中,但是

初次面度这个问题时读者可能看不到这样的解决方案,而误认为必须使用RTTI.

    最后一点,RTTI有时能解决效率问题.也许你的程序漂亮的运行着多态,但其中某个对象

是以极端缺乏效率的方式达到这个目的的.你可以挑出这个类,使用RTTI,并为其编写一段

特别的代码以提高效率.然而必须注意,不要太早地关注程序的效率问题,这是诱人的陷

阱.最好首先让程序运行起来,然后再考虑它的速度,如果要解决效率问题可以使用profiler

    我们已经看到了,由于反射允许更加动态的编程风格.因此它开创了编程的新世界.对有

些人来说,反射的动态特性是一种烦恼,对于已经习惯于静态类型检查的安全性的人来说,你

可以执行一些只能在运行时进行的检查,并用异常来报告检查结构的行为,这本身就是一种错

误的方法.有些人甚至走的更远,他们声称引入运行时异常本身就是一种指示,说明应该避免这种

代码.我发现这种意义的安全是一种错觉,因为总是有些事情是在运行时发生并抛出异常的,

即使是在不包含任何try语句块或异常规格说明的程序中也是如此.因此,我认为一致的错误报

告模型的存在使我们能够通过使用反射编写动态代码.当然,尽力编写能够进行静态检查的代

码是值得的,只要你确实能够这么做.但是我相信动态代码是将java与其他诸如C++这样的语言

区分开的重要工具之一.

你可能感兴趣的:(java基础)