笨熊之家

欢迎来到笨熊之家~

0%

文件权限

文件权限描述符

1
2
3
4
5
drwxrwxr-x 2 lucky lucky 4096 Apr 15 15:48 ./
drwxr-xr-x 5 lucky lucky 4096 Apr 14 13:24 ../
-rw-rw-r-- 1 lucky lucky 161 Apr 13 20:21 news
-rw-rw-r-- 1 lucky lucky 309 Apr 13 19:34 passwd.cut
-rw-rw-r-- 1 lucky lucky 309 Apr 13 19:34 passwd.sort

1 位是文件类型
2-4位是owner的权限
5-7位是group的权限
8-10位是other的权限
d代表directory(目录)
rwx分别是read(读),write(写),execute(执行)
- 在第一位指的是文件类型为文件,在后面的位上指的是不具有对应权限

文件夹权限描述符

Read more »

Carriage Return(CR), Line Feed(LF)
在以前使用打字机的时候,CR代表将机架移动到最右边(相对地,打字的指针也就复位到最左边),LF代表将机架向上移动,也就是相对地将打字的指针向下移动到新的一行。

为什么把CRLF分为两个操作

  • 打字机的CR操作为其提供了覆写一行文本的能力。这种能力可以用来产生加粗或是注音字符,下划线,划线字符(如: 这样)和一些组合符号。
  • 老式的打字机机架移动很慢,如果先LF,那么在执行CR操作时,打字机没有足够的时间完整打印出字符处理序列的下一个字符,可能会造成一些问题。先执行CR操作的话,下一个字符是LF(也许还有更多的填充字符,打字机处理这些填充字符的操作是不做任何事情),那么就能确保打字机在打印下一个可打印字符前有充足的时间完成CR操作。所以CRLF的顺序是CR然后是LF。
  • 这同时也使得将移动多行操作(例如打印两倍间距,带页头/页尾或是标题的页面)的时间压缩到使用单次CR操作的时间成为可能,这样就不需要处理冗余的CR信号,也就降低了与其相关的额外的电路或机械复杂性,从而使得打字机有更多的时间用来打印和传输。

CRLF的顺序对文本处理软件的影响

现代的打印机应该是没这些问题了,但是这些操作仍保留着。不同的操作系统对换行需要的特殊字符有不同的做法,如果CRLF的字符顺序为LF.CR,那么可能会使得文本处理软件错误的识别换行符(原以CRLF为换行单位的,现在用LF作为换行单位,那么CR就作为特殊字符显示出来了)。

Read more »

这篇文章只是个人笔记,如果没有实际使用过这些命令,请先自行阅读官方文档。

全局

配置个人信息

1
2
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

初始化git repo
git init

注意在Git 2.0之后你可能会遇到以下提示

When push.default is set to ‘matching’, git will push local branches to the remote branches that already exist with the same name.

Since Git 2.0, Git defaults to the more conservative ‘simple’ behavior, which only pushes the current branch to the corresponding remote branch that ‘git pull’ uses to update the current branch.

See ‘git help config’ and search for ‘push.default’ for further information. (the ‘simple’ mode was introduced in Git 1.7.11. Use the similar mode ‘current’ instead of ‘simple’ if you sometimes use older versions of Git)

Read more »

查看ArrayList源码时看到

1
transient Object[] elementData; // non-private to simplify nested class access

有点好奇使用默认权限而不是私有权限是怎么简化嵌套类访问过程的,先在Google中搜索相关内容,只找到对于这行代码中transientObject[]的讨论,所以我写了个测试类,然后查看两种权限下该类生成的字节码中有哪些差异。类的源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class CanNestedClassUsePrivateMember {
private int whatever;

class Inner {
void access() {
System.out.println(whatever);
}
}

public static void main(String[] args) {
new CanNestedClassUsePrivateMember().new Inner().access();
}
}

diff结果可以查看DiffChecker上的结果

Read more »

2018.12.1 现在最新版NexT主题已经集成了gitment,所以使用新版主题的朋友们就不需要再手动修改布局文件了。

  • 更新了文章的文件名,原来以序号为名,现在以文章标题的英文为名,更方便处理以及永久链接的留存。
  • 增加Gitment评论系统

已知问题: Gitment默认主题的编辑栏中Preview和Login两选项重合(在小屏访问时出现,且只能点击Preview)

添加Gitment进NexT主题

编辑themes/next/_config.yml

Read more »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        .file   "convert.c"
.text
.globl compute
.type compute, @function
compute:
.LFB0:
.cfi_startproc
movl $1, %eax
ret
.cfi_endproc
.LFE0:
.size compute, .-compute
.globl compute0
.type compute0, @function
compute0:
.LFB1:
.cfi_startproc
rep ret
.cfi_endproc
.LFE1:
.size compute0, .-compute0
.ident "GCC: (Debian 4.9.2-10) 4.9.2"
.section .note.GNU-stack,"",@progbits
1
2
3
4
5
6
int compute() {
return 1;
}
void compute0() {
//do nothing
}

