學(xué)習(xí)編程語言的通許遇到的第一個程序無非打印"Hello, world"了,然而在Java中要寫成
System.out.我們都會感覺太冗長了,能不能簡單一些呢?靜態(tài)導(dǎo)入可以省略掉System,就像這樣
import static java.lang.System.*;public class Hello { public static void main(String[] args) { out.println("Hello, world"); }}能不能再簡單一些呢?像C語言那樣?實(shí)際上,這里的System是類,out是System的一個PrintStream類型的靜態(tài)成員,因?yàn)樵?strong>System類中是這樣寫的
public final class System { // ...... public final static PrintStream out = null; // ......}可以得到啟發(fā),自己也寫一個類,然后靜態(tài)導(dǎo)入此類,就可以像C語言那樣直接輸出內(nèi)容了
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,然后修改環(huán)境變量,在CLASSPATH中添加%JAVA_HOME%/lib/p1.jar,這樣就可以一勞永逸了,只需要import static p1.Print.*;就可以直接使用println方法了。
3.2使用Java操作符這里提到操作符的副作用,這篇博文講得很詳細(xì)http://m.survivalescaperooms.com/lazycoding/archive/2011/04/27/side-effect.html
簡單說,變量X在一個表達(dá)式的運(yùn)算后,如果值未變,操作符沒有副作用,如果值改變了,操作符產(chǎn)生副作用。
3.3優(yōu)先級
| 優(yōu)先級 | 運(yùn)算符 | 結(jié)合性 |
| 1 | ( ) [ ] . | 從左至右 |
| 2 | ! +(正) -(負(fù)) ~ ++(遞增) --(遞減) | 從右向左 |
| 3 | * / % | 從左至右 |
| 4 | +(加) -(減) | 從左至右 |
| 5 | << >> >>> | 從左至右 |
| 6 | < , <= , > , >= , instanceof | 從左至右 |
| 7 | == != | 從左至右 |
| 8 | &(按位與) | 從左至右 |
| 9 | ^(異或) | 從左至右 |
| 10 | |(按位或) | 從左至右 |
| 11 | &&(邏輯與,短路與) | 從左至右 |
| 12 | ||(邏輯或,短路或) | 從左至右 |
| 13 | ?: | 從右向左 |
| 14 | = , += , -= , *= , /= , %= , &= , |= , ^= , ~=,<<= , >>= , >>>= | 從右向左 |
其實(shí)不需要刻意去記,因?yàn)槿f能的小括號( )可以減少錯誤,還使程序易于閱讀。
3.4賦值賦值很簡單,不外乎為一個變量賦值,比如
int x = 5;
初學(xué)者需要注意的是左值的問題,不能寫成
int x = 5;2 = x;// 左值不能是直接量,常量x + 1 = 5;// 左值不能是表達(dá)式3.5算術(shù)操作符
算術(shù)操作符有 +(加), -(減),*(乘),/(除),%(取模)
int sum = 9 - 8 + 6 / 3 * 5 % 3;// sum = 2
這5個算術(shù)操作符只是數(shù)學(xué)的基本的運(yùn)算符,自然會像數(shù)學(xué)那樣先乘除取模,再加減。所以這個例子中,先是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
如優(yōu)先級第 14 行所述,賦值和簡化操作符都是從右至左地運(yùn)算的,因此上面的程序先是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
再看復(fù)雜一點(diǎn)的程序
int x = 5;int y = x++ + x-- + ++x + --x;// x = 5, y = 22
上面的程序相當(dāng)于
int x = 5;int y = x++;y = x--;y = ++x;y = --x;
注意,不能對同一個變量使用2個或2個以上的遞增遞減操作符,比如下面的程序
x++--;// 錯誤,不能對同一個變量同時使用2個遞增遞減操作符3.7關(guān)系操作符
關(guān)系操作符有<(小于),<=(小于或等于),>(大于),>=(大于或等于),==(等于)和!=(不等于),運(yùn)算的結(jié)果是一個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 }}結(jié)果出乎意料了,第 11 行是true,可第 12 行卻是false!這是因?yàn)椋?= 和 != 比較的是對象的地址,而非對象的內(nèi)容。String類型的 s1 和 s2 引用的是同樣一個字符串常量,因此相等,而Person類型的xiaoMing和xiaoFu雖然內(nèi)容一樣,但是屬于兩個不同的對象,就像同一班里有兩個小明,雖然它們年齡相等,但是他們的基因不一樣。
既然這樣,那我們應(yīng)該如何比較兩個對象的內(nèi)容呢?可以使用從根類Object繼承下來的equals()方法
out.println(s1.equals(s2));// trueout.printlnl(xiaoMing.equals(xiaoFu));// false
結(jié)果又讓人費(fèi)解,為什么第 1 行的結(jié)果是true,而第 2 行的結(jié)果還是false?其實(shí)類String覆蓋了類Object的equals()方法,而這個例子尚未覆蓋它,實(shí)際上從類Object繼承的equals()方法默認(rèn)是這樣的
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實(shí)際上,引用變量s1所指向的字符串常量"abc"是放在常量池的,當(dāng)s2也要引用"abc"時,JVM并不會再開辟一個內(nèi)存空間,而是讓s2也引用已經(jīng)存在的"abc",因此s1會等于s2。s3和s4就不同了,它們所引用的對象是存在于堆中,而且是不同的對象,盡管它們的內(nèi)容相同,所以兩者是不相等的。由于類String實(shí)現(xiàn)了equals()方法,使之能比較兩String對象的內(nèi)容,而不是地址,所以第 8 行的結(jié)果是true。
3.8邏輯操作符邏輯操作符“與”(&&)、“或”(||)、“非”(!)能根據(jù)參數(shù)的邏輯關(guān)系,生成一個布爾值(true或false)。
值得注意的是,&& 和 || 是短路的,比如 p&&q,如果 p 為假,則不必再計(jì)算 q,如果 p 為真,則繼續(xù)計(jì)算 q,比如 p||q,如果 p 為真,則不必計(jì)算 q,如果 p 為假,則繼續(xù)計(jì)算 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 + " "); }}上面的程序,因?yàn)槎搪罚?5 行的結(jié)果是false和空格,第7行的結(jié)果是false true和空格
3.9直接常量直接引用《Java編程思想》的代碼
public class Literals { public static void main(String[] args) { int i1 = 0x2f;//十六進(jìn)制,小寫 out.println("i1: " + Integer.toBinaryString(i1)); int i2 = 0X2F;//十六進(jìn)制,大寫 out.println("i2: " + Integer.toBinaryString(i2)); int i3 = 0177;//八進(jìn)制,以0開始 out.println("i3: " + Integer.toBinaryString(i3)); char c = 0xffff;//十六進(jìn)制,char類型的最大值 out.println("c: " + Integer.toBinaryString(c)); byte b = 0x7f;//十六進(jìn)制,byte的最大值 out.println("b: " + Integer.toBinaryString(b)); short s = 0x7fff;//十六進(jìn)制,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 }}/*輸出結(jié)果i1: 101111i2: 101111i3: 1111111c: 1111111111111111b: 1111111s: 111111111111111*/在C、C++或者Java中,二進(jìn)制都沒有直接常量的表示方法,不過用十六進(jìn)制和八進(jìn)制來表示二進(jìn)制會更加直觀、簡潔和更易于閱讀。
既然是直接常量,程序就休想修改它的值了,比如下面的代碼不能編譯
int x = ++5;3.10按位操作符
按位操作符用來操作整數(shù)基本數(shù)據(jù)類型中的單個“比特”(bit),即補(bǔ)碼的二進(jìn)制位。按位操作符會對兩個參數(shù)中對應(yīng)的位執(zhí)行布爾代數(shù)運(yùn)算,并最終生成一個結(jié)果。
按位操作符有 按位與(&)、按位或(|)、按位異或(^)和按位非(~),它們的計(jì)算方式如下

實(shí)際應(yīng)用如下:
十進(jìn)制7的補(bǔ)碼:00000111十進(jìn)制9的補(bǔ)碼:000010017 & 9,即 00000111 & 00001001 = 00000001(十進(jìn)制1)7 | 9,即 00000111 | 00001001 = 00001111(十進(jìn)制15)7 ^ 9,即 00000111 ^ 00001001 = 00001110(十進(jìn)制14)~7, 即 ~00000111 = 11111000(十進(jìn)制-8)
按位操作符和邏輯操作符都使用了同樣的符號,因此我們能方便地記住它們的含義:由于位是非常“小”的,所以按位操作符僅使用了一個字符。
按位操作符可與等號(=)聯(lián)合使用,以便合并運(yùn)算和賦值:&=、|=、和^=都是合法的(由于~是一元操作符,所以不存在~=)
我們將布爾類型作為一種單bit值對待,因而它會有些獨(dú)特。對于布爾值,用按位操作符的話,將不再短路。我們可以對布爾值進(jìn)行&、|、^,但不能~(為了避免與!混淆),其中按位異或(^)使用如下
boolean p = true;boolean q = false;boolean r;r = p ^ p;// falser = p ^ q;// truer = q ^ p;// truer = q ^ q;// false3.11移位操作符
移位操作符有左移<<有符號右移>>,無符號右移>>>,它們的運(yùn)算方式如下:
x<<n; // 將x向左移動n位,在低位補(bǔ)0x>>n; // 將x向右移動n位,若x是正數(shù),則高位補(bǔ)0,若x是負(fù)數(shù),則高位補(bǔ)1x>>>n; // 將x向右移動n位,無論如何,在高位補(bǔ)0// 無論對0怎么移動,結(jié)果都是0
如果對char、byte或者short類型的數(shù)值進(jìn)行移位處理,那么在移位之前,它們先轉(zhuǎn)換成int類型,并且得到的結(jié)果也是一個int類型的值。
“移位”可與“等號”(<<=或>>=或>>>=)組合使用
3.12條件操作符條件操作符的語法如下形式:
expression ? value1 : value2;
其實(shí)它相當(dāng)于 if-else語句,如下
if (expression) value1;else value2;
如果expression為true,結(jié)果為value1,否則為value2。需要注意的是,條件操作符的結(jié)合性是從右至左的,比如
int x = 2 > 1 ? 10 : 100 > 99 ? 1000 : 10000;// x = 10
先執(zhí)行100 > 99 ? 1000 : 10000;結(jié)果為1000,再執(zhí)行2 > 1 ? 10 : 1000;所以結(jié)果為10
3.13字符串操作符+和+=簡單展示一下應(yīng)用
String s1 = "Hello,";String s2 = "world";String s3 = s1 + s2;// s3 = "Hello,world"String s1 += s2;// s1 = "Hello,world"3.14類型轉(zhuǎn)換
學(xué)過C語言的應(yīng)該都清楚類型轉(zhuǎn)換是怎么回事。只要類型比int小(即byte、char或short),那么在運(yùn)算之前,這些值會自動轉(zhuǎn)換成int,這樣一來,最終生成的結(jié)果就是int類型了。如果想 把結(jié)果賦值給較小的類型,就必須使用強(qiáng)制類型轉(zhuǎn)換(既然把結(jié)果賦給了較小的類型,就可能出現(xiàn)信息丟失)。通常,表達(dá)式中出現(xiàn)的最大的數(shù)據(jù)類型決定了表達(dá)式 最終結(jié)果的數(shù)據(jù)類型。如果將一個float值與一個double值相乘,結(jié)果就是double;如果將一個int和一個long相加,結(jié)果為long
類型轉(zhuǎn)換的應(yīng)用:精確到小數(shù)點(diǎn)后 n 位// 精確到小數(shù)點(diǎn)后3位double pi = 3.141592653;double x = (int) Math.round(pi * 1000) / 1000.0;// x = 3.142
新聞熱點(diǎn)
疑難解答
圖片精選