public class FirstExample{
public static void main(String[] args){
System.out.println("we will not use 'hello world' ");
}
}
從這個程序中,我們可以知道哪些?
1 java對大小寫很敏感,main寫成Main,程序無法執行
2 public訪問修飾符,控制程序的其他部分對這段代碼的訪問級別
3 class表名java程序包含在類中,這裡,只需要將類作為一個加載程序邏
輯的容器,程序邏輯定義了應用程序的行為。
4 class後面跟的是類名,命名規則:類名是以大寫字母開頭的名詞。如果
名字由多個單詞組成,每個單詞的第一個字母都應該大寫。其他等同於標
識符的命名規則。
5 文件名與公有類的類名一致,如FirstExample.java
6 每個java應用程序必須有一個main方法
7 {}方法體開始和結束。每個句子必須用‘;’結束,回車不是結束的標志,因此,可以將一條java語句寫在多行上
8 System.out.println(),方法調用
9 “”引用字符串
10 方法可以沒有參數,也可以有多個參數,但必須用()表示例如,不帶
參數的println方法只打印一個空行。使用下面的語句:
System.out.println()
Note:
運行編譯程序時, Java虛擬機將從指定類中的main方法開始執行(這裡的“方法”就是Java中所說的“函數”),
因此為了代碼能夠執行,在類的源文件中必須包含一個main方法。當然,也可以將用戶自定義的方法添加到類中,
並且在main方法中調用它們。
根據Java語言規范, main方法必須聲明為public
Java的類與C++的類很相似,但還是有些差異會使人感到困惑。
例如, Java中的所有函數都屬於某個類的方法(標准術語將其稱為方法,而不是成員函數)。
因此, Java中的main方法必須有一個外殼類。讀者有可能對C++中的靜態成員函數( static member functions)十分熟悉。
這些成員函數定義在類的內部,並且不對對象進行操作。 Java中的main方法必須是靜態的。
最後,C/C++一樣,關鍵字void表示這個方法沒有返回值,所不同的是main方法沒有給操作系統返回“退出代碼”。
如果main方法正常退出,那麼Java應用程序的退出代碼為0,表示成功地運行了程序。
如果希望在終止程序時返回其他的代碼,那就需要調用System.exit方法。
與多數設計語言一樣,java中的注釋不會出現在可執行程序中。
注釋類型:
單行://注釋的內容
多行:/*注釋的內容 */
另一種:/**注釋的內容*/
Note:
在Java中, /* */注釋不能嵌套。也就是說,如果代碼本身包含了一個*/,就不能用/*和*/將注釋括起來。
四種整型,兩種浮點,一種char,一種Boolean
1 整型
在java中,整型的取值范圍固定,與平台無關,這就解決了移植性的問題,而c/c++需要針對不同的處理器選擇最為有效的整型,會導致整數溢出問題
2 浮點型
常量Double.POSITIVE_INFINITY、 Double.NEGATIVE_INFINITY和Double.NaN(與相應的Float類型的常量一樣),例如:
一個正整數除以0的結果為正無窮大。計算0/0或者負數的平方根結果為NaN。
檢測一個數是不是NaN,不能
if(x==Double.NaN)
//所有"非數值"的值都認為是不相同的。可以用Double.NaN(x)
if(Double.NaN(x))
3 char類型
記住以下幾點:
1 ‘A’和“A”不同:前者是字符常量65,後者是包含字符A的字符串
2 在”和”“中可以假如轉義字符,但只有\u可以不在內部,如\u005B和\u005D是(和)的編碼。
3 java中采用的UTF-16描述一個代碼單元
4 強烈建議不要在程序中使用char類型
4 boolean型
在C++中,數值或指針可以代替boolean值。整數0相當於布爾值false,非0值相當於布爾值true。在Java中則不行。
因此, Java應用程序員不會遇到下述麻煩:
if(x=0)//
在C++中這個測試可以編譯運行,其結果總是false。而在Java中,這個測試將不
能通過編譯,其原因是整數表達式x = 0不能轉換為布爾值。
記住一下幾點:
1 變量名區分大小寫
2 在c/c++,區分變量定義和聲明,如:
int i=10;//定義變量
extern int i;//聲明一個變量
java中不做區分,可以直接寫成:int i=10;//聲明,定義,初始化
3 與變量對應的就是常量,用final聲明,通常常量名使用大寫,常量不能更改,如:
final int PI=3.14;
4 希望某個常量可以在一個類中的多個方法中使用,通常將這些常量稱為類
常量。可以使用關鍵字static final設置一個類常量。需要注意,類常量的定義位於main方法的外部。
const是Java保留的關鍵字,但目前並沒有使用。在Java中,必須使用final定義常量。
關於運算符需要注意的一些問題:
1 整數除0會產生一個異常,浮點數除0則會得到無窮或NaN
2 自增運算符與自減運算符,舉個例子:
int m=7;
int n=7;
int a=2*++m;//m=8,a=16
int b=2*n++;//n=8,b=14
3 關系運算符與boolean運算符,舉個例子:
if(x!=0&&1/x>x+y)
當x為0時,不會計算第二部分。因此,若x為0, 1/x不被計算,也不會出現除以0的錯誤。&&和 || 是按照“短路”方式求值的。
4 位運算符(這個用的較少,但容易忽略)
&( "與")、 |( "或")、 ^( "異或")、 ~( "非")
“ >>”和“ <<”運算符將二進制位進行右移或左移操作
>>>運算符將用0填充高位; >>運算符用符號位填充高位。沒有<<<運算符
對移位運算符右側的參數需要進行模32的運算(除非左邊的操作數是long類型,在這種情況下需對右側操作數模64)。例如, 1 << 35與1 << 3或8是相同的。
5 數學函數和常量
舉個例子:
double x=4;
double y=Math.sqrt(x);
System.out.println(y);//print 2.0
Note:
println方法和sqrt方法存在微小的差異。 println方法操作一個定義在System類中的System.out對象。但是, Math類中的sqrt方法操作的不是對象,這樣的方法被稱為靜態方法。
提示:從JDK 5.0開始,不必在數學方法名和常量名前添加前綴“ Math.”,而只要在源文件的頂部加上下列內容就可以了。
例如:
import static java.lang.Math.*;
6 數值之間的轉換規則
貼個圖,不解釋
實心箭頭,表示無信息丟失的轉換;虛箭頭,表示可能有精度損失的轉換。
例如:123 456 789是一個大整數,它所包含的位數比float類型所能夠表達的位數多。當將這個整型數值轉換為float類型時,將會得到同樣大小的結果,但卻失去了一定的精度。
int n=123456789;
float f=n;//f is 1.234567892 E8
當使用數值進行二元運算時,先將兩個操作數轉換為同一類型,轉換規則如下:
如果兩個操作數中有一個是double類型的,另一個操作數就會轉換為double類型。
否則,如果其中一個操作數是float類型,另一個操作數將會轉換為float類型。
否則,如果其中一個操作數是long類型,另一個操作數將會轉換為long類型。
否則,兩個操作數都將被轉換為int類型。
強制轉換,舉個例子;
double x=9.997;
int n=(int)x;//n is 9
如果取最接近的整數,可以使用:
double x=9.997;
int n=(int)Math.round(x);//n is 10
不要在boolean類型與任何數值類型之間進行強制類型轉換,如果轉換可以使用條件表達式b? 1:0。
7 括號與運算符級別
如果不使用圓括號,就按照給出的運算符優先級次序進行計算。同一個級別的運算符按照從左到右的次序進行計算(除了表中給出的右結合運算符外。)
8 枚舉類型
這裡先不做解釋
從概念上講,java字符串就是Unicode字符序列。如,串“ Java\u2122”由5個Unicode字符J、 a、 v、 a和TM。java沒有內置的字符串類型(基本數據來了類型裡沒有),在java標准類庫裡提供了一個預定義的String類。每個“”括起來的都是字符串的一個實例:
String string="";//an empty string
String String="hello";//String是Java的一個類,類名是標識符,所以String可以做標識符。
String sizeof="sizeof";//There is no sizeof operator.Java中沒有sizeof運算符,所以sizeof可以作為標識符
1 子串
舉個例子:
String greeting="hello";
String s=greeting.subString(0,3);//s is hel
解釋一下subString函數:
第一個參數,從0位置開始;第二個參數,到3結束(0,1,2,不包括3)。
則求子串的長度就比較簡單,即3-0=3。
2 拼接
所謂拼接,即用+連接兩個字符串。舉個例子:
String a="hello";
String b="world";
int age=13;
String c=a+b;//c is helloworld
String d=a+age;//d is hello13
兩個原則:
1 單詞之間沒有空格, +號按照給定的次序將兩個字符串拼接起來
2 當將一個字符串與一個非字符串的值進行拼接時,後者被轉換成字符串
3 不可變字符串
String類沒有提供修改字符串的方法,如果希望將greeting的內容修改為“ Help!”,不能直接地將greeting的最後兩個位置的字符修改為‘ p’和‘ !’。在c中實現起來,就比較麻煩:
在這裡寫提一下,將字符串認為是字符型數組:
char greeting[]="hello";
這種認識是錯誤的, Java字符串更加像char*指針,
char *greeting="hello";
當采用另一個字符串替換greeting的時候, c代碼主要進行下列操作:
char *temp=malloc(6);
strncpy(temp,greeting,3);
strncpy(temp+3,"p!",3);
greeting=temp;
在Java中實現這項操作非常容易。首先提取需要的字符,然後再拼接上替換的字符串:
greeting=greeting.subString(0,3)+"p!";//greeting is help!
在java的源碼文檔中,將String類對象成為不可變字符串,在這裡會有一個疑問:
String greeting="hello";
greeting="help!";
以上代碼只是修改了greeting引用的地址,即原來引用的是“hello”,後來引用“help!”,那原來的“hello”去哪了?
這樣做會不會產生內存遺漏呢?畢竟,原始字符串放置在堆中。十分幸運, Java將自動地進行垃圾回收。如果一塊內存不再使用了,系統最終會將其回收。
當然,C++ string對象也自動地進行內存的分配與回收。內存管理是通過構造器、賦值操作和析構器顯式執行的。然而, C++字符串是可修改的,也就是說,可以修改字符串中的單個字符。
為什麼這麼設計?看起來好像修改一個代碼單元要比創建一個新字符串更加簡潔,效率更高?
答案是:也對,也不對。的確,通過拼接“ Hel”和“ p!”來創建一個新字符串的效率確實不高。但是,不可變字符串卻有一個優點:編譯器可以讓字符串共享。
為了弄清具體的工作方式,可以想像將各種字符串存放在公共的存儲池中。字符串變量指向存儲池中相應的位置。如果復制一個字符串變量,原始字符串與復制的字符串共享相同的字符。
總而言之, Java的設計者認為共享帶來的高效率遠遠勝過於提取、拼接字符串所帶來的低效率。查看一下程序會發現:很少需要修改字符串,而是往往需要對字符串進行比較。
4 檢查字符串是否相等
如果你認為比較是否相等,可以用“==”即可,那你就錯了,舉個例子:
String greeting="hello";//initialize greeting to a string
if(greeting="hello")...
//probably true
if(greeting.subString(0,3)=="hel")...
//probably false
why?
如果虛擬機始終將相同的字符串共享,就可以使用 == 運算符檢測是否相等。但實際上只有字符串常量是共享的,而+或substring等操作產生的結果並不是共享的。因此,千萬不要使用 == 運算符測試字符串的相等性,以免在程序中出現糟糕的bug。從表面上看,這種bug很像隨機產生的間歇性錯誤。
那在java中怎麼比較字符串是否相等?
String greeting=hello;
"hello".equals(greeting)...//true
"Hello".equalsIgnore(greeting)...//true,不區分大小寫,
Note:
對於習慣使用C++的string類的人來說,在進行相等性檢測的時候一定要特別
小心。
C++的string類重載了==運算符以便檢測字符串內容的相等性。可惜Java沒有采用這種方式,
它的字符串“看起來、感覺起來”與數值一樣,但進行相等性測試時,其操作方式又類似於指針。
語言的設計者本應該像對+那樣也進行特殊處理,即重定義 == 運算符。
當然,每一種語言都會存在一些不太一致的地方。C程序員從不使用 == 對字符串進行比較,而使用strcmp函數。
Java的compareTo方法與strcmp完全類似,因此,可以這樣使用:
if(greeting.comepareTo("hello")==0)...
不過,使用equals看起來更為清晰。
5 代碼點與代碼單元
什麼是代碼點和代碼單元?
Java中,char[]、String、StringBuilder和StringBuffer類中采用了UTF-16編碼,使用U+0000~U+FFFF來表示一個基本字符(BMP字符),但是位於U+D800到U+DBFF和U+DC00到U+DFFF的char被視為無定義字符。大多數的常用Unicode字符使用一個代碼單元就可以表示,而輔助字符需要一對代碼單元表示。即:基本字符用一個char表示,輔助字符使用一對char表示。
Java使用代碼點(Unicode code pointer)這個概念來表示范圍在U+0000與U+10FFFF之間的字符值(int型),代碼單元(Unicode code unit)表示作為UTF-16編碼的代碼單元的 16位char值(char型)。也就是說,可能存在一個字符,它的代碼點數量是1,而代碼單元數量是2。所以,代碼單元的數量並不一定是字符的數量。
相比之下,代碼單元更加偏底層。
相關函數:
length()函數返回采用UTF-16編碼標識的給定字符串所需要的代碼單元的數量。
codePointCount()函數返回采用UTF-16編碼標識的給定字符串所需要的代碼點的數量。
測試程序:
package com.xujin;
public class Test{
public static void main(String...args){
char[] ch = Character.toChars(0x10400);
System.out.printf("U+10400 高代理字符: %04x\n", (int)ch[0]);//d801
System.out.printf("U+10400 低代理字符: %04x\n", (int)ch[1]);//dc00
String str = new String(ch);
System.out.println("代碼單元長度: " + str.length());//2
System.out.println("代碼點數量: " + str.codePointCount(0, str.length()));//1
System.out.println(str.codePointAt(0));//返回給定位置開始或結束的代碼點,66560
System.out.println(str.charAt(1));//返回給定位置的代碼單元,由於未定義,返回?
//遍歷一個字符串,打印出所有字符的代碼點
str += "Hello,world!";
int i = 0;
int cp = str.codePointAt(i);
while(i < str.length()){
System.out.println(str.codePointAt(i));
if(Character.isSupplementaryCodePoint(cp))
i += 2;//如果cp所在的位置是代碼點的第一部分,執行此處
else i++;
}
/*
* 66560
* 72
* 108
* 111
* 119
* 114
* 100
*/
}
}
java字符串是由char序列組成,char是一個采用UTF-16編碼表示
Unicode代碼點的代碼單元。常用Unicode字符使用一個代碼單元就可以表示,而輔助字符需要一對代碼單元表示。
length方法將返回采用UTF-16編碼表示的給定字符串所需要的代碼單元數量。例如:
String greeting="hello";
int l=greeting.length();//5
要想得到實際的長度,即代碼點數量,可以調用:
int cpCount = greeting.codePointCount(0, greeting.length() );
//為什麼說這個是實際長度?
調用s.charAt(n) 將返回位置n的代碼單元, n介於0~s.length()-1之間。例如:
char first=greeting.charAt(0);//first is h
char last=greeting.charAt(4);//last is o
//返回字符
//要想得到第 i 個代碼點,應該使用下列語句
int index = greeting.offsetByCodePoints(0, i);
int cp = greeting.codePointAt(index);
//返回ascii值
6 字符串API