Fork me on GitHub

关于

欢迎来到我的小站呀,很高兴遇见你!🤝

我是18届毕业生,专业是软件工程移动互网

喜欢编程、看书和摄影 😁

Github 信息

Anurag's github stats

推荐书单

《黑客与画家》

《软件随想录》

《暗时间》

《人生哲思录》

《少有人走的路》

开源贡献

Spring Boot

PR Simplify code

SpringBootCodeGenerator

PR 功能添加

WeChatRead

https://github.com/gaohanghang/WeChatRead

使用 electron 构建的微信读书电脑客户端

输出

CSDN:https://blog.csdn.net/qq_22871083

博客园:https://www.cnblogs.com/gaohanghang/

公众号:《骇客与画家》

头条号:《骇客与画家》

学习网站

packtpub视频学习

Github

牛客网

阮一峰的网络日志

博客工具

博文配图

公众号

《骇客与画家》

视频制作

B站地址

https://space.bilibili.com/180303522

视频制作网站和软件

新片场

iMovie

翻墙

https://justmysocks1.net (付费)

开发设备

MacBook Pro 2019(15寸)

AOC 4k显示器(27寸)

需要时刻锻炼的能力

算法能力

工程能力

沟通能力

表达能力

英语能力

翻译 YouTube 视频

专业书籍推荐

《java核心技术卷一》

《深入理解Java虚拟机》

《Java并发编程实战》

《码出高效 Java 开发手册》

为什么要写博客

知识的积累

价值的展示

喜欢的产品(虽然现在买不起)

莱卡相机

莱卡的相机实现太漂亮了

鸡汤

不要怂,就是干

提倡把自己丑陋的代码在比自己更优秀的人面前晒出来。含蓄的结果就是以为自己就是宇宙中心,感觉别人的代码都不如我。— 《码出高效 Java开发手册》

应该保持持续性的努力,而不要间歇性的努力

比起后悔的痛苦,努力的辛苦又算得了什么

不着急,不害怕,不要脸 — 冯唐

不想学习时该怎么办

使用手机拍摄学习延时视频,逼自己学习

看会书

个人技能

  • 熟悉JAVA编程
  • 熟练使用IntelliJ IDEA开发工具
  • 熟悉Spring,SpringMVC,Spring Boot等开源框架的使用
  • 熟悉MySQL,Postgresql数据库的使用
  • 熟悉Git的使用
  • 熟悉Gradle,Maven
  • Linux基本命令
  • 熟悉Tomcat应用服务器的使用
  • 熟悉restful接口风格
  • 会用Docker

final关键字详解

什么是final变量 / 类 / 方法?

任何变量前被 final 修饰就是 final 变量,定义的类前被 final 修饰就是 final 类,任何方法前被 final 修饰就是final方法。

当用final修饰一个类时,表明这个类不能被继承。

下面这段话摘自《Java编程思想》第四版第143页:

“使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的 Java 版本中,不需要使用 final 方法进行这些优化了。“

意思就是说如果认为方法足够完整,子类不需要修改就可以用final方法,避免子类去修改。

final方法是静态绑定的,在编译时候就确定好是哪个类的方法,所以 final 方法比非 final 方法快一些。

final修饰变量和修饰引用变量到底有啥不同?

简单来讲,就是final修饰的常量普通变量不可改变,修饰的引用变量引用不可变,引用对象的内容可以改变!

final关键字有啥好处?

  • final方法比非final快一些
  • final关键字提高了性能。JVM和Java应用都会缓存final变量。
  • final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
  • 使用final关键字,JVM会对方法、变量及类进行优化。

Git常用命令速查表

master: 默认开发分支

origin: 默认远程版本库

Head: 默认开发分支

Head^: Head 的父提交

创建版本库

1
2
3
git clone 	# 克隆远程版本库

git init # 初始化本地版本库

修改和提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
git status 						# 查看状态

git diff # 查看变更内容

git add # 跟踪所有改动过的文件

git add <file> # 跟踪指定的文件

git mv <ole> <new> # 文件改名

git rm <file> # 删除文件

git rm --cached <file> # 停止跟踪文件但不删除

git commit -m "commit message" # 提交所有更新过的文件

git commit --amend # 修改最后一个提交

查看提交历史

1
2
3
4
5
git log 						# 查看提交历史

git log -p <file> # 查看指定文件的提交历史

git blame <file> # 以列表方式查看指定文件的提交历史

撤销

1
2
3
4
5
git reset --hard HEAD			# 撤销工作目录中所有未提交文件的修改内容

git checkout HEAD <file> # 撤销指定的未提交文件的修改内容

git revert <commit> # 撤销指定的提交

revert与reset的区别

git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。

分支与比标签

