终于可以进入语法课了. 也就是程序员和非程序员拉开差距的地方. 其实, 只是记住一些语法规则, 至多算是入门级的程序员, 真正重要的是解决实际问题的能力. 语法有语法的思路, 理清了思路, 细节怎么变化都没太大关系.
另外一个阻碍就是英语. 应该说, 用什么语言编程都可以, 但是实际情况是, 主流还是英语, 绕不开. 好在计算机英语词汇意思相对固定. 在网上找一份计算机英语一千词或者两千词的表, 看几遍, 遇到想不起来的再查一下, 多见几次就记住了.
另外, 技术类内容通常涉及到很多术语和简写, 比如, javascript简写成js, 有不清楚的可以在网上搜一下. 我习惯使用360的浏览器看网页, 遇到不懂的词, 直接用鼠标选择, 然后往旁边一拉就可以搜索了, 比较节约时间.
按照传统, 开局首先是要输出
hello world
谐音是 好了 我的
也就是说, 折腾了这么长时间, 环境终于配好了, 可见软件开发是一件多么无聊的事, 明明只想写一句话的代码, 却不得不花很多时间让他运行起来. 简化繁琐的技术细节, 让程序员真正可以专心于业务, 是世界软件行业的发展方向. 不过在美好的明天到来之前, 我们还是需要知道怎么样处理好正确的环境配置, 让真正有用的那部分代码能够运行起来.
我们还是从最简单的开始, 打开chrome浏览器, 按F12, 看到了开发人员工具, 点击console, 就出现了终端, 也就是一个能输入代码和输出运行结果的地方.
输入:
console. log('hello world')
按回车之后, 下一行出现了"hello world", 这就是编程的第一步.
太简单了, 没什么意思是不是, 但是在软件世界里, 保持简单是最难的, 最简单的也是最重要和最常用的, 甚至是非常深刻的, 真正讲起来很不简单. 比如, 那个多余冒出来的undefined是什么东东. 这就涉及到很多深刻的知识. 其中一个关键的概念是函数, 函数有参数和返回值, 小括号里的内容就是参数, 而undefined是返回值. 先大概有个印象, 感觉跟中学数学里的函数差不多就行了, 我们以后要一直见到函数, 习惯了会用了就好了. 软件开发很多时候是这样, 尽管我们不全部理解, 但是我们知道怎么使用, 也能够实现功能, 这就叫封装. 好的产品一定是经过了良好的封装, 让用户不用学习很多复杂的理论就能傻瓜式的使用.
我们可以再来看几个函数, 想办法找点好玩的.
输入:
alert('hello')
回车, 看见弹框了吧, 这个弹框简单实用, 既可以给用户看, 也可以给自己看, 虽然颜值朴素了一些, 不过很多时候还是离不开他.
再试两个
prompt("Please enter your name")
出现了输入框.
confirm("Press a button")
出现了确认和取消的选项(可能显示的是英语什么的, 总之就是那些意思了).
这可以称为是传统的js入门三板斧了. 还是很简单的吧.
不过这些原生的组件样式不太美观, 现在很少使用了. 很多项目都要自己写一些颜值更高的弹框.
无论如何我们的js算是迈出了第一步. 那么java呢, java就更麻烦了. 为了简化问题, 我们从kotlin开始. kotlin是什么, 可以看作是升级版的java, 更现代, 更简单和强大. 由于是JetBrains公司出的(就是开发Idea那家公司), 和Idea配合很好.
接下来的事情就类似了, 打开Idea, 在菜单里找到tools, kotlin repl选项, 在下方的窗口输入
println('hello world')
然后ctrl加回车, 结果出来了, 和js差不多吧.
其实还是有很多不一样, 明显感到稍微麻烦一些. 这还是我们用了kotlin和repl, 已经简化很多了. 以前java是没有repl的, 那要怎么运行呢, 我们一步一步来看.
还是先用kotlin作例子, 可以在官网首页上粘贴那几行代码. 新建一个kotlin项目, 新建kotlin文件, 粘贴代码, 点击绿色箭头, 运行, 没有意外的话, 也出来结果了.
然后是新建java文件, java的代码是这样的
publicclass HelloWorld {
publicstaticvoid main(String[] args) {
System.out.println("Hello World");
}
}
明显感觉更长了是吧, 还是一样点击绿箭头, 运行, 结果一样.
说了半天总算到java了, 可是还没完呢. 用Idea运行也是我们简化了的, 真正在服务器上运行项目不太可能装个idea让我们上去点开始的. 那要怎么办呢, 我大概说一下流程,让大家感受一下. 不过这里概念多, 操作繁琐, 嫌麻烦的可以跳过.
首先要找到cmd, 现在是powershell, 就是输命令的东西. 然后确定jdk安装在什么地方. 当然默认安装的话, 都会把jdk路径添加到path中, 结果就是我们输入java, 会出现一长串英文提示信息, 代表各种命令选项. 然后是确定自己写的java文件所在的路径, 找好路径后先用javac命令编译java文件, 编译执行完后会生成同名的class文件. 再用java命令运行class文件, 他就会找到里面的main函数执行, 输出结果了.
图就不放了, 网上随便一搜java的hello world就有.
有没有感觉又难看又麻烦, 但是很多情况下这是唯一可用的方式. 既然没有选择, 那就享受吧, 时间长了说不定就会喜欢上这种方式了, 很多高手都是只用命令行的, 某些情况下确实方便快捷, 也更节省资源.
值和类型
我们继续从函数开始, 形式和数学中的函数写法类似, f(x), 小括号前面是函数名, 里面是函数的参数. 如果有多个参数, 用逗号分隔开. 如f(x, y, z)
这里涉及到两个概念, 一个是名字, 另一个是值. 我们先从值开始.
像在数学中一样, 首先当然是数字值. 既然是计算机, 也是要有数字的. 整数小数都有, 写法也是一样的.
另外一种基础的值是字符串. 这名字起的不是很动听. 其实就是文字, 各种文字包括特殊符号. 内容任意, 长度任意. 但是有一个要求, 开头和结尾要加上引号.
其实这也没什么, 养成认真良好的习惯, 我们平时写文章也是要规范的使用引号的. 但是这里有一些区别了. js里有单引号和双引号都可以, 可以看心情凭感觉来. 但在java里, 单个字符用单引号, 超过一个了用双引号, 不能乱用.
这就是语法, 不同的语言会有不一样的语法细节要求. 实际上要表达的东西是一样的. 但是很多语法要求也是为了让我们养成良好的习惯. 即使是js要求很宽松, 我们也不应该随意使用, 最好保持一致的风格, 方便自己, 也方便他人. 一般推荐在js里字符串用单引号.
另外一种值是boolean值, 只有两个, true代表真, false代表假.
暂时就接触这三种值吧. 我们说三种, 就是说他们分属于不同的系统, 也就是不同的类型. 类型是一个很重要的概念. 似乎看不见摸不着却又无处不在. 说简单很简单, 却也可以非常复杂.
命名和赋值
然后我们说一下名字吧. 名字用来代表某个东东. 人有名字, 物也有名字. 所以在软件里我们也要用不同的名字来区分是不是同一个东东. 最开始接触的值少, 可以用简单的名字, 单个字母的, 但是随着时间会有越来越多需要通过名字来区分, 这时候起名字就不那么容易了. 所以学好语文很重要.
尽管我们在学编程, 但是用到的很多是小学数学和语文的知识, 所以说, 越是基础的东西越重要和常用.
起名也是有语法要求的, 要是字母, 后面可以加点数字, 至于其他符号, 具体要求可以查语法手册, 其实很多语法细节没必要记那么细致, 无非都是为了不出错, 我们就用最通用的就足够了.
比如说, 我们起了一个名字叫WoDeBianLiang, 英文不好的可以先用拼音顶上, 长远来看还是努力学好英语吧. 这里每个首字母首字母大写, 这是一种良好的规范. 看起来更清楚.
怎么用这个名字呢, 在js里, 需要在他前面加一个let或var, 就可以用了, 也就是可以放在代码里那些需要值的地方了. 比如我们的
congsole. log(WoDeBianLiang)
运行之后, 也出了一些结果, 但是好像哪不太一样. 不像其他的那样输出返回值, 而是出了一些红字. 意思是说 这个名字没定义呢.
出现的还是undefined. 也就是说, 还没给这个名字指定内容.
好吧, 让我们换上专业的'科学'术语吧. let或var后面加名称就是声明了一个变量. 变量代表一个空间, 在计算机内存里的. 里面可以存放值, 存的过程叫赋值, 没赋值之前就用undefined表示.
赋值也简单, 后面加上等号和值, 就可以了.
实际上, 现在流行用常量, 也就是只赋值一次, 以后不再改变了. 常量用const声明, 后面直接赋值.
强烈推荐使用const, 然后你会发现, 很少有赋值后需要再次改变的情况, 基本可以忘掉let和var. 当然这要配合一些其他的办法. 这些思路和办法还有一个名字叫函数式编程. 其实也不需要研究太多名词, 只要知道他很好用, 用就可以了.
然后我们就可以写基本的代码了. 声明赋值, 调用函数, 运行, 我们已经可以称为初级程序员了.
const a = 'hello'
alert(a)
这是js的写法. 那么java怎么办呢. 还是那句话, java总要麻烦一些. java里凡事都有类型, 必须事先就规定好. 所以不能简单的写一个const加上名字, 名字前面要加上类型的. java里说是有8种基本类型, 其实6种都是数字, 剩下两种就是Boolean和char, 字符. 总的来说, 也还是那三类.
6种数字, 除了整数和小数, 难道还有分数, 复数, 无理数?嗯, 不是的, 只不过把整数分了四个范围, 小数分为两个范围. 就像我们分的两位数, 三位数之类. 但是在计算机里是按照二进制的位数分. 也就是8位数 byte 16位数short 32位数 int 64位数 long. 不过一般用int就够了, 实在大的数字可以用long. 小数在计算机机里一般叫浮点数, 我理解就是他们把小数点叫作浮点. 至于为什么叫浮点, 我推测是音译float. float表示流动. 可能感觉小数点的位置不固定, 就像在数字之间流动一样. 浮点数分为两类, 32位 float 64位 double, 一般用double就行.
基本类型就这些了, 以后还会有更多的类型. 最常见的一种就是我们是我们上面说到的字符串 String,
char表示用单引号的单个字符, String可以表示用双引号的多个字符.
所以在java里, 首先要写上类型, 强制在命名之前先想好类型, 并且要清楚的写出来.
而为了表示像const一样不可变的量, 还要在前面加上 final
final int a = 1;
final Stirng b = "hello";
有时候还要添加其他的前缀, 声明一个值, 需要加一大串各种头衔, 这就是java. 相比之下是不是觉得js好亲切啊. 不过凡事皆有利弊, 更多的限制有时候会带来更多规范, 只要限制是合理的.
说道这里就顺便说一下kotlin吧, kotlin试图减少一些没用的限制. 写起来是这样
val a = 1
val b = "hello"
val相当于js里的const, 如果直接用一个明显有类型的值来赋值, 就可以不写类型, 这叫类型推断. 可以理解成是用人工智能帮我们填上了类型. 哈哈, 总之我们要写的变少了.
但是如果没法推断, 还是要写类型的, kotlin里是写在名字后面, 中间加个冒号. kotlin类型和java类型基本对应, 个别名字有调整. 具体可以参考官网文档.
var a:Int
vat b:String
调用print, 开始阶段我们都直接在repl里实验吧. print和println的区别是println自带换行.
有时候我们面临两种或更多的选择, 需要根据条件来判断执行哪个, 就需要用到if else, 虽然是英语, 但是so easy, 习惯之后可能用起来比 如果 否则 还要熟练呢
用法
if(){
}
else{
}
if后面加小括号, 和函数一样, 但是小括号里必须是boolean值. 也就是true或者false. 后面加大括号, 大括号里面写要执行的代码. 如果小括号里是true, 就执行, 否则不执行. 后面加上else和大括号, 当false的时候就会执行else那个大括号里的代码.
如果条件更多, 就可以继续加 else if(){}
也还是比较简单的啊. 但是有一些细节问题 历史遗留问题说一下.
一是, 单行语句大括号可以省略, 这个个人感觉没太大用, 增加记忆负担. 我一般都是先把if(){}这三对写好, 再在里面填对应的内容. 省那两个括号用处不大, 有时候还容易出问题. 我们就记最简单, 最通用, 最没有歧义的就好了, 对大家都好.
二是, 分号有时可以省略. 语句结尾加分号, 这是C语言的传统, 老一代的语言基本都沿袭了下来, 不过现在很多新一代语言开始抛弃这一传统. 目前的情况是, js可以不加, kotlin可以不加, java还是要加. 我自己现在也习惯不加了, java代码能看懂就行了, 真正写的话还是用kotlin吧. 有新的为什么还要用旧的呢. 反正是完全兼容, 无缝调用, 甚至可以自动转换. 有时候真的不得不给jetbrains的工程师们点赞.
kotlin里的if else 除了兼容普通用法, 还可以作为表达式. 关于表达式和语句区别, 我们以后再说.
还有if 后面那个小括号里也是可以用Boolean表达式的, 其实很少直接写true false的.
还有一个多重选择的switch 功能弱 不好用, 建议大家可以先忽略. 见到能明白意思就行, 自己用还是写else if就行了. 学习要一直关注最有用的部分, 很多东西多年用不上一次, 没必要开始就花太多时间.
循环
如果不是按条件选择, 而是要一直重复执行, 就要用到循环了. 在学校的时候我总认为, 循环是计算机的主要价值, 因为那一堆 if else 的代码, 用心算结果都很快就出来了, 何必花半天时间写成代码, 让电脑去算呢. 后来才发现, if else的判断多了, 也是不好理清的. 不管怎么样我们需要自己在代码里理清一遍(其实还是要在自己脑子里先理清), 然后再让电脑帮我们处理无数遍.
循环有两种, for和while, do while 我觉得就是反过来的while. 循环确实是比较难的内容, 我建议大家先大概了解. 以后多数情况我们都是作业务层的开发, 基本不会手工控制循环(当然要借助高阶函数和递归的帮助). 如果需要做一些底层的技术, 对性能要求高的, 可能就要深入的研究怎么优化循环了.
看一下基本格式吧
while (boolean) { }
格式和if一致, 反过来是do while
do{ } while(boolean)
意思差不多, 说是这里至少会执行一次, 看格式就能猜出来, 因为是先执行后判断的嘛.
for的格式可能会有一些细微的不同, 这里放一个kotlin的示例吧. 反正我们很少会用到, 大概看一下, 真用到了再查查吧.
for (item in ints) { }
注释
最后说一下注释, 这个很简单, 就是说明或备注. 写了只能看, 不会被执行.
单行注释//
多行注释/* */
有一种意见是只用单行注释, 有多行的话, 每行前面都加//就行了. 这样更简单和清楚, 否则可能搞不清到哪结束的. 不过这个需要借助编辑器的帮助, 可以批量加//, 否则自己一行一行加就比较痛苦了.
注释虽然简单, 但是实际工作中也很重要. 代码更多时候需要给人阅读. 即使不考虑别人, 加上注释也能给自己作备忘. 当然注释要适度, 现在更多推荐写自说明的代码, 避免注释和代码不同步的情况. 总之, 注释运用的好, 是一种有效的帮助.
实际工作中还经常会有临时注释掉一块代码的情况, 这时候实际上把注释当成了临时的删除机制. 同样也是要做好控制, 如果有大量被注释掉的代码, 影响了阅读, 还是考虑放在版本库里可能更合适.