可以看出compute和compute0函数在C上区别为返回值类型不同,在汇编上区别则体现在movl $1, %eax这一行上,$1是立即数(用来表示常熟之的操作数类型)1,%eax则是存放返回值的寄存器,这里的意思就是将1复制到%eax中。

那么也就是说当用到函数返回值时,其实是调用函数,然后去专门用来存放返回值的寄存器中取值。

rep ret相关可参考StackOverflow上的问答,其中高票答案提到

Read more »

记录学习使用Struts2框架时遇到的问题及其解决方案,使用的IDE为Intellij IDEA,Struts2版本为2.5.13。

初次部署

添加需要的库

  • commons-digester-2.1.jar
  • commons-fileupload-1.3.3.jar
  • commons-io-2.5.jar
  • commons-lang3-3.6.jar
  • commons-logging-1.1.3.jar
  • freemarker-2.3.23.jar
  • javassist-3.20.0-GA.jar
  • log4j-api-2.8.2.jar
  • ognl-3.1.15.jar
  • struts2-core-2.5.13

当然这里自己一个个地添加库是比较笨的方法,官网中有介绍如何用Maven来添加依赖和构建项目的教程。

Read more »

通过使用视图可以获得其他的实现了集合接口和映射表接口的对象。

轻量级集包装器

Arrays类的静态方法asList将返回一个包装了Java数组的List包装器。返回的对象不是ArrayList,而是一个视图对象,其来自于Arrays的内部类,源码如下:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;

ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}

@Override
public int size() {
return a.length;
}

@Override
public Object[] toArray() {
return a.clone();
}

@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}

@Override
public E get(int index) {
return a[index];
}

@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}

@Override
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}

@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}

@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(a, Spliterator.ORDERED);
}

@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
action.accept(e);
}
}

@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
E[] a = this.a;
for (int i = 0; i < a.length; i++) {
a[i] = operator.apply(a[i]);
}
}

@Override
public void sort(Comparator<? super E> c) {
Arrays.sort(a, c);
}
}

可以看到这个内部类并没有实现add和remove等方法,所以调用改变数组大小的所有方法都会抛出一个Unsupported OperationException异常(因为其继承自AbstractList,而该父类中add和remove等默认实现是抛出异常)。

Collections.nCopies(n, anObject)方法将返回一个实现了List接口的不可修改的对象,看起来像一个包含n个元素,每个元素都是一个anObject的对象,其源码如下:

1
2
3
4
5
public static <T> List<T> nCopies(int n, T o) {
if (n < 0)
throw new IllegalArgumentException("List length = " + n);
return new CopiesList<>(n, o);
}

而CopiesList的源码为:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
private static class CopiesList<E>
extends AbstractList<E>
implements RandomAccess, Serializable
{
private static final long serialVersionUID = 2739099268398711800L;

final int n;
final E element;

CopiesList(int n, E e) {
assert n >= 0;
this.n = n;
element = e;
}

public int size() {
return n;
}

public boolean contains(Object obj) {
return n != 0 && eq(obj, element);
}

public int indexOf(Object o) {
return contains(o) ? 0 : -1;
}

public int lastIndexOf(Object o) {
return contains(o) ? n - 1 : -1;
}

public E get(int index) {
if (index < 0 || index >= n)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+n);
return element;
}

public Object[] toArray() {
final Object[] a = new Object[n];
if (element != null)
Arrays.fill(a, 0, n, element);
return a;
}

@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
final int n = this.n;
if (a.length < n) {
a = (T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), n);
if (element != null)
Arrays.fill(a, 0, n, element);
} else {
Arrays.fill(a, 0, n, element);
if (a.length > n)
a[n] = null;
}
return a;
}

public List<E> subList(int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > n)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
return new CopiesList<>(toIndex - fromIndex, element);
}

// Override default methods in Collection
@Override
public Stream<E> stream() {
return IntStream.range(0, n).mapToObj(i -> element);
}

@Override
public Stream<E> parallelStream() {
return IntStream.range(0, n).parallel().mapToObj(i -> element);
}

@Override
public Spliterator<E> spliterator() {
return stream().spliterator();
}
}

实际上字符串对象只存储一次,所以付出的存储代价很小。

子范围

Read more »

代码使用Gist托管,部分地区可能加载不出来。点击查看更多以显示具体代码。

对应第二天自习的题解:

  1. 写一个计算第n个斐波那契数列的程序,递归、循环两种方法。

  2. 在分母为0的情况下,如何让运算符/返回0?

  3. 写一个程序,把二维数组中的所有数相加。

  4. 对列表增加一个名为myAverage的槽,以计算列表中所有数字的平均值。如果列表中没有数字会发生什么?(加分题:如果列表中有任何一项不是数字,则产生一个Io异常。)

  5. 对二维列表写一个原型。该原型的dim(x,y)方法可为一个包含y个列表的列表分配内存,其中每个列表都有x个元素,set(x,y,v)可设置列表中的值,get(x,y)方法可返回列表中的值。

  6. 加分题:写一个转置方法,使得原列表上的matrix get(x,y)与转置后列表的(new_matrix get(x,y))相等。

  7. 把矩阵写入文件,并从文件中读取矩阵。

  8. 写一个程序,提供10次尝试机会,猜一个1~100之间的随机数。如果你愿意的话,可以在第一次猜测后,提示猜大了还是猜小了。