1
2
3
4
5
6
git branch 						# 显示所有的本地分支
git checkout <branch/tag> # 切换到指定分支或标签
git branch <new-branch> # 创建新分支
git tag # 列出所有本地标签
git tag <tagname> # 基于最新提交创建标签
git tag -d <tagname> # 删除标签

合并与衍合

1
2
git merge <branch>				# 合并指定分支到当前分支
git rebase <branch> # 衍合指定分支到当前分支
阅读更多...

ES Head插件的安装与使用

Head插件安装

如果都是通过rest请求的方式使用Elasticsearch,未免太过麻烦,而且也不够人性化。我

们一般都会使用图形化界面来实现Elasticsearch的日常管理,最常用的就是Head插件

步骤1:

下载head插件:https://github.com/mobz/elasticsearch-head

步骤2:

解压到任意目录,但是要和elasticsearch的安装目录区别开。

步骤3:

安装node js ,安装cnpm

1
npm install -g cnpm --registry=https://registry.npm.taobao.org

步骤4:

将grunt安装为全局命令 。Grunt是基于Node.js的项目构建工具。它可以自动运行你所

设定的任务

1
npm install -g grunt-cli
阅读更多...

GIT提交规范的使用和总结

原文地址:https://www.jianshu.com/p/1850c040271f
原作者:wizarot

  • Why

  1. 在接手新项目时候
  • 你希望看到git的commit记录是这样的?

  • 还是这样的?? WTF!?

  1. 听说鱼的记忆只有7秒钟, 但是我看人的记忆也不怎么样,反正我能记清楚之前写的代码细节,最多只有7天
  2. 那么问题来了,git提交记录如果不能提供有效信息,项目上线一段时间之后出bug需要修复,或者临时接手其他同事项目时,看到git记录里只有一堆的Update心情如何?

What

  • git 提交commit部分,规范模板,提供尽量详细的信息
  • 用最少得话把事说清楚,格式统一,方便快速阅读和定位
  • 不用想太多,简洁操作 , 无需额外增加大量时间
  • 与gitlab数据issue关联,获取更多信息, 例如当时这个需求细节是怎么样的?或者客户提出了什么样的奇葩要求,才有这段shi~一样的代码?

How

  • 复制模板(之后分享这个文件)到你的home目录.
  • 执行命令: git config –global commit.template ~/.git-commit-template
  • 看一下是否正确配置了: git config commit.template
  • 每次体检时简单修改一下即可,一般不会超过1分钟
  • 举一些完成的例子:
    1.<修改>: (后台MGTOMedia/AppBundle/Controller/NewsController.php) <为了保持前后台新闻排序一致,这里统一修改为按照position desc > issue#17
    2.<bug修复>: (MGTOMedia/CommonBundle/Services/ElasticSearchService.php)<搜索的queryBuilder忘記跟著改過來了,这里统一改一下> issue#18
    3.<测试代码>: (尝试composer引入phpoffice)composer 引入phpOffice读取doc文件遇到一些问题
    4.<文档改动>: (新增文档) <ElasticSearch相关>新增Ela搜索News的Mapping文档和搜索使用的query例子伪代码
  • 如果你针对自己的模板有什么改进,请记得分享给我一份!
  • 我的文档范本: (你看,真的很简单,只有3行)
1
2
3
<新功能|bug修复|文档改动|格式化|重构|测试代码>: (影响范围) <主题> 
# 解释为什么要做这些改动
issue #?

How good

  • 总结我个人在2018年下半年使用情况来看,这个确实是有必要的.几乎不花费额外精力和时间,但是之后查找问题效率很高.
  • 可以通过 issue#? 关联到gitlab. 这样如果之前关于每个需求细节都在issue中讨论的话,那么这几乎就是一套非常完整而且有细节,有代码的项目文档了.也不需要额外花费时间来写文档. 我知道写文档这工作基本没人愿意做. 等到真的需要的时候,也没人能记得清楚到底该写什么了.
  • 写清关联信息,方便事后查找,同事协作
  • 别给自己挖坑,提高问题解决的效率
  • 合作的时候能快速理解一些设计的原因
  • 出问题的时候可以快速定位到位置,并且理解逻辑快速修正
  • 你不能确保自己能在一个月后,自己还能记住项目的每个细节

Java中泛型的生存时间(泛型只存在于编译期)

Java中在使用集合的是往往会涉及泛型,那么泛型在Java中的生存时间是多少呢?

当我问这个问题的时候可能有的人不是太明白怎么还会有这么奇怪的问法。是的,问的就是Java中泛型的生存时间是多少,泛型的作用是申明集合中存储元素的类别,避免存储元素类型不统一混乱。

1
2
3
4
ArrayList<Integer> list = new ArrayList<Integer>(); 
list.add(111);
list.add(222);
list.add("Hello");//编译报错

