目录

Java虚拟机

JVM(Java Virtual Machine) 既可以指Java虚拟机规范,也可以指具体的某个实现。当JVM指Java虚拟机规范时,我们要注意虚拟机规范的版本。比如是JVM 1.8 还是 JVM 1.9。Java有很好的向后兼容性,使用高版本的Java编译器也可以顺利编译针对低版本JVM开发的代码。也正是由于Java的向后兼容,很多过时的语言规范成了新的语言规范的包袱,很多过时的标准类库依然遗留在新版本的JDK中。

阅读全文 »

目录

午餐时的争吵

今天中午我偶然路过二楼的厨房,听到同事们边吃午饭边争论着什么。我好奇的前去观摩,原来是在代码评审上有了分歧。

第一个同事说这个代码虽然能满足现在的需求,但是却不易于向某个他描述的方向拓展,他言之凿凿,认为我们的软件不久就会有他描述的需求。与其等到新需求到来时在对软件进行改动,不如开始实现时就考虑到可能的拓展,让这个模块变得灵活以适应将来的需求。

而另一位同事则不为所动,觉得YAGNI(You aren’t gonna need it)。就算我们真的要满足第一个同事所描述的需求,但是根据他的判断那也是很长时间(一年)之后的事了。如果现在就把模块变得易于拓展,那么无疑会增加代码的抽象层次,本来一个类就可以实现的功能,现在要多实现几个类。

第三位同事也加入了讨论。把软件设计的灵活以适应将来的变化是一件好事,但是这么做也是有代价的。灵活意味着这个模块需要更高的抽象层次,在新的需求到来前,这个模块都需要保持它本不需要的抽象层次。况且现在我们假设对于需求的预测是正确的,假如需求根本不是我们想象的那样变化,那么现在的努力不就白费了吗?

第一位同事似乎没有被说服,另外两位同事也各执已见。午饭结束,大家各自回到工位上继续搬砖了。

虽然这次争论还没有结果,也还不知道谁对谁错。那么我们在实现某个模块时,究竟是只实现现有需求还是要考虑到将来的需求而将模块实现的灵活一点呢?

阅读全文 »

目录

在Java里,如果我们创建了Integer类和Number类,并且IntegerNumber的子类。那么List<Integer>类也是List<Number>类的子类吗?

我们可以写一段代码来找到这个问题的答案。现在我们有一个求List<Number>类最大值的方法,它的输入是List<Number>类的实例。若List<Integer>类也是List<Number>类的子类,那么下面的代码应该是合法的。

阅读全文 »

目录

Java 泛型

我们为什么需要泛型

自从Java SE 1.5引入泛型(Generics) 之前,Java程序员想要写出通用的代码有点难度。比如想要得到Java某个集合(Collection)的最大值,在没有泛型的情况下,我们需要针对每个特定类型去写特定的求最大值方法。

比如针对Number集合我们需要实现

1
public static Number max(NumberCollection coll, NumberComparator comp)

针对Integer集合我们需要实现

1
public static Integer max(IntegerCollection coll, IntegerComparator comp)

显而易见,这样实现起来是非常没有效率的。我们需要为每个不同的类型实现重复的逻辑,重复在编程中是非常罪恶的。当然,为了减少重复,我们也可以有这样的实现

1
public static Object max(ObjectCollection coll, ObjectComparator comp)

因为Java所有的类都是Object的子类。当然这样实现的坏处就是需要做对象转型(Casting)

1
Integer maxInterger = (Integer) max(coll, comp)

然而对象转型也是非常罪恶的,因为一旦错误地使用了对象转型,代码只有到运行阶段(runtime) 才会报错。所以我们要尽可能的避免对象转型。

而有了泛型以后,我们只需要实现

阅读全文 »

目录

背景

几年前在实习时,我完全没有接触过设计评审。当时的团队采用Scrum开发过程。开发团队采取一个架构师(Architect)和三到四个开发者(Developers)的配置。为了保证开发速度,冲刺订单(Spring backlog)里的大多数任务(Ticket)都有架构师写的详细开发步骤。架构师在团队里负责了大多数的软件设计任务,开发者则专注于将架构师的想法实现。

