最近一段时间在外奔波,停留最多的当属火车站、汽车站和公交站牌。在这些地方总可以看到年老的、残疾的、聋哑的人在向等待买票或坐车的人要钱。我所见到的人却也千奇百态,有全身烫伤身体大部分绑着白白的发黄的绷带的,有缺胳膊少腿的,有口眼歪斜的,这些人确实能让你一眼看出或者都不敢正眼看,他们是存在缺陷的弱势群体。我也遇到没有缺陷的年长的老人,二话不说直接跪倒在你面前,不给钱不起身。我还见到一对头发斑白的老人,在大冬天里,老头吹着呜哇哇的唢呐,老伴手里拿着个破旧的瘪瘪的铝碗,他们就这样在匆忙的人群中慢慢地走过。
我记得第一次见到行乞的人是我小的时候在小伙伴家玩,突然门外来了两个人,一个男人,三十多岁的样子,一个小男孩,十几岁。开始我并没有在意他们。男人说,行行好,给些钱给孩子看病吧。我这时才把目光转移到小男孩身上,他端着手臂,手腕靠上处插了根当时有我拇指粗的铁棍,铁棍已经生锈,留有血迹。我当时心里咯噔一下,心想这肯定很疼吧。这时候阿姨出来看到说,你这作大人的怎么把孩子弄成这样?男人说,家里没有钱治,行行好,给点钱。阿姨说,钱给你,你拿去花了,不给孩子看病怎么办?男人说,会的,我肯定给他看病去。阿姨去屋里拿出了十块钱说,你这可要赶紧去给孩子看病去,你看这孩子看着真让人心疼,才多大一点呢。男人接过钱说,我这就去医院。他们走后,阿姨说,这样的家长真不是人,把孩子弄成这样,孩子多遭罪啊。
他们忍受着痛楚,放下了尊严,厚着脸皮,去找人要钱。不知道他们的第一次是怎么开始的,我想也会内心纠结,久久不能安定很长时间吧。生活上如果还能过的过去,不到万不得已,谁又会去行乞呢。每每遇到他们,我总会想,凭我能做些什么改变些什么呢,国家又在哪里呢。我所没有见到的应该还有好多,这些人撑过了二十世纪来到了欣欣向荣的二十一世纪的社会主义大家庭,此时的国家繁荣昌盛,国家以及地方的GDP保持着高速增长,国家和地方财政也不差钱。为什么国家不能多关注这些人,把你那所存的高额的外汇稍微拿点出来,而不是作为对外宣传对内唱赞歌的虚无缥缈的数字,这对他们也就足够了。
我希望我们所能见到的所能感受到的是这个国家的人民实实在在地过得幸福,活得有尊严,社会充满关怀,而不是幸福祥和只在新闻里。
2011年1月7日星期五
2011年1月4日星期二
回来看看TK
我差点就忘了TK了,今天收到邮件说我的TK域名90天内少于30个流量,被终止使用了。 突然想起停用TK域名已经有很长时间了,只是没有注销域名。
TK是我使用的第一个域名。它是个很优秀的免费并且顶级的域名,支持中文,使用简单,功能丰富,提供免费的DNS服务。我使用它超过了三个月,在这期间从来没有出现过问题。
第一次注册账户时,怎么着都不行,之后挂上代理才通过。申请TK域名也极其简单,只要没有被占用就能很容易地被你占有,前提是每个月你要让这个域名有30个访问量。我开始很是担心会不会达不到这个最小值,之后开通了TiKinet发现流量根本就不是问题,只要你保证网站存在并可访问。
TK的使用教程网上也不少,这里只简单的列举出它的功能列表。
我的个人资料
我的域名
TiKinet
大使计划 (Ambassador Program)
TK Mailias
TK是我使用的第一个域名。它是个很优秀的免费并且顶级的域名,支持中文,使用简单,功能丰富,提供免费的DNS服务。我使用它超过了三个月,在这期间从来没有出现过问题。
第一次注册账户时,怎么着都不行,之后挂上代理才通过。申请TK域名也极其简单,只要没有被占用就能很容易地被你占有,前提是每个月你要让这个域名有30个访问量。我开始很是担心会不会达不到这个最小值,之后开通了TiKinet发现流量根本就不是问题,只要你保证网站存在并可访问。
TK的使用教程网上也不少,这里只简单的列举出它的功能列表。
我的个人资料
- 更改我的个人资料
- 更改我的密码
- 申请API
我的域名
- 我的域名列表
- 修改域名
- 添加一个新域名
- 注销域名
- 为域名付款/延期
- Dot TK Traffic Check
- 告诉一位朋友
TiKinet
- 更多访问者
- 建立我的TiKilink
- 修改我的TiKilink
- 删除我的TiKilink
- TiKinet selector
大使计划 (Ambassador Program)
- 关于大使计划 (Ambassador Program)
TK Mailias
- TK Mailias设置
- 隐私设置
2011年1月3日星期一
360又泄密了
这次360安全被竞争对手金山抓住了小辫子,360泄露的内容有“邮箱账号、密码,详尽的网页访问记录,甚至可以通过其邮箱、QQ号等信息直接对应上相应的真实用户”。
曾记否,前一段时间沸沸扬扬的360指责腾讯QQ扫描用户资料并偷偷上传,自己却打着“安全”、“保护隐私”、“用户至上”的幌子来招摇撞骗,现在又被“以其人之道还治其人之身”了。中国的互联网越来越有看头,搞的比法国大革命还复杂多变。只是受伤的总是用户,用户信任的心被来回碾压,“兴,用户苦;亡,用户苦”。
其实也不能全怪罪于他们,中国现今的软件环境本身如此,厂家为了和谐为了国家利益为了自家利益出卖用户又算得了什么,试问国内有哪一家软件或互联网商把用户利益和更要命的隐私放在第一位?
在中国做安全卫士还不如做安全套来得实在。
曾记否,前一段时间沸沸扬扬的360指责腾讯QQ扫描用户资料并偷偷上传,自己却打着“安全”、“保护隐私”、“用户至上”的幌子来招摇撞骗,现在又被“以其人之道还治其人之身”了。中国的互联网越来越有看头,搞的比法国大革命还复杂多变。只是受伤的总是用户,用户信任的心被来回碾压,“兴,用户苦;亡,用户苦”。
其实也不能全怪罪于他们,中国现今的软件环境本身如此,厂家为了和谐为了国家利益为了自家利益出卖用户又算得了什么,试问国内有哪一家软件或互联网商把用户利益和更要命的隐私放在第一位?
在中国做安全卫士还不如做安全套来得实在。
360又泄密了
这次360安全被竞争对手金山抓住了小辫子,360泄露的内容有“邮箱账号、密码,详尽的网页访问记录,甚至可以通过其邮箱、QQ号等信息直接对应上相应的真实用户”。
曾记否,前一段时间沸沸扬扬的360指责腾讯QQ扫描用户资料并偷偷上传,自己却打着“安全”、“保护隐私”、“用户至上”的幌子来招摇撞骗,现在又被“以其人之道还治其人之身”了。中国的互联网越来越有看头,搞的比法国大革命还复杂多变。只是受伤的总是用户,用户信任的心被来回碾压,“兴,用户苦;亡,用户苦”。
其实也不能全怪罪于他们,中国现今的软件环境本身如此,厂家为了和谐为了国家利益为了自家利益出卖用户又算得了什么,试问国内有哪一家软件或互联网商把用户利益和更要命的隐私放在第一位?
在中国做安全卫士还不如做安全套来得实在。
曾记否,前一段时间沸沸扬扬的360指责腾讯QQ扫描用户资料并偷偷上传,自己却打着“安全”、“保护隐私”、“用户至上”的幌子来招摇撞骗,现在又被“以其人之道还治其人之身”了。中国的互联网越来越有看头,搞的比法国大革命还复杂多变。只是受伤的总是用户,用户信任的心被来回碾压,“兴,用户苦;亡,用户苦”。
其实也不能全怪罪于他们,中国现今的软件环境本身如此,厂家为了和谐为了国家利益为了自家利益出卖用户又算得了什么,试问国内有哪一家软件或互联网商把用户利益和更要命的隐私放在第一位?
在中国做安全卫士还不如做安全套来得实在。
77元房
A:听说现在北京有每月77元的房子可租,在哪里呢?
B:在新闻联播里。
A:是啊,好激动哦,全北京人都在找这样的房子。
B:别傻了,南都派记者去都没有找到,我们这些凡夫俗子是找不到的。
A:哎,看来只能是天之骄子才能找到这么好的房子租了。
B:在新闻联播里。
A:是啊,好激动哦,全北京人都在找这样的房子。
B:别傻了,南都派记者去都没有找到,我们这些凡夫俗子是找不到的。
A:哎,看来只能是天之骄子才能找到这么好的房子租了。
心酸的成长——看小武
看似一部纪录片,没有任何高潮,情节支离破碎,人物单一,讲述的是主人公小武的故事。他不务正业,游手好闲,偷鸡摸狗,“凭手艺吃饭”,没理想,没工作,没女朋友。儿时的小伙伴贩烟成了企业家,娶了个漂亮的老婆,结婚也没有通知他,因为看不起他。
小武看上歌厅的胡梅梅,一个成熟历事的女孩,洒脱有主见,有梦想,爱唱歌。小武在她面前有着男孩子青涩的害羞,爱听她唱歌,自己不会唱也不好意思唱。想和她在一起,却又不知道干什么。
本以为他们间会有一段不大不小的爱情,可终归是没有的,小武买了戒指要送给她,她却随着太原老板消失了。为了和她联系,小武买了个传呼机。一次作案时,寻呼机突然响了,导致被抓。在警察局里,他一直关注着自己的寻呼机,等待着她的消息。
在被铐在路边时,不一会儿功夫就围上了好多路人,看着,笑着,小武不好意思地扭曲着身体蹲在地上。突然想到我小的时候逛集市,看到派出所大铁门上拷了个人,他周围围得人山人海,人们同样也是像是看耍猴似的笑着,而我们小孩子朝着他做鬼脸,我现在已经忘记了他的模样,只是记得他一直在低着头,默不作声。
这部电影总能看到儿时的自己或他人的影子。黑乎乎的房子和道路,破旧的小县城,灰白的阳光,写的大大的“拆”字的墙,都是那么地似曾相识。
现在的小武是否已经长大成熟,结婚生子,是否有了自己的理想,面对着未来不再迷茫?
小武看上歌厅的胡梅梅,一个成熟历事的女孩,洒脱有主见,有梦想,爱唱歌。小武在她面前有着男孩子青涩的害羞,爱听她唱歌,自己不会唱也不好意思唱。想和她在一起,却又不知道干什么。
本以为他们间会有一段不大不小的爱情,可终归是没有的,小武买了戒指要送给她,她却随着太原老板消失了。为了和她联系,小武买了个传呼机。一次作案时,寻呼机突然响了,导致被抓。在警察局里,他一直关注着自己的寻呼机,等待着她的消息。
在被铐在路边时,不一会儿功夫就围上了好多路人,看着,笑着,小武不好意思地扭曲着身体蹲在地上。突然想到我小的时候逛集市,看到派出所大铁门上拷了个人,他周围围得人山人海,人们同样也是像是看耍猴似的笑着,而我们小孩子朝着他做鬼脸,我现在已经忘记了他的模样,只是记得他一直在低着头,默不作声。
这部电影总能看到儿时的自己或他人的影子。黑乎乎的房子和道路,破旧的小县城,灰白的阳光,写的大大的“拆”字的墙,都是那么地似曾相识。
现在的小武是否已经长大成熟,结婚生子,是否有了自己的理想,面对着未来不再迷茫?
2011年1月2日星期日
Java学习笔记的整理
《Java学习笔记》,良葛格,清华大学出版社。
原名:林信良 网站:http://caterpillar.onlyfun.net/Gossip/ (繁体)
Java Gossip是作者Java的学习笔记。
以下是本人在原作的基础上根据个人实际情况整理的结果,版权归原作者所有。
1. Java版本发表是以JDK名称发表。
2. Java不再是表示程序语言,而是一种开发软件的平台,也是一种开发软件的标准和框架的总称。
3. 需要掌握的Java API有:字符串处理、异常处理、容器、输入/输出、线程。
4. Java技术论坛:http://www.javaworld.com/
5. 一个文件中可以编写数个类,但是只能有一个公开的类(public),而且主文件名必须与这个公开的类名一致。
6. main()方法一定是public成员,这样它才能够在执行环境中被调用;main()方法不需要产生对象(object)就能被执行,所以它必须是个static成员。Main()方法不需要返回任何值,所以一律定义为void.
7. System.out.println(); //使用Java.lang包下的System下的out对象所提供的println方法。
8. 取得使用者输入:
import java.util.Scanner;
public class HelloUser {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Please input your name: ");
System.out.printf("Hello! %s!", scanner.next());
}
}
"new"表示新增一個 Scanner物件,在新增一個 Scanner物件時需要一個System.in物件,因為實際上還是System.in在取得使用者的輸入,您可以將Scanner看作是 System.in物件的支援者,System.in取得使用者輸入之後,交給Scanner作一些處理。也就是使用它的next()方法來取得使用者的輸入字串。
9. 使用Scanner來取得使用者的輸入很方便,但是它以空白來區隔每一個輸入字串,在某些時候並不適用,因為使用者可能輸入一個字串,中間會包括空白字元,而您希望取得完整的字串。比较简单的方法是使用java.io.BufferedReader类取得输入。
import java.io.*;
public class Echo {
public static void main(String[] args) throws IOException {
BufferedReader buf = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("請輸入一列文字: ");
String text = buf.readLine();
System.out.println("您輸入的文字: " + text);
}
}
BufferedReader在构造時接受一個Reader对象,在 讀取標準輸入串流時,會使用InputStreamReader, 它繼承了Reader類。
10. autoboxing的作用就是把基本数据类型变成object来处理,unboxing的作用相反。
Autoboxing:
Integer integer = 10;
Unboxing:
Integer fooInteger = 10;
int fooPrimitive = fooInteger;
11. '=='可用來比較兩個基本型態的變數值是否相等,事實上'=='也用於判斷兩個object变量名稱是否指向同一個object.
12. 数组的定义与初始化:(简易方式)
int[] score = {90, 85, 55, 94, 77};
数组在Java中得看成对象,Java中的对象是以new来分配内存空间。完整的数组定义方式:
int[] arr = new int[10];
在使用new新增数组时一并指定初始值,不必指定数组长度:
int[] arr = new int[]{45,85,66,23,77};
动态配置数组长度:
import java.util.Scanner;
public class CustomArrayLength {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入Array大小: ");
int length = scanner.nextInt();
int[] arr = new int[length]; // 動態配置長度
System.out.println("Array長度: " + arr.length);
System.out.print("內容: ");
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
13. 二维数组初始化
int[][] arr = {{1, 2, 3},{4, 5, 6}};
在使用二維陣列物件時,注意length所代表的長度,陣列名稱直接加上length,所指的是有幾列(Row),而使用索引加上length,指的是該列所擁有的元素,也就是行(Column)數目。
二维数组定义:
int[][] arr = new int[2][3];
二维数组初始化(以对象形式):
int[][] arr = new int[][]{{1,2,3},{4,5,6}};
14. 数组元素值的复制
在Java中数组是一個object,而使用 = 指定時是將object指定給数组名稱來參考,而不是数组複製,如果您想將整個数组的值複製給另一個数组,您可以使用循环,將整個数组的元素值走訪一遍,並指定給另一個数组相對應的索引位置。
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
for(int i = 0; i < arr1.length; i++)
arr2[i] = arr1[i];
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
另一個更簡便的方法是使用System類別所提供的靜態方法arraycopy(),其語法如下:
System.arraycopy(來源, 起始索引, 目的, 起始索引, 複製長度);
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
在JDK 6中,Arrays 類別 新增了copyOf()方法,可以直接傳回一個新的陣列物件,而當中包括複製的內容,例如:
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
15. foreach与数组
例如傳統上循序存取一個陣列的方式如下:
int[] arr = {1, 2, 3, 4, 5};
for(int i = 0; i < arr.length; i++)
System.out.println(arr[i]);
在J2SE 5.0中可以這麼寫:
int[] arr = {1, 2, 3, 4, 5};
for(int element : arr)
System.out.println(element);
每次从arr中取出的元素,会自动设定给element,你不用自己判断是否超出了数组的长度,注意element的类型必须与数组元素的类型相同。
16.
一個字符串对象一旦被配置,它的內容就是固定不可變的(immutable),例如下面這個宣告:
String str = "caterpillar";
這個宣告會配置一個長度為11的字串物件,您無法改變它的內容。
String str = "just";
str = "justin";
它們兩個是不同的字符串对象,您並不是在 "just"字串後加上"in"字串,而是讓str名稱參考至新的字符串对象。
17.
String str1 = "flyweight";
String str2 = "flyweight";
System.out.println(str1 == str2);
程式的執行結果會顯示true,在Java中,會維護一個String Pool,對於一些可以共享的字串物件,會先在String Pool中查找是否存在相同的String內容(字元相同),如果有就直接傳回,而不是直接創造一個新的String物件,以減少内存的耗用。
18.
在 J2SE 5.0 提供StringBuilder類別,使用這個類別所產生的物件預設會有16個字元的長度,您也可以自行指定初始長度,如果附加至物件的字元超出可容納的長度,則StringBuilder物件會自動增加長度。
在StringBuilder中,length()可傳回目前物件中的字元長度,而capacity()可傳回該物件目前可容納的字元容量,下面這個程式是個簡單的示範:
public class UseStringBuilder {
public static void main(String[] args) {
StringBuilder strBuilder =
new StringBuilder("Knowledge is power!");
System.out.println("內容: " + strBuilder);
System.out.println("長度: " + strBuilder.length());
System.out.println("容量: " + strBuilder.capacity());
}
}
19. Main()方法的参数为String[] args,它就是用來接受一個字符串数组,您只要使用索引取出args中的元素值,就可以取出程式運行時的參數。
20. 使用类定义出对象的规范,再根据类来构建出一个个的对象,然后通过对象所提供的操作接口来与程序互动。屬性是对象的静态表现,而方法則是对象與外界互動的動態操作。
21. 在定义类时,您可以使用「构造方法」(Constructor)來進行对象的初始化。
22. 在构造方法中,您可以定義無參數的构造方法,或具有參數的构造方法,程式在運行時,會根據配置对象時所指定的参数型態等來決定,該使用哪一個构造方法。
23. 參數名稱與域成員名稱相同時,為了識別是參數或是域成員,我們必須明確的使用this參考來指定,但如果參數名稱與域成員名稱不相同則不用特别指定。
public Ball(double radius, String name) {
this.radius = radius;
this.name = name;
}
public Ball(double r, String n) {
radius = r; // 實際等於this.radius = r;
name = n; // 實際等於this.name = n;
}
24.
this除了上面的用法之外,還有一種可以帶參數的用法,主要是用於類中调用构造方法,而避免直接以构造方法的名稱來调用,例如:
public class Ball {
private String name;
public Ball() {
this("No name");
....
}
public Ball(String name) {
this.name = name;
....
}
}
25. 對於每一個基於相同類所產生的对象而言,其擁有各自的域成員,然而在某些時候,您會想要這些对象擁有相同的域成員,其域成员是共享的。这时候我们需要用static来标记,比如public static double PI = 3.14159; // 宣告static域成员
静态成员或者静态方法是用类名.来调用。由於static成員屬於類所擁有,所以在不使用对象名稱的情況下,您可以使用類名稱加上 . 運算子來存取static域成員。
26. 当类的成员声明为受保护的成员之后,继承的类就可以直接使用这些成员,不需要经过public方法。但这些成员依然受到保护,仅可以使用于对象内部或者子对象,不可以被外部对象直接使用。
27.
"final" 關鍵字可以使用在變數宣告時,表示該變數一旦設定之後,就不可以再改變該變數的值,例如在下面的程式碼中,PI這個變數一旦設定,就不可以再有指定值給 PI的動作:
final double PI = 3.14159;
如果在方法成員宣告時使用"final",表示該方法成員在無法被子類別重新定義(Override)
28. Java在实现多态时可以让程序依赖于抽象类或接口。
29. 當您定義類別時,可以僅宣告方法名稱而不實作當中的邏輯,這樣的方法稱之為「抽象方法」(Abstract method),如果一個類別中包括了抽象方法,則該類別稱之為「抽象類別」(Abstract class),抽象類別是個未定義完全的類別,所以它不能被用來生成对象,它只能被擴充,並於擴充後完成未完成的抽象方法定義。在Java中要宣告抽象方法與抽象類別,您使用"abstract"關鍵字.
30. 當您實作多個接口時,記得您必須實作每一個接口中所定義的方法,由於您實作了多個接口,所以要操作物件時,必要時您必須作「接口轉換」,如此程式才能知道如何正確的操作物件,例如假設someObject實作了ISomeInterface1與ISomeInterface2兩個接口,則我們可以如下對物件進行接口轉換與操作:
ISomeInterface1 obj1 = (ISomeInterface1) someObject;
obj1.doSomeMethodOfISomeInterface1();
ISomeInterface2 obj2 = (ISomeInterface2) someObject;
obj2.doSomeMethodOfISomeInterface2();
31. 使用內部類別的好處在於可以直接存取外部類別的私用(private)成員,另一個好處是,當某個Slave類別完全只服務於一個Master類別時,我們可以將之設定為內部類別,如此使用Master類別的人就不用知道 Slave的存在。
32. 匿名内部类可以不声明类名称,而是用new直接产生一个对象,它可以继承某个类或者某个接口。声明方式如下:
new [类或接口()] {
// 实现
}
public class UseInnerClass {
public static void main(String[] args) {
Object obj = new Object() {
public String toString() {
return "匿名類別物件";
}
};
System.out.println(obj.toString());
}
}
如果要在內部匿名類別中使用某個方法中的變數,此变量必须声明为final类型。究其原因,在於區域變量 x 並不是真正被拿來於內部匿名類中使用,而是在內部匿名類中複製一份,作為field成員來使用,由於是複本,即便您在內部匿名類別中對 x 作了修改,也不會影響真正的區域變數 x,事實上您也通不過編譯器的檢查,因為編譯器要求您加上"final"關鍵字,這樣您就知道您不能在內部匿名類別中改變 x 的值。
33. 當您使用"enum"定義枚举类型時,實質上您定義出來的类型繼承自 java.lang.Enum 類別,而每個列舉的成員其實就是您定義的枚举类型的一個實例(Instance),它們都被預設為 final,所以您無法改變它們,它們也是 static 成員,所以您可以透過型態名稱直接使用它們,當然最重要的,它們都 是公開的(public)。每个枚举类型的成员都是一个对象实例。
34. toString()方法被重新定義了,可以讓您直接取得列舉值的字串描述,而列舉物件定義的values ()方法可以讓您取得所有的列舉實例,並以陣列方式傳回,您使用這兩個方法來簡單的將OpConstants的內容顯示出來:
public class ShowEnum {
public static void main(String[] args) {
for(OpConstants constant: OpConstants.values()) {
System.out.println(constant.toString());
}
}
}
35. Collection 類包括了 List 類與 Set 類,List 以放置物件至容器中的順序來排列物件,Set 類不接受重覆的物件,並有自己的一套排序規則。
36. ArrayList实现了List接口,Arraylist使用数组结构实现List数据结构。使用add()方法可以將一個对象加入ArrayList中,使用size()方法可以傳回目前的ArrayList的長度,使用get()可以傳回指定索引處的对象,使用toArray()可以將ArrayList中的对象轉換為对象数组。
37. iterator()方法會傳回一個Iterator对象,這個对象提供的遍訪的方法,hasNext()方法測試Iterator中是否還有对象,如果有的話,可以使用next()取出。
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
使用增強的for循环可以直接遍訪List的所有元素,例如:
for(String s : list) {
System.out.print(s + " ");
}
38. 如果您會經常從容器中作移除或插入物件的動作,則使用LinkedList會獲得較好的效能。
39. 簡單的說,您將Map容器物件當作一個有很多間房間的房子,每個房間的門有一把鑰匙,您將物件儲存至房間中時,要順便擁有一把鑰匙,下次要取回物件時,就是根據這把鑰匙取得。
40. 容器:它不僅持有对象,還負責对象的生命周期與相關服務的連結。
41. Thread类也实现了Runnable接口,您也可以繼承Thread类並重新定義它的run()方法,好處是可以使用Thread上的一些繼承下來的方法,例如yield(),然而繼承了Thread就表示您不能讓您的类再繼承其它的类。
42. 在Java中要實現线程功能,可以实现Runnable接口,Runnable接口中只定義一個run()方法,然後實例化一個 Thread对象時,傳入一個实现Runnable接口的对象作為引數,Thread对象會調用Runnable对象的run()方法,進而執行當中所定義的流程。
43. 一個Daemon執行緒是一個在背景執行服務的執行緒,例如網路伺服器傾聽連接埠的服務、隱藏的系統執行緒如垃圾收集執行緒或其它JVM 建立的執行緒,如果所有的非Daemon的執行緒都結束了,則Daemon執行緒自動就會終止。
44. 從Main函式開始的是一個非Daemon執行緒,如果您希望某個執行緒在非Daemon執行緒都結束後也跟著終止,那麼您要將它設定為Daemon執行緒。
原名:林信良 网站:http://caterpillar.onlyfun.net/Gossip/ (繁体)
Java Gossip是作者Java的学习笔记。
以下是本人在原作的基础上根据个人实际情况整理的结果,版权归原作者所有。
1. Java版本发表是以JDK名称发表。
2. Java不再是表示程序语言,而是一种开发软件的平台,也是一种开发软件的标准和框架的总称。
3. 需要掌握的Java API有:字符串处理、异常处理、容器、输入/输出、线程。
4. Java技术论坛:http://www.javaworld.com/
5. 一个文件中可以编写数个类,但是只能有一个公开的类(public),而且主文件名必须与这个公开的类名一致。
6. main()方法一定是public成员,这样它才能够在执行环境中被调用;main()方法不需要产生对象(object)就能被执行,所以它必须是个static成员。Main()方法不需要返回任何值,所以一律定义为void.
7. System.out.println(); //使用Java.lang包下的System下的out对象所提供的println方法。
8. 取得使用者输入:
import java.util.Scanner;
public class HelloUser {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Please input your name: ");
System.out.printf("Hello! %s!", scanner.next());
}
}
"new"表示新增一個 Scanner物件,在新增一個 Scanner物件時需要一個System.in物件,因為實際上還是System.in在取得使用者的輸入,您可以將Scanner看作是 System.in物件的支援者,System.in取得使用者輸入之後,交給Scanner作一些處理。也就是使用它的next()方法來取得使用者的輸入字串。
9. 使用Scanner來取得使用者的輸入很方便,但是它以空白來區隔每一個輸入字串,在某些時候並不適用,因為使用者可能輸入一個字串,中間會包括空白字元,而您希望取得完整的字串。比较简单的方法是使用java.io.BufferedReader类取得输入。
import java.io.*;
public class Echo {
public static void main(String[] args) throws IOException {
BufferedReader buf = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("請輸入一列文字: ");
String text = buf.readLine();
System.out.println("您輸入的文字: " + text);
}
}
BufferedReader在构造時接受一個Reader对象,在 讀取標準輸入串流時,會使用InputStreamReader, 它繼承了Reader類。
10. autoboxing的作用就是把基本数据类型变成object来处理,unboxing的作用相反。
Autoboxing:
Integer integer = 10;
Unboxing:
Integer fooInteger = 10;
int fooPrimitive = fooInteger;
11. '=='可用來比較兩個基本型態的變數值是否相等,事實上'=='也用於判斷兩個object变量名稱是否指向同一個object.
12. 数组的定义与初始化:(简易方式)
int[] score = {90, 85, 55, 94, 77};
数组在Java中得看成对象,Java中的对象是以new来分配内存空间。完整的数组定义方式:
int[] arr = new int[10];
在使用new新增数组时一并指定初始值,不必指定数组长度:
int[] arr = new int[]{45,85,66,23,77};
动态配置数组长度:
import java.util.Scanner;
public class CustomArrayLength {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入Array大小: ");
int length = scanner.nextInt();
int[] arr = new int[length]; // 動態配置長度
System.out.println("Array長度: " + arr.length);
System.out.print("內容: ");
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
13. 二维数组初始化
int[][] arr = {{1, 2, 3},{4, 5, 6}};
在使用二維陣列物件時,注意length所代表的長度,陣列名稱直接加上length,所指的是有幾列(Row),而使用索引加上length,指的是該列所擁有的元素,也就是行(Column)數目。
二维数组定义:
int[][] arr = new int[2][3];
二维数组初始化(以对象形式):
int[][] arr = new int[][]{{1,2,3},{4,5,6}};
14. 数组元素值的复制
在Java中数组是一個object,而使用 = 指定時是將object指定給数组名稱來參考,而不是数组複製,如果您想將整個数组的值複製給另一個数组,您可以使用循环,將整個数组的元素值走訪一遍,並指定給另一個数组相對應的索引位置。
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
for(int i = 0; i < arr1.length; i++)
arr2[i] = arr1[i];
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
另一個更簡便的方法是使用System類別所提供的靜態方法arraycopy(),其語法如下:
System.arraycopy(來源, 起始索引, 目的, 起始索引, 複製長度);
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
在JDK 6中,Arrays 類別 新增了copyOf()方法,可以直接傳回一個新的陣列物件,而當中包括複製的內容,例如:
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
15. foreach与数组
例如傳統上循序存取一個陣列的方式如下:
int[] arr = {1, 2, 3, 4, 5};
for(int i = 0; i < arr.length; i++)
System.out.println(arr[i]);
在J2SE 5.0中可以這麼寫:
int[] arr = {1, 2, 3, 4, 5};
for(int element : arr)
System.out.println(element);
每次从arr中取出的元素,会自动设定给element,你不用自己判断是否超出了数组的长度,注意element的类型必须与数组元素的类型相同。
16.
一個字符串对象一旦被配置,它的內容就是固定不可變的(immutable),例如下面這個宣告:
String str = "caterpillar";
這個宣告會配置一個長度為11的字串物件,您無法改變它的內容。
String str = "just";
str = "justin";
它們兩個是不同的字符串对象,您並不是在 "just"字串後加上"in"字串,而是讓str名稱參考至新的字符串对象。
17.
String str1 = "flyweight";
String str2 = "flyweight";
System.out.println(str1 == str2);
程式的執行結果會顯示true,在Java中,會維護一個String Pool,對於一些可以共享的字串物件,會先在String Pool中查找是否存在相同的String內容(字元相同),如果有就直接傳回,而不是直接創造一個新的String物件,以減少内存的耗用。
18.
在 J2SE 5.0 提供StringBuilder類別,使用這個類別所產生的物件預設會有16個字元的長度,您也可以自行指定初始長度,如果附加至物件的字元超出可容納的長度,則StringBuilder物件會自動增加長度。
在StringBuilder中,length()可傳回目前物件中的字元長度,而capacity()可傳回該物件目前可容納的字元容量,下面這個程式是個簡單的示範:
public class UseStringBuilder {
public static void main(String[] args) {
StringBuilder strBuilder =
new StringBuilder("Knowledge is power!");
System.out.println("內容: " + strBuilder);
System.out.println("長度: " + strBuilder.length());
System.out.println("容量: " + strBuilder.capacity());
}
}
19. Main()方法的参数为String[] args,它就是用來接受一個字符串数组,您只要使用索引取出args中的元素值,就可以取出程式運行時的參數。
20. 使用类定义出对象的规范,再根据类来构建出一个个的对象,然后通过对象所提供的操作接口来与程序互动。屬性是对象的静态表现,而方法則是对象與外界互動的動態操作。
21. 在定义类时,您可以使用「构造方法」(Constructor)來進行对象的初始化。
22. 在构造方法中,您可以定義無參數的构造方法,或具有參數的构造方法,程式在運行時,會根據配置对象時所指定的参数型態等來決定,該使用哪一個构造方法。
23. 參數名稱與域成員名稱相同時,為了識別是參數或是域成員,我們必須明確的使用this參考來指定,但如果參數名稱與域成員名稱不相同則不用特别指定。
public Ball(double radius, String name) {
this.radius = radius;
this.name = name;
}
public Ball(double r, String n) {
radius = r; // 實際等於this.radius = r;
name = n; // 實際等於this.name = n;
}
24.
this除了上面的用法之外,還有一種可以帶參數的用法,主要是用於類中调用构造方法,而避免直接以构造方法的名稱來调用,例如:
public class Ball {
private String name;
public Ball() {
this("No name");
....
}
public Ball(String name) {
this.name = name;
....
}
}
25. 對於每一個基於相同類所產生的对象而言,其擁有各自的域成員,然而在某些時候,您會想要這些对象擁有相同的域成員,其域成员是共享的。这时候我们需要用static来标记,比如public static double PI = 3.14159; // 宣告static域成员
静态成员或者静态方法是用类名.来调用。由於static成員屬於類所擁有,所以在不使用对象名稱的情況下,您可以使用類名稱加上 . 運算子來存取static域成員。
26. 当类的成员声明为受保护的成员之后,继承的类就可以直接使用这些成员,不需要经过public方法。但这些成员依然受到保护,仅可以使用于对象内部或者子对象,不可以被外部对象直接使用。
27.
"final" 關鍵字可以使用在變數宣告時,表示該變數一旦設定之後,就不可以再改變該變數的值,例如在下面的程式碼中,PI這個變數一旦設定,就不可以再有指定值給 PI的動作:
final double PI = 3.14159;
如果在方法成員宣告時使用"final",表示該方法成員在無法被子類別重新定義(Override)
28. Java在实现多态时可以让程序依赖于抽象类或接口。
29. 當您定義類別時,可以僅宣告方法名稱而不實作當中的邏輯,這樣的方法稱之為「抽象方法」(Abstract method),如果一個類別中包括了抽象方法,則該類別稱之為「抽象類別」(Abstract class),抽象類別是個未定義完全的類別,所以它不能被用來生成对象,它只能被擴充,並於擴充後完成未完成的抽象方法定義。在Java中要宣告抽象方法與抽象類別,您使用"abstract"關鍵字.
30. 當您實作多個接口時,記得您必須實作每一個接口中所定義的方法,由於您實作了多個接口,所以要操作物件時,必要時您必須作「接口轉換」,如此程式才能知道如何正確的操作物件,例如假設someObject實作了ISomeInterface1與ISomeInterface2兩個接口,則我們可以如下對物件進行接口轉換與操作:
ISomeInterface1 obj1 = (ISomeInterface1) someObject;
obj1.doSomeMethodOfISomeInterface1();
ISomeInterface2 obj2 = (ISomeInterface2) someObject;
obj2.doSomeMethodOfISomeInterface2();
31. 使用內部類別的好處在於可以直接存取外部類別的私用(private)成員,另一個好處是,當某個Slave類別完全只服務於一個Master類別時,我們可以將之設定為內部類別,如此使用Master類別的人就不用知道 Slave的存在。
32. 匿名内部类可以不声明类名称,而是用new直接产生一个对象,它可以继承某个类或者某个接口。声明方式如下:
new [类或接口()] {
// 实现
}
public class UseInnerClass {
public static void main(String[] args) {
Object obj = new Object() {
public String toString() {
return "匿名類別物件";
}
};
System.out.println(obj.toString());
}
}
如果要在內部匿名類別中使用某個方法中的變數,此变量必须声明为final类型。究其原因,在於區域變量 x 並不是真正被拿來於內部匿名類中使用,而是在內部匿名類中複製一份,作為field成員來使用,由於是複本,即便您在內部匿名類別中對 x 作了修改,也不會影響真正的區域變數 x,事實上您也通不過編譯器的檢查,因為編譯器要求您加上"final"關鍵字,這樣您就知道您不能在內部匿名類別中改變 x 的值。
33. 當您使用"enum"定義枚举类型時,實質上您定義出來的类型繼承自 java.lang.Enum 類別,而每個列舉的成員其實就是您定義的枚举类型的一個實例(Instance),它們都被預設為 final,所以您無法改變它們,它們也是 static 成員,所以您可以透過型態名稱直接使用它們,當然最重要的,它們都 是公開的(public)。每个枚举类型的成员都是一个对象实例。
34. toString()方法被重新定義了,可以讓您直接取得列舉值的字串描述,而列舉物件定義的values ()方法可以讓您取得所有的列舉實例,並以陣列方式傳回,您使用這兩個方法來簡單的將OpConstants的內容顯示出來:
public class ShowEnum {
public static void main(String[] args) {
for(OpConstants constant: OpConstants.values()) {
System.out.println(constant.toString());
}
}
}
35. Collection 類包括了 List 類與 Set 類,List 以放置物件至容器中的順序來排列物件,Set 類不接受重覆的物件,並有自己的一套排序規則。
36. ArrayList实现了List接口,Arraylist使用数组结构实现List数据结构。使用add()方法可以將一個对象加入ArrayList中,使用size()方法可以傳回目前的ArrayList的長度,使用get()可以傳回指定索引處的对象,使用toArray()可以將ArrayList中的对象轉換為对象数组。
37. iterator()方法會傳回一個Iterator对象,這個对象提供的遍訪的方法,hasNext()方法測試Iterator中是否還有对象,如果有的話,可以使用next()取出。
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
使用增強的for循环可以直接遍訪List的所有元素,例如:
for(String s : list) {
System.out.print(s + " ");
}
38. 如果您會經常從容器中作移除或插入物件的動作,則使用LinkedList會獲得較好的效能。
39. 簡單的說,您將Map容器物件當作一個有很多間房間的房子,每個房間的門有一把鑰匙,您將物件儲存至房間中時,要順便擁有一把鑰匙,下次要取回物件時,就是根據這把鑰匙取得。
40. 容器:它不僅持有对象,還負責对象的生命周期與相關服務的連結。
41. Thread类也实现了Runnable接口,您也可以繼承Thread类並重新定義它的run()方法,好處是可以使用Thread上的一些繼承下來的方法,例如yield(),然而繼承了Thread就表示您不能讓您的类再繼承其它的类。
42. 在Java中要實現线程功能,可以实现Runnable接口,Runnable接口中只定義一個run()方法,然後實例化一個 Thread对象時,傳入一個实现Runnable接口的对象作為引數,Thread对象會調用Runnable对象的run()方法,進而執行當中所定義的流程。
43. 一個Daemon執行緒是一個在背景執行服務的執行緒,例如網路伺服器傾聽連接埠的服務、隱藏的系統執行緒如垃圾收集執行緒或其它JVM 建立的執行緒,如果所有的非Daemon的執行緒都結束了,則Daemon執行緒自動就會終止。
44. 從Main函式開始的是一個非Daemon執行緒,如果您希望某個執行緒在非Daemon執行緒都結束後也跟著終止,那麼您要將它設定為Daemon執行緒。
2011年1月1日星期六
Java学习笔记的整理
《Java学习笔记》,良葛格,清华大学出版社。
原名:林信良 网站:http://caterpillar.onlyfun.net/Gossip/ (繁体)
Java Gossip是作者Java的学习笔记。
以下是本人在原作的基础上根据个人实际情况整理的结果,版权归原作者所有。
1. Java版本发表是以JDK名称发表。
2. Java不再是表示程序语言,而是一种开发软件的平台,也是一种开发软件的标准和框架的总称。
3. 需要掌握的Java API有:字符串处理、异常处理、容器、输入/输出、线程。
4. Java技术论坛:http://www.javaworld.com/
5. 一个文件中可以编写数个类,但是只能有一个公开的类(public),而且主文件名必须与这个公开的类名一致。
6. main()方法一定是public成员,这样它才能够在执行环境中被调用;main()方法不需要产生对象(object)就能被执行,所以它必须是个static成员。Main()方法不需要返回任何值,所以一律定义为void.
7. System.out.println(); //使用Java.lang包下的System下的out对象所提供的println方法。
8. 取得使用者输入:
import java.util.Scanner;
public class HelloUser {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Please input your name: ");
System.out.printf("Hello! %s!", scanner.next());
}
}
"new"表示新增一個 Scanner物件,在新增一個 Scanner物件時需要一個System.in物件,因為實際上還是System.in在取得使用者的輸入,您可以將Scanner看作是 System.in物件的支援者,System.in取得使用者輸入之後,交給Scanner作一些處理。也就是使用它的next()方法來取得使用者的輸入字串。
9. 使用Scanner來取得使用者的輸入很方便,但是它以空白來區隔每一個輸入字串,在某些時候並不適用,因為使用者可能輸入一個字串,中間會包括空白字元,而您希望取得完整的字串。比较简单的方法是使用java.io.BufferedReader类取得输入。
import java.io.*;
public class Echo {
public static void main(String[] args) throws IOException {
BufferedReader buf = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("請輸入一列文字: ");
String text = buf.readLine();
System.out.println("您輸入的文字: " + text);
}
}
BufferedReader在构造時接受一個Reader对象,在 讀取標準輸入串流時,會使用InputStreamReader, 它繼承了Reader類。
10. autoboxing的作用就是把基本数据类型变成object来处理,unboxing的作用相反。
Autoboxing:
Integer integer = 10;
Unboxing:
Integer fooInteger = 10;
int fooPrimitive = fooInteger;
11. '=='可用來比較兩個基本型態的變數值是否相等,事實上'=='也用於判斷兩個object变量名稱是否指向同一個object.
12. 数组的定义与初始化:(简易方式)
int[] score = {90, 85, 55, 94, 77};
数组在Java中得看成对象,Java中的对象是以new来分配内存空间。完整的数组定义方式:
int[] arr = new int[10];
在使用new新增数组时一并指定初始值,不必指定数组长度:
int[] arr = new int[]{45,85,66,23,77};
动态配置数组长度:
import java.util.Scanner;
public class CustomArrayLength {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入Array大小: ");
int length = scanner.nextInt();
int[] arr = new int[length]; // 動態配置長度
System.out.println("Array長度: " + arr.length);
System.out.print("內容: ");
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
13. 二维数组初始化
int[][] arr = {{1, 2, 3},{4, 5, 6}};
在使用二維陣列物件時,注意length所代表的長度,陣列名稱直接加上length,所指的是有幾列(Row),而使用索引加上length,指的是該列所擁有的元素,也就是行(Column)數目。
二维数组定义:
int[][] arr = new int[2][3];
二维数组初始化(以对象形式):
int[][] arr = new int[][]{{1,2,3},{4,5,6}};
14. 数组元素值的复制
在Java中数组是一個object,而使用 = 指定時是將object指定給数组名稱來參考,而不是数组複製,如果您想將整個数组的值複製給另一個数组,您可以使用循环,將整個数组的元素值走訪一遍,並指定給另一個数组相對應的索引位置。
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
for(int i = 0; i < arr1.length; i++)
arr2[i] = arr1[i];
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
另一個更簡便的方法是使用System類別所提供的靜態方法arraycopy(),其語法如下:
System.arraycopy(來源, 起始索引, 目的, 起始索引, 複製長度);
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
在JDK 6中,Arrays 類別 新增了copyOf()方法,可以直接傳回一個新的陣列物件,而當中包括複製的內容,例如:
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
15. foreach与数组
例如傳統上循序存取一個陣列的方式如下:
int[] arr = {1, 2, 3, 4, 5};
for(int i = 0; i < arr.length; i++)
System.out.println(arr[i]);
在J2SE 5.0中可以這麼寫:
int[] arr = {1, 2, 3, 4, 5};
for(int element : arr)
System.out.println(element);
每次从arr中取出的元素,会自动设定给element,你不用自己判断是否超出了数组的长度,注意element的类型必须与数组元素的类型相同。
16.
一個字符串对象一旦被配置,它的內容就是固定不可變的(immutable),例如下面這個宣告:
String str = "caterpillar";
這個宣告會配置一個長度為11的字串物件,您無法改變它的內容。
String str = "just";
str = "justin";
它們兩個是不同的字符串对象,您並不是在 "just"字串後加上"in"字串,而是讓str名稱參考至新的字符串对象。
17.
String str1 = "flyweight";
String str2 = "flyweight";
System.out.println(str1 == str2);
程式的執行結果會顯示true,在Java中,會維護一個String Pool,對於一些可以共享的字串物件,會先在String Pool中查找是否存在相同的String內容(字元相同),如果有就直接傳回,而不是直接創造一個新的String物件,以減少内存的耗用。
18.
在 J2SE 5.0 提供StringBuilder類別,使用這個類別所產生的物件預設會有16個字元的長度,您也可以自行指定初始長度,如果附加至物件的字元超出可容納的長度,則StringBuilder物件會自動增加長度。
在StringBuilder中,length()可傳回目前物件中的字元長度,而capacity()可傳回該物件目前可容納的字元容量,下面這個程式是個簡單的示範:
public class UseStringBuilder {
public static void main(String[] args) {
StringBuilder strBuilder =
new StringBuilder("Knowledge is power!");
System.out.println("內容: " + strBuilder);
System.out.println("長度: " + strBuilder.length());
System.out.println("容量: " + strBuilder.capacity());
}
}
19. Main()方法的参数为String[] args,它就是用來接受一個字符串数组,您只要使用索引取出args中的元素值,就可以取出程式運行時的參數。
20. 使用类定义出对象的规范,再根据类来构建出一个个的对象,然后通过对象所提供的操作接口来与程序互动。屬性是对象的静态表现,而方法則是对象與外界互動的動態操作。
21. 在定义类时,您可以使用「构造方法」(Constructor)來進行对象的初始化。
22. 在构造方法中,您可以定義無參數的构造方法,或具有參數的构造方法,程式在運行時,會根據配置对象時所指定的参数型態等來決定,該使用哪一個构造方法。
23. 參數名稱與域成員名稱相同時,為了識別是參數或是域成員,我們必須明確的使用this參考來指定,但如果參數名稱與域成員名稱不相同則不用特别指定。
public Ball(double radius, String name) {
this.radius = radius;
this.name = name;
}
public Ball(double r, String n) {
radius = r; // 實際等於this.radius = r;
name = n; // 實際等於this.name = n;
}
24.
this除了上面的用法之外,還有一種可以帶參數的用法,主要是用於類中调用构造方法,而避免直接以构造方法的名稱來调用,例如:
public class Ball {
private String name;
public Ball() {
this("No name");
....
}
public Ball(String name) {
this.name = name;
....
}
}
25. 對於每一個基於相同類所產生的对象而言,其擁有各自的域成員,然而在某些時候,您會想要這些对象擁有相同的域成員,其域成员是共享的。这时候我们需要用static来标记,比如public static double PI = 3.14159; // 宣告static域成员
静态成员或者静态方法是用类名.来调用。由於static成員屬於類所擁有,所以在不使用对象名稱的情況下,您可以使用類名稱加上 . 運算子來存取static域成員。
26. 当类的成员声明为受保护的成员之后,继承的类就可以直接使用这些成员,不需要经过public方法。但这些成员依然受到保护,仅可以使用于对象内部或者子对象,不可以被外部对象直接使用。
27.
"final" 關鍵字可以使用在變數宣告時,表示該變數一旦設定之後,就不可以再改變該變數的值,例如在下面的程式碼中,PI這個變數一旦設定,就不可以再有指定值給 PI的動作:
final double PI = 3.14159;
如果在方法成員宣告時使用"final",表示該方法成員在無法被子類別重新定義(Override)
28. Java在实现多态时可以让程序依赖于抽象类或接口。
29. 當您定義類別時,可以僅宣告方法名稱而不實作當中的邏輯,這樣的方法稱之為「抽象方法」(Abstract method),如果一個類別中包括了抽象方法,則該類別稱之為「抽象類別」(Abstract class),抽象類別是個未定義完全的類別,所以它不能被用來生成对象,它只能被擴充,並於擴充後完成未完成的抽象方法定義。在Java中要宣告抽象方法與抽象類別,您使用"abstract"關鍵字.
30. 當您實作多個接口時,記得您必須實作每一個接口中所定義的方法,由於您實作了多個接口,所以要操作物件時,必要時您必須作「接口轉換」,如此程式才能知道如何正確的操作物件,例如假設someObject實作了ISomeInterface1與ISomeInterface2兩個接口,則我們可以如下對物件進行接口轉換與操作:
ISomeInterface1 obj1 = (ISomeInterface1) someObject;
obj1.doSomeMethodOfISomeInterface1();
ISomeInterface2 obj2 = (ISomeInterface2) someObject;
obj2.doSomeMethodOfISomeInterface2();
31. 使用內部類別的好處在於可以直接存取外部類別的私用(private)成員,另一個好處是,當某個Slave類別完全只服務於一個Master類別時,我們可以將之設定為內部類別,如此使用Master類別的人就不用知道 Slave的存在。
32. 匿名内部类可以不声明类名称,而是用new直接产生一个对象,它可以继承某个类或者某个接口。声明方式如下:
new [类或接口()] {
// 实现
}
public class UseInnerClass {
public static void main(String[] args) {
Object obj = new Object() {
public String toString() {
return "匿名類別物件";
}
};
System.out.println(obj.toString());
}
}
如果要在內部匿名類別中使用某個方法中的變數,此变量必须声明为final类型。究其原因,在於區域變量 x 並不是真正被拿來於內部匿名類中使用,而是在內部匿名類中複製一份,作為field成員來使用,由於是複本,即便您在內部匿名類別中對 x 作了修改,也不會影響真正的區域變數 x,事實上您也通不過編譯器的檢查,因為編譯器要求您加上"final"關鍵字,這樣您就知道您不能在內部匿名類別中改變 x 的值。
33. 當您使用"enum"定義枚举类型時,實質上您定義出來的类型繼承自 java.lang.Enum 類別,而每個列舉的成員其實就是您定義的枚举类型的一個實例(Instance),它們都被預設為 final,所以您無法改變它們,它們也是 static 成員,所以您可以透過型態名稱直接使用它們,當然最重要的,它們都 是公開的(public)。每个枚举类型的成员都是一个对象实例。
34. toString()方法被重新定義了,可以讓您直接取得列舉值的字串描述,而列舉物件定義的values ()方法可以讓您取得所有的列舉實例,並以陣列方式傳回,您使用這兩個方法來簡單的將OpConstants的內容顯示出來:
public class ShowEnum {
public static void main(String[] args) {
for(OpConstants constant: OpConstants.values()) {
System.out.println(constant.toString());
}
}
}
35. Collection 類包括了 List 類與 Set 類,List 以放置物件至容器中的順序來排列物件,Set 類不接受重覆的物件,並有自己的一套排序規則。
36. ArrayList实现了List接口,Arraylist使用数组结构实现List数据结构。使用add()方法可以將一個对象加入ArrayList中,使用size()方法可以傳回目前的ArrayList的長度,使用get()可以傳回指定索引處的对象,使用toArray()可以將ArrayList中的对象轉換為对象数组。
37. iterator()方法會傳回一個Iterator对象,這個对象提供的遍訪的方法,hasNext()方法測試Iterator中是否還有对象,如果有的話,可以使用next()取出。
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
使用增強的for循环可以直接遍訪List的所有元素,例如:
for(String s : list) {
System.out.print(s + " ");
}
38. 如果您會經常從容器中作移除或插入物件的動作,則使用LinkedList會獲得較好的效能。
39. 簡單的說,您將Map容器物件當作一個有很多間房間的房子,每個房間的門有一把鑰匙,您將物件儲存至房間中時,要順便擁有一把鑰匙,下次要取回物件時,就是根據這把鑰匙取得。
40. 容器:它不僅持有对象,還負責对象的生命周期與相關服務的連結。
41. Thread类也实现了Runnable接口,您也可以繼承Thread类並重新定義它的run()方法,好處是可以使用Thread上的一些繼承下來的方法,例如yield(),然而繼承了Thread就表示您不能讓您的类再繼承其它的类。
42. 在Java中要實現线程功能,可以实现Runnable接口,Runnable接口中只定義一個run()方法,然後實例化一個 Thread对象時,傳入一個实现Runnable接口的对象作為引數,Thread对象會調用Runnable对象的run()方法,進而執行當中所定義的流程。
43. 一個Daemon執行緒是一個在背景執行服務的執行緒,例如網路伺服器傾聽連接埠的服務、隱藏的系統執行緒如垃圾收集執行緒或其它JVM 建立的執行緒,如果所有的非Daemon的執行緒都結束了,則Daemon執行緒自動就會終止。
44. 從Main函式開始的是一個非Daemon執行緒,如果您希望某個執行緒在非Daemon執行緒都結束後也跟著終止,那麼您要將它設定為Daemon執行緒。
原名:林信良 网站:http://caterpillar.onlyfun.net/Gossip/ (繁体)
Java Gossip是作者Java的学习笔记。
以下是本人在原作的基础上根据个人实际情况整理的结果,版权归原作者所有。
1. Java版本发表是以JDK名称发表。
2. Java不再是表示程序语言,而是一种开发软件的平台,也是一种开发软件的标准和框架的总称。
3. 需要掌握的Java API有:字符串处理、异常处理、容器、输入/输出、线程。
4. Java技术论坛:http://www.javaworld.com/
5. 一个文件中可以编写数个类,但是只能有一个公开的类(public),而且主文件名必须与这个公开的类名一致。
6. main()方法一定是public成员,这样它才能够在执行环境中被调用;main()方法不需要产生对象(object)就能被执行,所以它必须是个static成员。Main()方法不需要返回任何值,所以一律定义为void.
7. System.out.println(); //使用Java.lang包下的System下的out对象所提供的println方法。
8. 取得使用者输入:
import java.util.Scanner;
public class HelloUser {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Please input your name: ");
System.out.printf("Hello! %s!", scanner.next());
}
}
"new"表示新增一個 Scanner物件,在新增一個 Scanner物件時需要一個System.in物件,因為實際上還是System.in在取得使用者的輸入,您可以將Scanner看作是 System.in物件的支援者,System.in取得使用者輸入之後,交給Scanner作一些處理。也就是使用它的next()方法來取得使用者的輸入字串。
9. 使用Scanner來取得使用者的輸入很方便,但是它以空白來區隔每一個輸入字串,在某些時候並不適用,因為使用者可能輸入一個字串,中間會包括空白字元,而您希望取得完整的字串。比较简单的方法是使用java.io.BufferedReader类取得输入。
import java.io.*;
public class Echo {
public static void main(String[] args) throws IOException {
BufferedReader buf = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("請輸入一列文字: ");
String text = buf.readLine();
System.out.println("您輸入的文字: " + text);
}
}
BufferedReader在构造時接受一個Reader对象,在 讀取標準輸入串流時,會使用InputStreamReader, 它繼承了Reader類。
10. autoboxing的作用就是把基本数据类型变成object来处理,unboxing的作用相反。
Autoboxing:
Integer integer = 10;
Unboxing:
Integer fooInteger = 10;
int fooPrimitive = fooInteger;
11. '=='可用來比較兩個基本型態的變數值是否相等,事實上'=='也用於判斷兩個object变量名稱是否指向同一個object.
12. 数组的定义与初始化:(简易方式)
int[] score = {90, 85, 55, 94, 77};
数组在Java中得看成对象,Java中的对象是以new来分配内存空间。完整的数组定义方式:
int[] arr = new int[10];
在使用new新增数组时一并指定初始值,不必指定数组长度:
int[] arr = new int[]{45,85,66,23,77};
动态配置数组长度:
import java.util.Scanner;
public class CustomArrayLength {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入Array大小: ");
int length = scanner.nextInt();
int[] arr = new int[length]; // 動態配置長度
System.out.println("Array長度: " + arr.length);
System.out.print("內容: ");
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
13. 二维数组初始化
int[][] arr = {{1, 2, 3},{4, 5, 6}};
在使用二維陣列物件時,注意length所代表的長度,陣列名稱直接加上length,所指的是有幾列(Row),而使用索引加上length,指的是該列所擁有的元素,也就是行(Column)數目。
二维数组定义:
int[][] arr = new int[2][3];
二维数组初始化(以对象形式):
int[][] arr = new int[][]{{1,2,3},{4,5,6}};
14. 数组元素值的复制
在Java中数组是一個object,而使用 = 指定時是將object指定給数组名稱來參考,而不是数组複製,如果您想將整個数组的值複製給另一個数组,您可以使用循环,將整個数组的元素值走訪一遍,並指定給另一個数组相對應的索引位置。
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
for(int i = 0; i < arr1.length; i++)
arr2[i] = arr1[i];
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
另一個更簡便的方法是使用System類別所提供的靜態方法arraycopy(),其語法如下:
System.arraycopy(來源, 起始索引, 目的, 起始索引, 複製長度);
public class AdvancedArray {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = new int[5];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
在JDK 6中,Arrays 類別 新增了copyOf()方法,可以直接傳回一個新的陣列物件,而當中包括複製的內容,例如:
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
for(int i = 0; i < arr2.length; i++)
System.out.print(arr2[i] + " ");
System.out.println();
}
}
15. foreach与数组
例如傳統上循序存取一個陣列的方式如下:
int[] arr = {1, 2, 3, 4, 5};
for(int i = 0; i < arr.length; i++)
System.out.println(arr[i]);
在J2SE 5.0中可以這麼寫:
int[] arr = {1, 2, 3, 4, 5};
for(int element : arr)
System.out.println(element);
每次从arr中取出的元素,会自动设定给element,你不用自己判断是否超出了数组的长度,注意element的类型必须与数组元素的类型相同。
16.
一個字符串对象一旦被配置,它的內容就是固定不可變的(immutable),例如下面這個宣告:
String str = "caterpillar";
這個宣告會配置一個長度為11的字串物件,您無法改變它的內容。
String str = "just";
str = "justin";
它們兩個是不同的字符串对象,您並不是在 "just"字串後加上"in"字串,而是讓str名稱參考至新的字符串对象。
17.
String str1 = "flyweight";
String str2 = "flyweight";
System.out.println(str1 == str2);
程式的執行結果會顯示true,在Java中,會維護一個String Pool,對於一些可以共享的字串物件,會先在String Pool中查找是否存在相同的String內容(字元相同),如果有就直接傳回,而不是直接創造一個新的String物件,以減少内存的耗用。
18.
在 J2SE 5.0 提供StringBuilder類別,使用這個類別所產生的物件預設會有16個字元的長度,您也可以自行指定初始長度,如果附加至物件的字元超出可容納的長度,則StringBuilder物件會自動增加長度。
在StringBuilder中,length()可傳回目前物件中的字元長度,而capacity()可傳回該物件目前可容納的字元容量,下面這個程式是個簡單的示範:
public class UseStringBuilder {
public static void main(String[] args) {
StringBuilder strBuilder =
new StringBuilder("Knowledge is power!");
System.out.println("內容: " + strBuilder);
System.out.println("長度: " + strBuilder.length());
System.out.println("容量: " + strBuilder.capacity());
}
}
19. Main()方法的参数为String[] args,它就是用來接受一個字符串数组,您只要使用索引取出args中的元素值,就可以取出程式運行時的參數。
20. 使用类定义出对象的规范,再根据类来构建出一个个的对象,然后通过对象所提供的操作接口来与程序互动。屬性是对象的静态表现,而方法則是对象與外界互動的動態操作。
21. 在定义类时,您可以使用「构造方法」(Constructor)來進行对象的初始化。
22. 在构造方法中,您可以定義無參數的构造方法,或具有參數的构造方法,程式在運行時,會根據配置对象時所指定的参数型態等來決定,該使用哪一個构造方法。
23. 參數名稱與域成員名稱相同時,為了識別是參數或是域成員,我們必須明確的使用this參考來指定,但如果參數名稱與域成員名稱不相同則不用特别指定。
public Ball(double radius, String name) {
this.radius = radius;
this.name = name;
}
public Ball(double r, String n) {
radius = r; // 實際等於this.radius = r;
name = n; // 實際等於this.name = n;
}
24.
this除了上面的用法之外,還有一種可以帶參數的用法,主要是用於類中调用构造方法,而避免直接以构造方法的名稱來调用,例如:
public class Ball {
private String name;
public Ball() {
this("No name");
....
}
public Ball(String name) {
this.name = name;
....
}
}
25. 對於每一個基於相同類所產生的对象而言,其擁有各自的域成員,然而在某些時候,您會想要這些对象擁有相同的域成員,其域成员是共享的。这时候我们需要用static来标记,比如public static double PI = 3.14159; // 宣告static域成员
静态成员或者静态方法是用类名.来调用。由於static成員屬於類所擁有,所以在不使用对象名稱的情況下,您可以使用類名稱加上 . 運算子來存取static域成員。
26. 当类的成员声明为受保护的成员之后,继承的类就可以直接使用这些成员,不需要经过public方法。但这些成员依然受到保护,仅可以使用于对象内部或者子对象,不可以被外部对象直接使用。
27.
"final" 關鍵字可以使用在變數宣告時,表示該變數一旦設定之後,就不可以再改變該變數的值,例如在下面的程式碼中,PI這個變數一旦設定,就不可以再有指定值給 PI的動作:
final double PI = 3.14159;
如果在方法成員宣告時使用"final",表示該方法成員在無法被子類別重新定義(Override)
28. Java在实现多态时可以让程序依赖于抽象类或接口。
29. 當您定義類別時,可以僅宣告方法名稱而不實作當中的邏輯,這樣的方法稱之為「抽象方法」(Abstract method),如果一個類別中包括了抽象方法,則該類別稱之為「抽象類別」(Abstract class),抽象類別是個未定義完全的類別,所以它不能被用來生成对象,它只能被擴充,並於擴充後完成未完成的抽象方法定義。在Java中要宣告抽象方法與抽象類別,您使用"abstract"關鍵字.
30. 當您實作多個接口時,記得您必須實作每一個接口中所定義的方法,由於您實作了多個接口,所以要操作物件時,必要時您必須作「接口轉換」,如此程式才能知道如何正確的操作物件,例如假設someObject實作了ISomeInterface1與ISomeInterface2兩個接口,則我們可以如下對物件進行接口轉換與操作:
ISomeInterface1 obj1 = (ISomeInterface1) someObject;
obj1.doSomeMethodOfISomeInterface1();
ISomeInterface2 obj2 = (ISomeInterface2) someObject;
obj2.doSomeMethodOfISomeInterface2();
31. 使用內部類別的好處在於可以直接存取外部類別的私用(private)成員,另一個好處是,當某個Slave類別完全只服務於一個Master類別時,我們可以將之設定為內部類別,如此使用Master類別的人就不用知道 Slave的存在。
32. 匿名内部类可以不声明类名称,而是用new直接产生一个对象,它可以继承某个类或者某个接口。声明方式如下:
new [类或接口()] {
// 实现
}
public class UseInnerClass {
public static void main(String[] args) {
Object obj = new Object() {
public String toString() {
return "匿名類別物件";
}
};
System.out.println(obj.toString());
}
}
如果要在內部匿名類別中使用某個方法中的變數,此变量必须声明为final类型。究其原因,在於區域變量 x 並不是真正被拿來於內部匿名類中使用,而是在內部匿名類中複製一份,作為field成員來使用,由於是複本,即便您在內部匿名類別中對 x 作了修改,也不會影響真正的區域變數 x,事實上您也通不過編譯器的檢查,因為編譯器要求您加上"final"關鍵字,這樣您就知道您不能在內部匿名類別中改變 x 的值。
33. 當您使用"enum"定義枚举类型時,實質上您定義出來的类型繼承自 java.lang.Enum 類別,而每個列舉的成員其實就是您定義的枚举类型的一個實例(Instance),它們都被預設為 final,所以您無法改變它們,它們也是 static 成員,所以您可以透過型態名稱直接使用它們,當然最重要的,它們都 是公開的(public)。每个枚举类型的成员都是一个对象实例。
34. toString()方法被重新定義了,可以讓您直接取得列舉值的字串描述,而列舉物件定義的values ()方法可以讓您取得所有的列舉實例,並以陣列方式傳回,您使用這兩個方法來簡單的將OpConstants的內容顯示出來:
public class ShowEnum {
public static void main(String[] args) {
for(OpConstants constant: OpConstants.values()) {
System.out.println(constant.toString());
}
}
}
35. Collection 類包括了 List 類與 Set 類,List 以放置物件至容器中的順序來排列物件,Set 類不接受重覆的物件,並有自己的一套排序規則。
36. ArrayList实现了List接口,Arraylist使用数组结构实现List数据结构。使用add()方法可以將一個对象加入ArrayList中,使用size()方法可以傳回目前的ArrayList的長度,使用get()可以傳回指定索引處的对象,使用toArray()可以將ArrayList中的对象轉換為对象数组。
37. iterator()方法會傳回一個Iterator对象,這個对象提供的遍訪的方法,hasNext()方法測試Iterator中是否還有对象,如果有的話,可以使用next()取出。
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
使用增強的for循环可以直接遍訪List的所有元素,例如:
for(String s : list) {
System.out.print(s + " ");
}
38. 如果您會經常從容器中作移除或插入物件的動作,則使用LinkedList會獲得較好的效能。
39. 簡單的說,您將Map容器物件當作一個有很多間房間的房子,每個房間的門有一把鑰匙,您將物件儲存至房間中時,要順便擁有一把鑰匙,下次要取回物件時,就是根據這把鑰匙取得。
40. 容器:它不僅持有对象,還負責对象的生命周期與相關服務的連結。
41. Thread类也实现了Runnable接口,您也可以繼承Thread类並重新定義它的run()方法,好處是可以使用Thread上的一些繼承下來的方法,例如yield(),然而繼承了Thread就表示您不能讓您的类再繼承其它的类。
42. 在Java中要實現线程功能,可以实现Runnable接口,Runnable接口中只定義一個run()方法,然後實例化一個 Thread对象時,傳入一個实现Runnable接口的对象作為引數,Thread对象會調用Runnable对象的run()方法,進而執行當中所定義的流程。
43. 一個Daemon執行緒是一個在背景執行服務的執行緒,例如網路伺服器傾聽連接埠的服務、隱藏的系統執行緒如垃圾收集執行緒或其它JVM 建立的執行緒,如果所有的非Daemon的執行緒都結束了,則Daemon執行緒自動就會終止。
44. 從Main函式開始的是一個非Daemon執行緒,如果您希望某個執行緒在非Daemon執行緒都結束後也跟著終止,那麼您要將它設定為Daemon執行緒。
人性的价值
买票
几年前过年回家到火车站买票,大老远就看到长长的队伍。站在队尾开始,在寒风中排了几十分钟,到我排到队伍中间时,突然想到这个队会不会不卖学生票,不卖的话岂不是瞎排了吗。只是我一个人过来,没人给我占着现在的位置,于是我就看了看后面,是个年青的小姑娘,我原以为她会很好说话,就笑呵呵的和她说,我先上前面问一下,等过会儿再回来。她好象是没听见,面无表情。我又重复了一遍,她还是没有说话。等我走出队伍,她马上紧紧地贴上了前面的人。
招聘
在人才市场,和招聘人员谈了好长时间,对方的感觉也挺好,就在最后填表格时,有一个选项是某证,我就说,我现在还没有这个证。还没等招聘人员回答,我后面的一个女生迅速漂移到我的前面说,没有这个证不行的,我有。
奖学金
某年学校奖学金评比,我让宿舍的室友把申请表一起递交上去,她满口答应地说好。等到奖学金结果公布出来,没有我的名字。室友直接和我说,当时你的申请表我没有交。
进修
我室友和我说后天我要去北京进修法语了,我很诧异地问,怎么这么突然,没听说你要走的呀。她说,其实好几个星期前就申请了,我一直没有说,现在才出来结果。
工作
某单位招聘,在网上发布消息,所见者甚少。偶尔看到后马上直接到单位面试,在面试厅见到了本班同学的一份简历。面试官问,是不是同班同学推荐你过来的呀。
人都是自私的,只是自私的度不一样。有些人为了利益草菅人命、损人利己,有些人在赚取利益时坚守着人性的价值。有人和我说过,在现实环境中人都是会变的,只是不管他怎么变,内心深处依旧还保持着原有的那份人性的纯真,那他就还是个好人。对于利益,赤条条来去无牵挂,能带去的又能有多少呢。
订阅:
博文 (Atom)