2016年7月

《Head First Java》知识点整理

这本书看过有一段时间了,因为一直做PHP方向,没有去深入使用Java,所以现在对Java的了解维持在一个能读懂Java语法的程度。毕竟很多书都是拿Java作为代码的主要语言的。但是现在可能去做一些Java相关的开发了,所以把这本书重新温习一下是非常有必要的。


第一章:基本概念
主要介绍了Java的代码是什么样的和控制语句,因为这本书是Head First嘛,所以这方面讲的比较粗略。
第二章:类与对象
众所周知,Java里面只有类和对象(但是不代表一定用了对象的方式去思考)。这一章开始介绍类和对象相关的知识。
第三章:primitive主数据类型和引用
和其他语言类似,Java里面还是没有把基本数据类型直接包装成类,依旧分成了了primitive主数据类型和引用。然后,这一章还讲到了Java数组方面的知识。
第四章:方法操作实例变量
这一章讲到了对象的属性和方法,可以了解一下,还提到了一下变量的比较(==和equals())。
第五章:编写程序
凭借上面几章学习的基本知识,我们可以开始编写程序了。当然,没有泛型&继承&异常,更没有网络&GUI&持久化,我们能写的程序会功能非常简单。但是,这确实是一个完整的Java程序,而且开发流程值得初学者借鉴。


第六章:认识Java的API
本章给我们带来了增强版的程序,用到了Java的类库中一个名为ArrayList的数据结构。然后,自然而然引申到了Java API库的简单介绍。

java.util.ArrayList
取代数组的数据结构,具有非常好的扩展性。

第七章:继承和多态
现在我们需要面对的是面向对象的三大特性之二,剩下的一个在第二章已经讲过了。继承是为了复用产生的特性,多态是继承和接口自然而然引申出来的特性。
第八章:接口和抽象类
因为继承的设计到现在还没有一个统一的答案,Java使用的是单继承多接口的设计思路。抽象类不能实例化,只能用来被继承;接口类似于抽象类。两者区别是抽象类是用来extends(只有一个),接口被用来implements(可以多个);接口里面所有方法都没有实体,抽象类部分方法没有实体。
第九章:构造器和垃圾收集器
构造器算是面向对象的基本配置了。然后我们来看对象什么时候被回收,这边介绍了一种最简单的GC方式:被引用次数为零。
第十章:数字和静态
因为Java都是对象,但是我们会经常需要函数而不是对象,怎么办?只有用对象构筑函数集合,那就是静态方法,除此以外还有静态变量。

java.lang.Math
关于数学的静态函数集合。
java.lang.Interger(Boolean, Character, Byte, Short, Long, Float, Double)
primitive主函数类型的包装库。
java.lang.String
String.format()静态方法可以将数字进行格式化。
java.util.Calendar(Date)
使用Calendar来从操作时间。

第十一章:异常处理
什么情况下使用异常?大多数的书籍对这一点含糊其词。这边主要介绍了Java的异常的语法,还用了一个例子来说明该如何使用。


第十二章 图形用户接口
如何使用Java来构建图形界面程序,然后因为用到了内部类,所以也提及了一下。

javax.swing.*
java.awt.event.*
java.awt.*

第十三章 swing
学习如何使用swing组件来进行布局,以及介绍了swing的几个常用组件。
第十四章 序列化和文件的输入/输出
介绍了Java的序列化反序列化和文件的输入输出相关的内容。

java.io.*

第十五章 网络和线程
主要介绍了Socket连接在客户端和服务端的使用,然后在客户端引申出线程,然后引申出对象锁的概念。

java.net.*
java.lang.thread

第十六章 集合和泛型
主要介绍了多种集合数据类型,不过这边引申了泛型的概念。不过总觉得泛型作为Java非常重要的一部分,放到这边来讲不太好。

java.util.Collections
java.util.HashSet
java.util.TreeSet
java.util.HashMap
java.util.LinkedList
java.util.LinkedHashMap


