學習編程語言的通許遇到的第一個程序無非打印"Hello, world"了,然而在Java中要寫成
System.out.我們都會感覺太冗長了,能不能簡單一些呢?靜態導入可以省略掉System,就像這樣
import static java.lang.System.*;public class Hello { public static void main(String[] args) { out.println("Hello, world"); }}能不能再簡單一些呢?像C語言那樣?實際上,這里的System是類,out是System的一個PrintStream類型的靜態成員,因為在System類中是這樣寫的
public final class System { // ...... public final static PrintStream out = null; // ......}可以得到啟發,自己也寫一個類,然后靜態導入此類,就可以像C語言那樣直接輸出內容了
package p1;import static java.lang.System.*;public class Print { public static void println(String x) { out.println(x); }}然后寫一個Hello程序
import static p1.Print.*;public class Hello{ public static void main(String[] args) { println("Hello,world"); }}NOTE:大家可以將自己寫的打印輸出類打包成jar文件,使用命令jar cvf p1.jar p1/Print.class,其中p1是包名,Print是類名,然后放在jdk目錄下的lib目錄中,比如D:/jdk/lib/p1.jar,然后修改環境變量,在CLASSPATH中添加%JAVA_HOME%/lib/p1.jar,這樣就可以一勞永逸了,只需要import static p1.Print.*;就可以直接使用println方法了。
3.2使用Java操作符這里提到操作符的副作用,這篇博文講得很詳細http://www.companysz.com/lazycoding/archive/2011/04/27/side-effect.html
簡單說,變量X在一個表達式的運算后,如果值未變,操作符沒有副作用,如果值改變了,操作符產生副作用。
3.3優先級
優先級 | 運算符 | 結合性 |
1 | ( ) [ ] . | 從左至右 |
2 | ! +(正) -(負) ~ ++(遞增) --(遞減) | 從右向左 |
3 | * / % | 從左至右 |
4 | +(加) -(減) | 從左至右 |
5 | << >> >>> | 從左至右 |
6 | < , <= , > , >= , instanceof | 從左至右 |
7 | == != | 從左至右 |
8 | &(按位與) | 從左至右 |
9 | ^(異或) | 從左至右 |
10 | |(按位或) | 從左至右 |
11 | &&(邏輯與,短路與) | 從左至右 |
12 | ||(邏輯或,短路或) | 從左至右 |
13 | ?: | 從右向左 |
14 | = , += , -= , *= , /= , %= , &= , |= , ^= , ~=,<<= , >>= , >>>= | 從右向左 |
其實不需要刻意去記,因為萬能的小括號( )可以減少錯誤,還使程序易于閱讀。
3.4賦值賦值很簡單,不外乎為一個變量賦值,比如
int x = 5;
初學者需要注意的是左值的問題,不能寫成
int x = 5;2 = x;// 左值不能是直接量,常量x + 1 = 5;// 左值不能是表達式3.5算術操作符
算術操作符有 +(加), -(減),*(乘),/(除),%(取模)
int sum = 9 - 8 + 6 / 3 * 5 % 3;// sum = 2
這5個算術操作符只是數學的基本的運算符,自然會像數學那樣先乘除取模,再加減。所以這個例子中,先是6 / 3 = 2,再2 * 5 = 10,再10 % 3 = 1,最后9 - 8 + 1 = 2
為了簡化語句,可以使用C語言那樣的簡化操作符,如下
int a = 5;int b = 6;int c;int d = a += b -= c = 2;// d = 9
如優先級第 14 行所述,賦值和簡化操作符都是從右至左地運算的,因此上面的程序先是c = 2,再是b -= c,得出b =4,接著是a += b,得出a = 9,最后是d = a,得出d = 9。
3.6自動遞增和遞減遞增操作符分為前綴遞增和后綴遞增,遞減操作符也分為前綴遞增和后綴遞減,分別是
x++ 和 ++x, x-- 和 --x
前綴遞增 ++x 的意思是先對 x 加1,然后再使用 x;而后綴遞增 x++ 的意思是先使用 x,再對 x 加1,遞減操作符也是同樣的道理,比如下面的程序
int a = 5;print(++a);// 6int b = 5;print(b++);// 5int c = 5;print(--c);// 4int d = 5;print(c--);// 5
再看復雜一點的程序
int x = 5;int y = x++ + x-- + ++x + --x;// x = 5, y = 22
上面的程序相當于
int x = 5;int y = x++;y = x--;y = ++x;y = --x;
注意,不能對同一個變量使用2個或2個以上的遞增遞減操作符,比如下面的程序
x++--;// 錯誤,不能對同一個變量同時使用2個遞增遞減操作符3.7關系操作符
關系操作符有<(小于),<=(小于或等于),>(大于),>=(大于或等于),==(等于)和!=(不等于),運算的結果是一個boolean值,如下所示
int x = 7;out.print(x < 8); // trueout.print(x <= 8);// trueout.print(x > 8); // falSEOut.print(x >= 8);// falseout.print(x == 8);// falseout.print(x != 8);// true
== 和 != 還可以用來比較對象,比如
public class Person { private int age; public Person(int newAge) { age = newAge; } public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; Person xiaoMing = new Person(18); Person xiaoFu = new Person(18); out.println(s1 == s2);// true out.println(xiaoMing == xiaoFu);// false }}
結果出乎意料了,第 11 行是true,可第 12 行卻是false!這是因為,== 和 != 比較的是對象的地址,而非對象的內容。String類型的 s1 和 s2 引用的是同樣一個字符串常量,因此相等,而Person類型的xiaoMing和xiaoFu雖然內容一樣,但是屬于兩個不同的對象,就像同一班里有兩個小明,雖然它們年齡相等,但是他們的基因不一樣。
既然這樣,那我們應該如何比較兩個對象的內容呢?可以使用從根類Object繼承下來的equals()方法
out.println(s1.equals(s2));// trueout.printlnl(xiaoMing.equals(xiaoFu));// false
結果又讓人費解,為什么第 1 行的結果是true,而第 2 行的結果還是false?其實類String覆蓋了類Object的equals()方法,而這個例子尚未覆蓋它,實際上從類Object繼承的equals()方法默認是這樣的
public boolean equals(Object obj) { return (this == obj);}
我們可以在類Person中重寫(覆蓋)equals()方法,然后比較兩個對象,如下
public class Person { private int age; public Person(int newAge) { age = newAge; } public boolean equals(Object obj) { if (age == ((Person)obj).age) return true; else return false; } public static void main(String[] args) { Person xiaoMing = new Person(18); Person xiaoFu = new Person(18); out.println(xiaoMing.equals(xiaoFu));// true }}
我們再來看看兩個String對象的比較,如下
String s1 = "abc";String s2 = "abc";String s3 = new String("abc");String s4 = new String("abc");out.println(s1 == s2);// trueout.println(s2 == s3);// falseout.println(s3 == s4);// falseout.println(s2.equals(s3));// true
實際上,引用變量s1所指向的字符串常量"abc"是放在常量池的,當s2也要引用"abc"時,JVM并不會再開辟一個內存空間,而是讓s2也引用已經存在的"abc",因此s1會等于s2。s3和s4就不同了,它們所引用的對象是存在于堆中,而且是不同的對象,盡管它們的內容相同,所以兩者是不相等的。由于類String實現了equals()方法,使之能比較兩String對象的內容,而不是地址,所以第 8 行的結果是true。
3.8邏輯操作符邏輯操作符“與”(&&)、“或”(||)、“非”(!)能根據參數的邏輯關系,生成一個布爾值(true或false)。
值得注意的是,&& 和 || 是短路的,比如 p&&q,如果 p 為假,則不必再計算 q,如果 p 為真,則繼續計算 q,比如 p||q,如果 p 為真,則不必計算 q,如果 p 為假,則繼續計算 q。
public class Demo { boolean flag; public static void main(String[] args) { boolean x = new Demo(false).flag && new Demo(true).flag && new Demo(true).flag;// false boolean y = new Demo(false).flag || new Demo(true).flag || new Demo(true).flag;// false true } Demo(boolean newFlag) { flag = newFlag; print(flag + " "); }}
上面的程序,因為短路,第 5 行的結果是false和空格,第7行的結果是false true和空格
3.9直接常量直接引用《Java編程思想》的代碼
public class Literals { public static void main(String[] args) { int i1 = 0x2f;//十六進制,小寫 out.println("i1: " + Integer.toBinaryString(i1)); int i2 = 0X2F;//十六進制,大寫 out.println("i2: " + Integer.toBinaryString(i2)); int i3 = 0177;//八進制,以0開始 out.println("i3: " + Integer.toBinaryString(i3)); char c = 0xffff;//十六進制,char類型的最大值 out.println("c: " + Integer.toBinaryString(c)); byte b = 0x7f;//十六進制,byte的最大值 out.println("b: " + Integer.toBinaryString(b)); short s = 0x7fff;//十六進制,short的最大值 out.println("s: " + Integer.toBinaryString(s)); long n1 = 200L;//long類型,后綴大L long n2 = 200l;//long類型,后綴小l long n3 = 200;//long類型,無后綴 float f1 = 1;//float類型,無后綴 float f2 = 1F;//float類型,后綴大F float f3 = 1f;//float類型,后綴小f double d1 = 1d;//double類型,后綴小d double d2 = 1D;//double類型,后綴大D }}/*輸出結果i1: 101111i2: 101111i3: 1111111c: 1111111111111111b: 1111111s: 111111111111111*/
在C、C++或者Java中,二進制都沒有直接常量的表示方法,不過用十六進制和八進制來表示二進制會更加直觀、簡潔和更易于閱讀。
既然是直接常量,程序就休想修改它的值了,比如下面的代碼不能編譯
int x = ++5;3.10按位操作符
按位操作符用來操作整數基本數據類型中的單個“比特”(bit),即補碼的二進制位。按位操作符會對兩個參數中對應的位執行布爾代數運算,并最終生成一個結果。
按位操作符有 按位與(&)、按位或(|)、按位異或(^)和按位非(~),它們的計算方式如下
實際應用如下:
十進制7的補碼:00000111十進制9的補碼:000010017 & 9,即 00000111 & 00001001 = 00000001(十進制1)7 | 9,即 00000111 | 00001001 = 00001111(十進制15)7 ^ 9,即 00000111 ^ 00001001 = 00001110(十進制14)~7, 即 ~00000111 = 11111000(十進制-8)
按位操作符和邏輯操作符都使用了同樣的符號,因此我們能方便地記住它們的含義:由于位是非常“小”的,所以按位操作符僅使用了一個字符。
按位操作符可與等號(=)聯合使用,以便合并運算和賦值:&=、|=、和^=都是合法的(由于~是一元操作符,所以不存在~=)
我們將布爾類型作為一種單bit值對待,因而它會有些獨特。對于布爾值,用按位操作符的話,將不再短路。我們可以對布爾值進行&、|、^,但不能~(為了避免與!混淆),其中按位異或(^)使用如下
boolean p = true;boolean q = false;boolean r;r = p ^ p;// falser = p ^ q;// truer = q ^ p;// truer = q ^ q;// false3.11移位操作符
移位操作符有左移<<有符號右移>>,無符號右移>>>,它們的運算方式如下:
x<<n; // 將x向左移動n位,在低位補0x>>n; // 將x向右移動n位,若x是正數,則高位補0,若x是負數,則高位補1x>>>n; // 將x向右移動n位,無論如何,在高位補0// 無論對0怎么移動,結果都是0
如果對char、byte或者short類型的數值進行移位處理,那么在移位之前,它們先轉換成int類型,并且得到的結果也是一個int類型的值。
“移位”可與“等號”(<<=或>>=或>>>=)組合使用
3.12條件操作符條件操作符的語法如下形式:
expression ? value1 : value2;
其實它相當于 if-else語句,如下
if (expression) value1;else value2;
如果expression為true,結果為value1,否則為value2。需要注意的是,條件操作符的結合性是從右至左的,比如
int x = 2 > 1 ? 10 : 100 > 99 ? 1000 : 10000;// x = 10
先執行100 > 99 ? 1000 : 10000;結果為1000,再執行2 > 1 ? 10 : 1000;所以結果為10
3.13字符串操作符+和+=簡單展示一下應用
String s1 = "Hello,";String s2 = "world";String s3 = s1 + s2;// s3 = "Hello,world"String s1 += s2;// s1 = "Hello,world"3.14類型轉換
學過C語言的應該都清楚類型轉換是怎么回事。只要類型比int小(即byte、char或short),那么在運算之前,這些值會自動轉換成int,這樣一來,最終生成的結果就是int類型了。如果想 把結果賦值給較小的類型,就必須使用強制類型轉換(既然把結果賦給了較小的類型,就可能出現信息丟失)。通常,表達式中出現的最大的數據類型決定了表達式 最終結果的數據類型。如果將一個float值與一個double值相乘,結果就是double;如果將一個int和一個long相加,結果為long
類型轉換的應用:精確到小數點后 n 位// 精確到小數點后3位double pi = 3.141592653;double x = (int) Math.round(pi * 1000) / 1000.0;// x = 3.142
新聞熱點
疑難解答