参加工作后,由于开发领域,开发过程,甚至是公司文化都与我实习过的公司有很多不同。在此期间,我也接触到了相当多的设计文档和设计评审。

2019年,我在开发团队里承担的设计任务也越来越多,写过的设计文档有二三十个。参加的设计评审则是更多。一年下来,我对设计评审,这个软件开发中的一个流程,有了自己的一些看法,下面则是我对设计评审的一个小总结。

阅读全文 »

目录

简短的介绍

request-pullPull Request的名称如此相似,但是他们的功能是完全不同的。

request-pull是git的命令,它用于生成发送到邮件列表的待处理的更改的摘要。默认情况下,GitHub没有集成这个功能。

Pull Request是GitHub特有的一项功能(简称PR)。它用于向Github托管的某一项目中的某一分支提出合并请求。项目管理者则可以在github的web界面上合并来自不同分支的代码,解决合并冲突,做代码审查或对代码进行评论。

Git request-pull

使用目的

Generates a summary of pending changes

生成待处理的更改的摘要

阅读全文 »

目录

翻译自:Latency Numbers Every Programmer Should Know


操作 延迟(纳秒) 延迟(微秒) 延迟(毫秒) 参考
CPU L1 级缓存访问 0.5 ns
分支预测错误* 5 ns  
CPU L2 级缓存访问 7 ns 14x L1 cache
互斥体Mutex 加锁/解锁 25 ns
内存访问 100 ns 20x L2 cache, 200x L1 cache
用Zippy压缩1K字节 3,000 ns 3 us
在1 Gbps速率的网络上发送1K字节 over 10,000 ns 10 us
从SSD读取4K长度的随机数据 150,000 ns 150 us ~1GB/sec SSD
从内存读取连续的1 MB长度数据 250,000 ns 250 us
在同一数据中心内的来回通讯延迟* 500,000 ns 500 us
从SSD读取连续的1 MB长度数据 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
磁盘寻址   10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
从磁盘读取连续的1 MB长度数据 20,000,000 ns 20,000 us 20 ms 80x memory, 20X SSD
发送数据包 California->Netherlands->California 150,000,000 ns 150,000 us 150 ms
阅读全文 »

目录

第一印象

大约在20天前,我在亚马逊上冲动的购买了这个东西

树莓派3的官方Desktop Starter Kit,其实也就是树莓派3开发板+16GB miroSD装机卡+壳子+充电器套装。不过这样一套买下来,上手把玩树莓派要方便许多,机子到手第一天我就按照说明书安装了树莓派定制Debian的发型版Raspbian系统。第一感觉还挺好用,通过HDMI连接上显示器,再用4个USB接口中的两个连接键盘和鼠标就可以当做桌面电脑使用了。如果要通过个人电脑远程连接树莓派的话,ssh和VNC Viewer都很好用。

远程连接

通过ssh

注意,以下步骤均在个人电脑上完成,不是在树莓派上

阅读全文 »

目录

机器学习第一周笔记

概述

什么是机器学习?

从字面上来说,机器学习就是让机器通过模仿人学习的过程学习。也就是说让机器有能力学习,而不是通过准确的程序而实现。我们生活中无处不在存在着机器学习的应用,例如垃圾邮件分类系统,通过图片识别物体等。

机器学习的分类

机器学习分为两大类:

阅读全文 »

目录

反引号`

今天在看一本基于python2.2的Design Pattern书,其中有一段关于单例的代码我很不解,因为用到了反引号`,也就是reverse quotes。书中代码如下

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
class OnlyOne:
class __OnlyOne:
def __init__(self, arg):
self.val = arg
def __str__(self):
return `self` + self.val
instance = None
def __init__(self, arg):
if not OnlyOne.instance:
OnlyOne.instance = OnlyOne.__OnlyOne(arg)
else:
OnlyOne.instance.val = arg
def __getattr__(self, name):
return getattr(self.instance, name)

x = OnlyOne('sausage')
print x
y = OnlyOne('eggs')
print y
z = OnlyOne('spam')
print z
print x
print y
print `x`
print `y`
print `z`
阅读全文 »