参考:

Read more »

博客上第三篇日记

早上九点起床,去食堂过早之后到网咖玩了会游戏,十一点左右回宿舍。
中午看剧依然是《美国众神》,午饭点的外卖。
下午接着研究《设计模式》,把第二章实例研究:设计一个文档编辑器看完了,对其中涉及到八个设计模式以及设计模式是怎么解决对应的实际问题的有了一定的了解。读到3.1 抽象工厂时看到有段Smalltalk的代码:

1
2
make : partName
^ (partCatalog at : partName) copy

因为之前没有接触过Smalltalk,所以这种语法有点不理解,本想着不理解也没关系(示例基本有两个实现,一个是Smalltalk,还有一个则是用C++实现),但是出于好奇还是去Google相关资料来了解Smalltalk的基本语法规则。
找到了GNU Smalltalk User’s Guide,但是还没看。
想起自己买了本电子书,叫做《七周七语言 理解多种编程范型》,翻出来找到其中有一章讲到Io语言,于是开始按照书上的内容学习这一门原型语言,准备之后再看GNU Smalltalk的文档。Io官方文档
三点半休息了一会,下午四点钟起来去打了一个半小时的篮球,之后看了几个视频,出去吃晚餐以及参加周日的点评。

Read more »

博客上第二篇日记

昨天晚上追剧《美国众神》(American Gods),看到凌晨两点左右才睡下,所以早上十点起床出去逛了会儿,吃了点东西然后回宿舍。
带上《设计模式》、《操作系统》和《雾都孤儿》就去了图书馆,天气炎热,图书馆二层有些冷气因此位置都占满了,在三楼找了个位置坐下看书。
下午四点返回宿舍,路上买了两个包子作点心。回来后困得不行,趴在桌子上睡了一个多钟头。醒来又看了两集《美国众神》,晚餐点了鸡肉水果双拼披萨,味道不错。
接着研究反射,查看QQ消息时看到他们在讨论字符串是否符合数字格式的问题,也到网上查了查,其中有个方法是:

1
2
3
4
5
6
static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}

本来想研究下具体实现的,但是这几个方法返回值都以父类接收了,父类是一个接口,里面都是些抽象方法,而其中又涉及到

1
2
3
4
Locale locale = Locale.getDefault(Locale.Category.FORMAT);
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, locale);
NumberFormatProvider provider = adapter.getNumberFormatProvider();
NumberFormat numberFormat = provider.getNumberInstance(locale);

这几个方法。涉及类比较多,所以暂时没有继续深入,今天还是主要深入研究反射相关的官方文档并且实践。

Read more »

博客上第一篇日记

早早起来准备去上本学期最后一堂Android上机课,结果任课老师说考试都过了,还上什么课…
回宿舍路上买了几个包子作为早餐,在宿舍看了会儿新买的《设计模式:可复用面向对象软件的基础》。之后去篮球场上和同学打篮球,边打球边聊天,聊了关于家乡饮食习惯,大学社团,同学关系以及兴趣爱好的问题,能够和同学聊天还是蛮开心地。
对披萨的尺寸没什么概念,于是中午点了份水果披萨外卖,9寸大小,份量刚刚好,味道也还不错呢。
中午小憩了一会儿,起来看了几个英语的简单句示例。之后是看了几集《绝命律师》第三季(Better Call Saul)。
打开IDEA,打开Google Chrome,研究了一些问题:

  1. 关于反射(如何获取私有无参构造器->getDeclaredConstructor())
  2. 关于Atomic Classes,简单了解了下对应基本类型的原子操作,具体细节等实际学习并发时再作进一步研究
Read more »

两个月没写博客了,最近在看Flipboard上看文章时看见Mr.Weather作者的相关文章,在底部链接找到了作者的博客,发现是一位大三的CS专业的学生。看了几篇他的博文,想起我的博客也是好久没更新了,于是就有了将四月到六月的一些事情整理写出来。

学习

购买新书《深入理解计算机操作系统(原书第三版)》,相比学校相关教材《计算机操作系统(第四版)》,这本书是从程序员的角度来深入研究,学校这本教材则更多是着重于理论方面。
这几个月间断地阅读书籍,实体书有《Effective Java中文版》、《第一行代码》、《重构 改善既有代码的设计》、《深入理解计算机操作系统》、《C Primer Plus》和《雾都孤儿》,电子书有《HTTP权威指南》、《CSS设计指南》和《古龙文集》。技术书籍中大多是实际上碰到问题或是查阅资料时阅读的,部分是在系统的学习。可以看到其中有两本小说,也是在看的,我个人是最喜欢科幻小说了,不过武侠小说和名著也是偶尔会看的。

实践

学校项目

Read more »

ssh

安装ssh服务器

sudo apt install openssh-server 安装OpenSSH服务器
vim /etc/ssh/sshd_config 编辑sshd设置

新建ssh会话

ssh username@ip -p port

Read more »