如上面的代码实例:创建了一个数组集合泛型是Integer类型的,存储字符串“Hello”会立即报错,这是在编译期报错,当然了这种类型不匹配运行时肯定也会是报错的;

1
2
3
4
5
6
7
ArrayList<Integer> list = new ArrayList<Integer>(); 
list.add(111);
list.add(222);
Class clazz3 = Class.forName("java.util.ArrayList");//获取ArrayList的字节码文件
Method m = clazz3.getMethod("add", Object.class);//获取add() 方法,Object.class 代表任意对象类型的数据
m.invoke(list,"Hello");//通过反射添加字符串类型元素数据
System.out.println(list);//运行结果:[111, 222, Hello]

上面代码通过反射给Integer类型的数组集合添加了一个“Hello”字符串类型的数据并且正常的将数组打印了出来;

这是没有报错的;说明泛型只是在java的编译期会产生错误但是在java的运行期(已经生成字节码文件后)是会被擦除的,这个期间并没泛型的存在;

由此可见:泛型值存在于java的编译期,编译后生产字节码文件泛型是被擦除的;

排序算法的思想

选择排序

找到数组中最小的元素,将它和数组的第一个元素交换位置,再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复直到整个数组有序。

不断选择剩余元素之中的最小者。

阿里巴巴Java开发规约-注释规约篇

1.[强制] 类、类属性、类方法的注释必须使用Javadoc规范,使用/*内容/格式,不得使用// xxx方式。

说明: 在IDE编辑窗口中,Javadoc方式会提示相关注释,生成Javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。

2.[强制] 所有的抽象方法(包括接口中的方法)必须要用Javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。

说明: 对子类的实现要求,或者调用注意事项,请一并说明。

3.[强制] 所有的类都必须添加创建者和创建日期。
4.[强制] 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。
5.[强制] 所有的枚举类型字段必须要有注释,说明每个数据项的用途。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* @Description: 季节枚举类
* @author: Gao Hang Hang
* @date 2019/01/05 22:02
*/
public enum SeasonEnum {

/**
* 春季
*/
SPRING,

/**
* 夏季
*/
SUMMER,

/**
* 秋季
*/
FALL,

/**
* 冬季
*/
WINTER;
}
6.[推荐] 与其”半吊子”英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持英文原文即可。

反例: “TCP连接超时”解释成”传输控制协议连接超时”,理解反而费脑筋。

7.[推荐] 代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。

说明: 代码与注释更新不同步,就像路网与导航软件更新不同步一样,如果导航软件严重滞后,就失去了导航的意义。

8.[参考] 谨慎注释掉代码。在上方详细说明,而不是简单地注释掉。如果无用,则删除。

说明: 代码被注释掉有两种可能性:

  • 后续会恢复此段代码逻辑。
  • 永久不用。

前者如果没有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。

9.[参考] 对于注释的要求: 第一、能够准确反应设计思想和代码逻辑;第二、能够描述业务含义,使别的程序员能够迅速了解到代码背后的信息。完全没有注释的大段代码对于阅读者形同天书,注释是给自己看的,即使隔很长时间,也能清晰理解当时的思路;注释也是给继任者看的,使其能够快速接替自己的工作。
10.[参考] 好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的一个极端: 过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。

反例:

1
2
// put elephant into fridge
put(elephant, fridge);

方法名put,加上两个有意义的变量名elephant和fridge,已经说明了这是在干什么,语义清晰的代码不需要额外的注释。

11.[参考] 特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描,经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。
  • 待办事宜(TODO): (标记人,标记时间,[预计处理时间]),表示需要实现,但目前还未实现的功能。这实际上是一个Javadoc的标签,目前的Javadoc还没有实现,但已经被广泛使用。只能应用于类,接口和方法(因为它是一个Javadoc标签)。
  • 错误,不能工作(FIXME): (标记人,标记时间,[预计处理时间]),在注释中用FIXME标记某代码是错误的,而且不能工作,需要及时纠正的情况。
1
2
3
4
public class Test {
// TODO: (高行行,2019-1-5,[2019-1-6])
// FIXME: (高行行,2019-1-5,[2019-1-6])
}

如何提高工作中的开发效率

转载 如何提高工作中的开发效率

注: 以下不提过多技术层面的技巧,更多的是工作方式。*

积极沟通,理解产品需求;主动对接,减少不必要的等待;学会搜索,培养一套自己的开发流程。

如果项目中大多只是做业务开发,涉及到的技术难点不多,只是业务逻辑比较复杂的话,那整个开发流程真正花在编码的时间其实是不多的,大部分时间花在以下几方面:

  • 了解清楚业务需求,开发中和 PM 沟通一些需求的细节问题;
  • 等待 UI 设计师完成设计图或切图;
  • 等待后端开发写好接口文档或进行接口的联调;
  • 开发过程中的需求变更或增加新需求;

