如何深入学习一种编程语言?
结合自己学习、带实习生的一些经验总结的学习一门编程语言的切入方向。
本文可以作为学习语言的路书,当然只能作为指导原则,细节还需要参照具体语言决定。也可以作为自查工具,看看自己还有那些漏掉的地方。
基本上参考了一下几年来我接触到的几种语言的特性:JavaScript, Node.js, Golang, Java, Python。
总结的不完善,将来想到的时候再补充吧。
学习新语言的步骤
- 平台与特性
- 包管理机制
- 数据与运算
- 流程与控制
- 内建工具和包装类型
- 封装和抽象
- 测试与异常
- 扩展
平台与特性
- 平台的设计
- 面向领域
- 性能
- 语言特性
- 编译型,解释型
- 静态类型 / 动态类型
- 强类型 / 弱类型
- 函数式 / 过程式 / 对象式
语言的设计领域决定了其使用成本,比如开发 Web 项目,使用 Go,Node.js 等内置 HTTP API 的语言肯定要比 C++ 一类的语言使用成本更低。当然,像是 Java 这种有完善的 HTTP 开发框架,开发效率也会很高。
性能比较好理解,通常来说,语言越高级越自动化,性能相对越差。这里提供一个 Debian 团队的语言 Benchmark 项目的 连接 , 这里记录了大部分语言的 benchmark 信息。可以作为理解语言定位的参考。
编译(解释)方式、动态 / 静态、强 / 弱类型等语言特性很大程度上影响了该语言的程序设计思想。当我选用 Node.js 开发项目时,我可以相对随意的设计和运行程序。但是 Java 或者 C 就相对严肃,我需要严格的按照范式进行,否则根本跑不起来。
不是所有的特性每种语言都有完整的支持,没有的或者没有写到的也不用奇怪。
包管理机制
个人觉得包管理机制因该优先于语法学习。个人也推崇自顶向下的学习理念。
只有宏观了解代码运行和组织方式之后,再深入微观才能有比较好的理解。
- 包管理工具
- 第三方仓库的查询,安装
- 私有仓库的使用方法
不管会不会 Nodejs 都值得一试的 Nodejs 的包管理器:NPM
数据与运算
这里语言的基础语法层面的知识,是熟练使用的前提。通常来说,各种语言在这个领域类似但是不相同。
需要注意的点如下
- 基础语法
- 语言结构
- 文件命名,语句写法
- 标识符:大小写敏感
- 语言结构
- 数据与表示
- 数据的类型
- 基础类型:默认值 字节数 取值范围
- 数字型:short, int, long, float, double
- 非数字型:byte, boolean, char
- 高级类型
- 字符类型:string
- 操作:连接,查找,替换,trim, 大小写转换,split, 模版替换
- 包装类型:基础类型的衍生
- 字符类型:string
- 基础类型转换
- 隐式转换
- number 转: string boolean byte char
- string 转: number boolean byte char
- byte 转: string char
- char 转: string int
- 显式转换
- 隐式转换
- 集合类型
- 枚举,bitSet (位集), vector (向量), stack, array, map, slice
- 多维,遍历,查找,排序,比较,删除,插入,过滤
- 枚举,bitSet (位集), vector (向量), stack, array, map, slice
- 基础类型:默认值 字节数 取值范围
- 数据的表示
- 变量,常量
- 语法:声明,声明并赋值
- 作用域
- 范围:全局,局部,模块作用域
- 闭包
- 转义:
\t \b 后退符 \n 换行符 \r 回车符 \f 换页符 \' \" \\
- 数据的类型
- 数据的计算
- 运算
- 运算符号
- 算数运算:
+ - * / % ++ --
- 关系元算:
== != > < >= <=
- 位运算:
& | ^(异或) ~(按位取反) << >> >>>
- 逻辑运算:
&& || !
- 赋值运算:
= += -= *= /= %= <<= >>= &= ^= |=
- 三元运算符:
?:
- 类型运算符:
instanceof
- 算数运算:
- 运算符优先级
- 以 java 为例,优先级按顺序展开:
- 后缀:
() [] . (点操作符)
- 一元:
++ -- +(正号) -(负号) ~ !
- 乘性:
* / %
- 加性:
+ -
- 位移:
>> >>> <<
- 关系:
> >= < <=
- 相等:
== !=
- 按位与
&
> 按位异或^
> 按位或|
- 逻辑与
&&
> 逻辑或||
- 条件:
? :
- 赋值:
= += -= *= /= %= >>= <<= &= ^= |=
- 逗号:
,
- 后缀:
- 以 java 为例,优先级按顺序展开:
- 运算符号
- 运算
流程与控制
- 循环
- 条件循环: for wihle
- 迭代器
- 中断 break
- 跳过 continue
- 分支
- 两个出口的分支: if
- 多个出口的分支: if switch—case
- 暂停
- 阻塞(等待)
内建工具和包装类型
这部分是常见的自带的库的用法,写的不完善,可以根据需要参考语言文档按需选择。
- number 包装类型
- Short Integer Long Byte Double Float
- Math 计算工具
- 数值计算: abs ceil (上取整) floor rint (最接近的整数) round min max exp (e 的 a 次方) pow (a 的 b 次方) sqrt
- 三角函数: sin cos tan acos atan atan2 toDegrees toRadians
- 其他: random
- Charactor 类
- 转义字符
- 操作: isLetter isDigit isWhitespace isUpperCase isLowerCase toString
- String StringBuffer StringBuilder
- 连接 查找 替换 trim 大小写转换 substring split
- Date 的使用
- 时间戳 时区转化 格式化 比较 计算
- 用 string 转换
- 格式化编码
- G 纪元标记 AD
- y 四位年份 2001
- M 月份 July or 07
- d 一个月的日期 10
- h A.M./P.M. (1~12) 格式小时 12
- H 一天中的小时 (0~23) 22
- m 分钟数 30
- s 秒数 55
- S 毫秒数 234
- E 星期几 Tuesday
- D 一年中的日子 360
- F 一个月中第几周的周几 2 (second Wed. in July)
- w 一年中第几周 40
- W 一个月中第几周 1
- a A.M./P.M. 标记 PM
- k 一天中的小时 (1~24) 24
- K A.M./P.M. (0~11) 格式小时 10
- z 时区 Eastern Standard Time
- ‘ 文字定界符 Delimiter
- “ 单引号 `
- 正则表达式
- match
- 一般字符
. \d \D \s \S \w \W
- 不可见字符
^ $ \f 换页符 \n \r \t \v \b 字符边界 \B 非边界
- 其他
\cx 控制符(\cm 表示 ctrl+M)
\xn 十六进制字符:"\x41"匹配"A
\num 匹配重复次数: "(.)\1"匹配两个连续的相同字符
\un 匹配十六进制unicode字符: \u00A9 匹配版权符号©
- 组合
x|y [xyz] [^xyz] [a-z] [^a-z] (pattern)
- 一般字符
- count:
* + ? {n} {n,} {n,m}
- 模式
?
表示非贪心,如*? +? {n}? {n,}? {n,m}?
(?:pattern)
匹配但是不捕获industr(?:y|ies)
是比 ‘industry|industries’ 更经济的表达式(?=pattern)
匹配 pattern 结尾的表达式Windows (?=95|98|NT|2000)
匹配”Windows 2000” 中的”Windows”- 不匹配”Windows 3.1” 中的”Windows”
(?!pattern)
匹配不以 pattern 结尾的表达式Windows (?!95|98|NT|2000)
匹配”Windows 3.1” 中的 “Windows”- 不匹配”Windows 2000” 中的”Windows”
- match
- 流处理
- 文件处理
- IO
- 控制台交互
- socket
封装和抽象
- method
- 声明
- 调用
- 对象
- 模块
- 面向对象设计
- 继承
- 多态
- 接口
- 范型:描述算法忽略类型的工具,描述时忽略类型,使用算法时来再来确定类型
对于静态类型的语言来说,没有范型简直就是灾难。说的就是你: Go。
测试与异常
- 测试方法(单元测试)
- 同步异常
- 异步异常
功能扩展
- 序列化
- 多线程
- 文档提取
- 代码混淆
- 语言风格