java 学习笔记《1》

来源:互联网 发布:网络语洗白是什么意思 编辑:程序博客网 时间:2024/06/01 19:07

======================================================
注:本文源代码点此下载
======================================================

1.??除了标准输出串流out之外,java程式在执行之后,还会开启标准输入串流in与标准错误输出串流err。对于in来说,它对应至键盘或其它的输入来源,准备接受使用者或其它来源的输入。而对于err,它会将指定的字串输出至显示装置或其它指定的装置,与标准输出串流out不同的是,它会立即显示指定的(错误)讯息给使用者知道,例如即使您指定程式将结果重新导向至档案,err输出串流的讯息并不会被重新导向,而仍会显示在指定的显示装置上,下面这个例子给您一个简单的测试方式: helloworld.java文件

1: public class helloworld {

2:public static void main(string[] args) {

3:system.out.println("hello! world!");

4:system.err.println("error message test");

5:}

6: }

但是在编译执行程序之后你会发现输出结果如下:

1: java helloworld >> output.txt

2: error message test

当我们开启output.txt之后,您会发现当中只有"hello! world!"讯息,而error message test讯息并没有被导向至档案中,而是直接显示在console(或终端机)中。

要重新导向标准输出是用 '>' ,标准输入则是 '>'除了重导标准输出之外,还有附加的功能,也就是会把输出附加到被导向的目标档案后头,如果目标档案本来不存在,那么效果就和'>'一样。

2.关于自动装箱和自动拆箱的一点问题。

自动装箱与拆箱是编译器在编译时期为您作好一切的事情,是 编译蜜糖(compiler sugar) ,这很方便,但在运行阶段您还是了解java的语义,例如下面的程式是可以通过编译的:

1: integer i = null;

2: int j = i;

通过测试我们可以知道,这段代码在编译期间完全是可以通过的。但是在运行时期会有错误,因为null表示i 没有参考至任何的物件实体,它可以合法的指定给物件参考名称,但null值对于基本型态j 的指定是不合法的,上面的写法在运行时会出现nullpointerexception的错误。再来看一个,先看看程式,您以为结果是如何?

1: integer i1 = 100;

2: integer i2 = 100;

3: if (i1 == i2)

4:system.out.println("i1 == i2");

5: else

6:system.out.println("i1 != i2");

先不说结果,我们在看看下面的这段代码:

1: integer i1 = 200;

2: integer i2 = 200;

3: if (i1 == i2)

4:system.out.println("i1 == i2");

5: else

6:system.out.println("i1 != i2");

你认为这个结果是什么呢?也许第一个正如你所猜想的。结果是i1==i2,但是我想第二个应该是出乎你的意料吧。因为这两段代码区别仅仅在于我改变了一个数值。经过运行我们可以知道,第二断代码的结果是:“i1!=i2”。为什么呢?

其实这与 '=='运算子 的比较有关,'=='可用来比较两个基本型态的变数值是否相等,事实上'=='也用于判断两个物件变数名称是否参考至同一个物件。

所以'=='可以比较两个基本型态的变数值是否相等,也可以判断两个物件变数的参考物件是否相同。 预设对于值从 -128到127 之间的值,它们被装箱为integer物件后,会存在记忆体之中被重用,所以当值在100,使用'=='进行比较时,i1与i2实际上参考至同一个物件。预设 如果超过了从-128到127之间的值,被装箱后的integer物件并不会被重用,即相当于每次都新建一个integer物件,所以当值在200,使用'=='进行比较时,i1与i2参考的是不同的物件。

所以不要过份依赖自动装箱与拆箱,您还是必须知道基本型态与物件的差异,上面的程式最好还是依正规的方式来写,而不是依赖编译蜜糖(compiler sugar),例如当值为200时,必须改写为以下才是正确的。

1: integer i1 = 200;

2: integer i2 = 200;

3:if (i1.equals(i2))

4:system.out.println("i1 == i2");

5: else

6:system.out.println("i1 != i2");

事实上在我们编写integer i=100;的时候,编译器其实将我们的代码转化为 integer i = integer.valueof(100); valueof()方法会将-128到127的值放到快取之中,以重复使用,这可以查看integer.java的原始码得知,如果是jdk5:

1: public static integer valueof(int i) {

2:final int offset = 128;

3:if (i >= -128 && i // must cache

4:return integercache.cache[i + offset];

5:}

6:return new integer(i);

7: }也就是在-128到127之间所产生的包裹物件,将会放到快取中重复使用 ,而在jdk6之后,则是这么写的:

1: public static integer valueof(int i) {

2:if(i >= -128 && i

3:return integercache.cache[i + 128];

4:else

5:return new integer(i);

6: }

7:

integercache.high预设是127,所以预设是 在-128到127之间所产生的包裹物件,将会放到快取中重复使用(可以透过设置属性

java.lang.integer.integercache.high来设定integercache.high的值) 。

3.对于数组。和c/c++一样,java中不存在多维数组,只有一维数组,而我们平时所说的“多维数组”其实就是数组的数组。在java里面,我们可以有如下的代码:

1: import java.util.scanner;

2:

3: public class customarraylength {

4:public static void main(string[] args) {

5:scanner scanner = new scanner(system.in);

6:

7:system.out.print("请输入array大小: ");

8:

9:int len??gth = scanner.nextint();

10:int[] arr = new int[length]; // 动态配置长度

11:

12:system.out.println("array长度: " + arr.length);

13:system.out.print("内容: ");

14:for(int i = 0; i

15:system.out.print(arr[i] + " ");

16:system.out.println();

17:}

18: }

请注意第9和第10行。在c++中我们不能写如下的代码片段:

1: #include

2: using namespace std;

3: int main(){

4:int i;

5:cin>>i;

6:int a[]=new int[i];

7:return 0;

8: }

然而我们在java中确实可以的.这一点希望对于c++程序员有一点点提醒.

另外提醒一下,在java中,数组是一个对象。当我们使用"="将对象指定给数组名的时候,并不是对于数组进行复制,而是将对象名指定给数组名进行引用。

对于对维数组我们在输出的时候可以采用加强的for 循环:

1: int [][] arr={ {1,2,3},

2:{1,2,3},

3:{1,2,3}

4:

5: };

6: for(int [] elment1 : arr)

7:for(int elment2 : elment1 )

8:system.out.println(elment2);

其次我们来谈谈对象数组吧.先来看下面的代码:

1: int[] arr=new int[3];你认为它产生了几个对象呢?答案是一个一维数组对象.

下面的呢?

1: int[][]arr=new int [2][3];产生了几个对象呢? 答案是3个对象.在进一步的说,

1: integer[] arr= new integer[3];产生了几个对象呢?答案还是一个对象数组.同理.对于 integer[][] arr =new integer[2][3];也是产生3个对象。

4.对于string.

一个字串物件一旦被配置,它的内容就是固定 不可变的(immutable) ,例如下面这个宣告:

string str = "caterpillar";

这个宣告会配置一个长度为11的字串物件,您无法改变它的内容;别以为下面这个宣告就是改变一个字串物件的内容:

string str = "just";

str = "justin";

串物件,您无法改变它的内容;别以为下面这个宣告就是改变一个字串物件的内容:

string str = "just";

str = "justin";

事实上在这个程序片段中,会有两个字串物件,一个是"just",长度为4,一个是"justin",长度为6,它们两个是不同的字串物件,您并不是

在"just"字串后加上"in"字串,而是让str名称参考至新的字串物件。

在java中,使用=将一个字串物件指定给一个名称,其意义为改变名称的参考物件,原来的字串物件若没有其它名称来参考它,就会在适当的时机

被java的 「垃圾回收」(garbage collection) 机制回收,在java中,程式设计人员通常不用关心无用物件的资源释放问题,java会检查物件

是否不再被参考,如果没有任何名称参考的物件将会被回收。

所以如果您在程式中使用下面的方式来宣告,则实际上是指向同一个字串物件:

1: string str1 = "flyweight";

2: string str2 = "flyweight";

3: system.out.println(str1 == str2);

程式的执行结果会显示true,在java中,会维护一个 string pool ,对于一些可以共享的字串物件,会先在string pool中查找是否存在相同的string

内容(字元相同),如果有就直接传回,而不是直接创造一个新的string物件,以减少记忆体的耗用。

谈到string pool,那就不能不提string的 intern() 方法,来看看它的api说明的节录:

returns a canonical representation for the string object.

a pool of strings, initially empty, is maintained privately by the class string.

when the intern method is invoked, if the pool already contains a string equal to this string object as determined by the

equals(object) method, then the string from the pool is returned. otherwise, this string object is added to the pool and a

reference to this string object is returned.

如果大家看过《设计模式》的话,应该可以想起flyweight模式。看个例子再说吧:

1: public class stringintern {

2:public static void main(string[] args) {

3:string str1 = "fly";

4:string str2 = "weight";

5:string str3 = "flyweight";

6:string str4;

7:

8:str4 = str1 + str2;

9:system.out.println(str3 == str4);

10:

11:str4 = (str1 + str2).intern();

12:system.out.println(str3 == str4);

13:}

14: } 在

在程式中第一次比较str3与str4物件是否为同一物件时,您知道结果会是false,而intern()方法会先检查string pool中是否存在字元部份相同的字串

物件,如果有的话就传回,由于程式中之前已经有"flyweight"字串物件,intern()在string pool中发现了它,所以直接传回,这时再进行比较,str3

与str4所指向的其实是同一物件,所以结果会是true。

注意到了吗? ==运算在java中被用来比较两个名称是否参考至同一物件,所以 不可以用==来比较两个字串的内容是否相同 ,例如:

1: string str1 = new string("caterpillar");

2: string str2 = new string("caterpillar");

3: system.out.println(str1 == str2);

4: system.out.println(str1.equals(str2));

 

或许结果在你的意料之中。前者为false,后者为true、

所以我们不能用“==”来比较两个字符串是否相等。另外说一句闲话,上面代码段的前3行产生了几个string的对象呢?很多人也许会认为是2个吧

,我之前也是这样,但是答案却是3个,别忘记“caterpillar”就是一个。它存在于string pool里面(⊙o⊙)哦,小盆友。

 


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
原创粉丝点击