第十七章 包、jar存档文件和部署
第十八章 远程部署的RMI

Java Servlet&JSP Web开发

最近几周读了《Head First Servlets&JSP》一书,有一些想法,所以想记录下来。
因为自己主要擅长PHP开发,所以会与PHP做对比。

其实Servlet的doPost和doGet等方法非常符合REST这种设计理念,这点不得不佩服Servlet当初的设计者。
Servlet应该叫做应用控制器(application controller),因此没有前端控制器(front controller)。
对比PHP,PHP在非框架开发也是通过应用控制器这种模式进行开发的,与Servlet颇为类似。
但是与PHP不同的是,PHP根本没有REST思想,想怎么命名应用控制器都可以。
Servlet如果设计得当,就会得到符合REST风格的应用控制器。
但是可能性比较小,估计至少90%的项目都和PHP差不多,命名乱成一团。

然后再来看路由,相比于非框架的PHP,访问的地址就是文件名,Servlet的路由和现代框架风格比较相似。
Servlet用了路由来决定URL地址对应的Servlet,在当时确实是一种很现代的思想。
路由只是Servlet配置的一部分,除了路由以外,Servlet的还有很多配置项也都是配置在web.xml文件里面的。
因为毕竟编译语言,写在xml文件里面就免除了重新编译的麻烦。
书中还介绍了一种使用配置文件的数据生成全局对象的方法,但是这种方法产生的对象因为多线程共享,所以可能会有线程安全问题,值得注意。

再来说一下Servlet的官方视图JSP。请牢记,JSP就是一个Servlet,它会执行时编译成Servlet。
本质上来说Servlet采用的这种JSP的方式是这样的:
本来Servlet有一个函数比如叫做render(HttpServletReqeust req, HttpServletResponse res){}。
这个函数里面写了各种out.println("")之类的输出语句,用来构成一个网页。
但是大家有没有发现,这个render函数无法被多个Servlet重用,那么为了视图的重用,怎么办呢?
于是这个函数就被分离出来,形成一个单独的视图Servlet,这个函数内有一个函数类似render函数。
然后控制器Servlet在执行完了之后会把数据添加到req的属性中去,并把req和res传递给视图Servlet。
视图Servlet收到req和res后,就会从req获取数据渲染并传递给res,就是我们看到的网页。
但是视图Servlet写起来太麻烦了,写一个网页相比单纯的HTML要花费太多功夫,怎么办呢?
jSP的设计中想到的方法很简单,那就是先写HTML风格的页面脚本,然后把这个页面脚本编译成Servlet。
一次请求Servlet的处理过程是这样的:
系统会根据你的请求的URL通过路由找到对应的控制器Servlet;
控制器Servlet处理完成后,会把数据设置为Request的属性,然后把请求转发给视图Servlet;
如果视图Servlet没有找到,只有JSP文件,那么就会把JSP编译成视图Servlet;
视图Servlet会根据请求信息和控制器保存的属性信息渲染页面,形成我们看到的网页。

除此以外,Servlet还有一个非常特殊的特性叫做监听器,它会监听系统中的多种事件,满足我们在事件前后执行的需求。
当然,监听器用的比较少,不过有机会还是会用得上的。

工作流引擎的实现

如何看待工作流引擎?近日在研究工作流引擎Activiti的数据库设计。
一个完整的工作流引擎有哪些部分?一个用户和组系统,一个流程定义文件,N个外置表单。
就拿最简单的请假流程举例:

  • 员工1点击申请按钮。
  • 系统启动一个流程实例。
  • 流程实例启动了一个表单1。
  • 员工1填写了表单1后提交。
  • 系统接收到员工1填写的内容,将其保存为变量。
  • 系统创建了签收任务,并分配给领导组。
  • 领导1签收这个申请。
  • 系统创建了批准任务,并分配给领导1。
  • 领导1点击办理按钮。
  • 系统启动了表单2.
  • 领导1填写了表单2并提交。
  • 系统接收到领导1填写的内容,并将其保存为变量。
  • 系统创建了签收任务,并分配给HR组。
  • HR1签收了这个申请。
  • 系统创建了批准任务,并分配给HR1.
  • HR1点击办理按钮。
  • 系统启动了表单3。
  • HR1填写了表单3并提交。
  • 系统接收到HR1填写的内容,并将其保存为变量。
  • 系统创建了销假任务,并分配给用户1。
  • 用户1点击销假按钮。
  • 系统启动了表单4。
  • 用户1填写了表单4并提交。
  • 系统接收到用户1填写的内容,并将其保存为变量。
  • 流程实例结束。