那如何减少这些开发流程中花费的时间,从而提高开发效率呢?我觉得可以从以下几方面去考虑:

1. 积极沟通,理解产品需求

一般开发初期,开发人员会根据 PM 提供的原型图进行开发,但开发过程中可能会遇到一些业务逻辑,在原型上并没有标清楚,这时候,我一般习惯提前问清楚 PM,而不是等到测试提出问题后才改,虽然这样,开发前期会花不少时间在沟通上,但可以减少后期测试时的问题。

2. 主动对接,减少不必要的等待

待了几家公司,也接触了不少客户端的开发者,他们往往喜欢等弄好设计图才开始开发,或等后端定义好接口才开发。我觉得其实可以提前根据原型图初步弄好布局或大致的控件元素,或是自己先搭建好 UI 框架,等设计图和接口好了,再调整下边距、字号、颜色等,建model 层,最后后端发布接口到开发环境,就可以测试联调接口了。

3. 如何应对开发过程的需求变动或增加新需求?

需求变动时,要考虑变动的合理性,让 PM 给出合理的理由,而不是一味认同 PM 的需求,PM 说什么就做什么。自己认为不合理的需求,说出自己的理由,和 PM 据理力争(同时也要站在产品需求和用户体验的角度考虑问题)。如果 PM 固执己见,又不能把我说服,那也只能询问自己的上级了,确定要做的话,也就只能做了。

另外,开发中无论是需求变动,还是接到新需求,首先如果不是紧急的需求,是大需求,耗时比较长的话,最好和 PM 申请要增加开发时间,避免延期,同时要做一下几点判断:

  • 需求的合理性;(理解需求的底层逻辑,可以更好地了解产品)
  • 需求的技术可行性;(在有限的项目周期内,技术是否可以实现)
  • 功能的版本兼容性处理;(是否适配旧版本,是否需要做接口版本处理)

4. 学会搜索,培养自己的一套开发流程

首先基础技术要扎实,这是提高效率的最好办法,而不是所有大小问题都去搜索,这样挺耗时间的。这里所说的“学会搜索”,一方面是搜索引擎,要懂得科学上网,使用 Google 搜索;另外是学会用英文搜索!这是我工作将近三年来慢慢开始培养的习惯,学会用英文搜索,可以更快速找到准确的答案。

在几家创业公司上班都没有严格的开发流程,有时候只有一个上线的时间节点,连测试的时间节点都是开发后期才确定,这种情况下,我觉得需要有自己的一套开发流程,各个环节都做好,开发效率就会提高了。目前我基本按照以下流程进行开发:

  • 过需求:根据被分配的任务,过一遍原型图的需求,大致了解需要用到哪些技术点;

  • UI 布局:根据原型图弄好 UI 布局,等到设计弄好设计图,再微调;

  • 搭页面框架:根据布局写好视图层逻辑,如 Activity,Fragment,Adapter 和相关控件;

  • Model 层:根据后端写好的接口文档,初步弄好 Model 层的逻辑;

  • 接口联调:和后端开发进行接口联调;

  • 自测:根据原型图上备注复查一遍业务逻辑和一些文案以及 UI 细调,同时测试下一些交互等;(我遇到不少人,其实自测不是很严格,导致提测时会出现一堆 bug)

  • 提测:提交给测试人员测试;(有些是开发层的逻辑,测试可能不清楚的,要提前告知)

  • ……

以上流程,虽然也不算很完善,比如没有单元测试(创业公司很少有单元测试这个环节),也不清楚大公司的开发流程是怎样的。不过在实践中,这个流程的确给我提高了效率和保证了质量。比如,有一次开发中,几个人的工作量本来是一样的,但前期我被安排去做其他任务花了一周,后来还是按时同时完成了开发,而且测试阶段禅道(bug管理系统)的 bug 数量比其他人少25%左右。一套规范的流程,对开发效率来说还是有很大帮助的。

5. 开发中沟通的小技巧

  • 群聊最好能直接 at 相关人;
    有时候群消息太多,根本没留意看,所以群聊的时候最好 at 相关人;

  • 私聊高效于群聊;
    不是所有人都时刻看群消息,或者有时候看了,也会忘记回复;所以有针对性的问题,直接找相关人私聊会比较高效;

  • 重要事情直接找负责人当面沟通;
    比如一些问题比较复杂,用文字说,效率会比较低,最好直接当面聊;或者是一些比较紧急的问题,如出现线上 bug,最好当面沟通;

根据事情的紧急情况选择不同的沟通方式,而不是所有事情都是群聊或者当面沟通,这样不仅耗时,而且自己的时间容易被“中断”。

最后,以上只是我工作中关于开发效率的一些感悟,但是不同公司的开发流程可能不一样,而且不同人的工作方式不一样,希望多少能给你带来一些启发吧。

END

  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信