stackoverflow上关于Java的TOP10问题

1、Why is it faster to process a sorted array than an unsorted array?
概述:为什么处理一个排序数组比一个未排序数组更快?
点评:答案是分支预测,重点在于了解分支预测的原理。

2、Why is subtracting these two times (in 1927) giving a strange result?
概述:为什么有特定的两个时间相差一秒,但是计算得出的结果却不是一秒。
点评:时区变化导致了很多问题,包括这一例,所以可能比较奇怪。只要保持时间问题上的敏感性就好。

3、Is Java “pass-by-reference” or “pass-by-value”?
概述:Java是值传递还是引用传递?
点评:虽然答案很清楚,但是回答里面还是可以学习到一些东西的。

4、Java's +=, -=, *=, /= compound assignment operators
概述:Java的+=, -=, *=, /=等运算符的执行原理?
点评:这些运算符运算完之后都会被格式化一遍,所以可能和想象中有所出入。

5、Avoiding != null statements
概述:如何避免使用 !=null 表达式?
点评:答案中提供了很多方案,这边就不赘述了。

6、Proper use cases for Android UserManager.isUserAGoat()?
概述:征求Android中UserManager.isUserAGoat的合适使用场景。
点评:对Android不了解就不点评了。

7、Differences between HashMap and Hashtable?
概述: HashMap和Hashtable之间的区别。
点评:需要对HashMap和Hashtable等数据格式有比较深入的了解。

8、Read/convert an InputStream to a String
概述: 询问如何把InputStream类型的数据变成一个字符串。
点评:涉及到InputStream和String两种格式之间的转换。

9、Why is char[] preferred over String for passwords in Java?
概述:为什么Java Swing中的密码优先使用chare[]而不是字符串?
点评:因为String是immutable,所以为了提前释放password这种敏感信息,所以使用字符数组。

10、Create ArrayList from array
概述:询问如何把array格式数据变成ArrayList格式数据。
点评:涉及到array和ArrayList两种格式之间的转换。

形参和实参,值传递和引用传递?

虽然接受了一定的编程科班教育,但是一直在搞Web,连形参和实参,值传递和引用传递的概念都搞模糊了。
正好趁自己不理解,把这几个概念都了解一下,免得以后搞个大笑话。

首先是形参和实参,这两个概念和值传递引用传递的概念搞混,但是现在了解了一下,完全不是一回事。
比如有个函数:
function test($a, $b, $c) {
print_r($a + $b + $c);
}
然后有个调用:
test($one, $two, $three);
那么$one, $two, $three就叫做实参,$a, $b, $c就叫做形参,形参只有在函数被调用时短暂存在。

然后再说值传递和引用传递
传参有两种效果,一种传递了以后,修改形参不影响实参;一种传递了之后,修改实参会影响形参。
值传递就是修改形参不影响实参的方式。
引用传递就是修改实参会影响形参的方式。

还得说一个特别一点的传递方式,对象类型引用变量的传参。
对象类型引用变量无论是值传递还是引用传递,最后都能修改被引用的对象的数据,这点需要牢记。
怎么说呢?整个过程是这样的:

  • 变量(地址)->地址指向的数据(引用)->引用指向的数据(对象)。

作为对比,普通类型变量的过程是这样的:

  • 变量(地址)->地址指向的数据(数据)。