国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

對初學者有用的文章

2019-11-18 15:06:10
字體:
來源:轉載
供稿:網友

  經常聽到這樣的對話:"你會Weblogic, Oracle, xml, Kylix, 等等嗎?不會?你好差。這么先進的技術怎么能不會?"往往我們也能在看到很多簡歷,自稱精通某某,某某某技術, 乍一看下來,簡直是絕頂高手,精通了所有流行的先進技術。但是我經常想,就算是不吃飯不睡覺也不可能在短短時間里精通那么多范圍極廣,博大精深的技術啊。而我自己,卻經常在實際工作中碰到一些問題,讓我不得不想起基礎知識的重要性。我在這里不是要打擊大家學習先進技術的熱情,而是為了強調一下基礎知識的重要。比如,有很多的java程序員在使用JBuilder, WebLogic, WebSphere, SilverStream,寫普通的java程序或者寫j2ee, corba結構的程序。在但是,在把握先進技術的同時,我們也要注重一下基礎的修煉,免得不斷出現本可以避免的錯誤。我將陸續寫一系列的文章,關于java編程常見問題。這些,都是我在日常工作中積累下來的一些筆記,不成體系(我盡量將它們按照范圍不同組織一下), 嚴格的說,不能叫做文章吧。大家隨便看看。呵呵。
(內容)
先來看一個常見的錯誤。
public boolean testAns(String ans, int n){
boolean rslt;
if( ans.equalsIgnoreCase("YES") && n > 5)
rslt = true;
return rslt;
}
程序邏輯方面并沒有問題,但是編譯的時候會出現錯誤提示
:
variable rslt might not have been initialized
return rslt;
^
這是因為,當if條件為false的時候,rslt可能會沒有被賦予初值,而return的時候則會出錯。java編譯器很聰明的檢查了這一錯誤并在編譯的時候給予了提示。這需要你在聲明rslt的時候或者在返回rslt之前給它賦值。
比如:
public boolean testAns(String ans, int n){
boolean rslt = false;
if( ans.equalsIgnoreCase("YES") && n > 5)
rslt = true;
return rslt;
}
相關的問題還有:
public boolean testAns(String ans, int n){
boolean rslt = true;
while(false){rslt = false;}
for(;false;){rslt = false;}
if(false) {rslt = false;}
return rslt;
}
則Java編譯器會提示
unreachable statement
while(false){rslt = false;}
^
unreachable statement
for(;false;){rslt = false;}[/code]
^
但是if(false)這一段則沒有錯誤提示,編譯通過。這也是要注重的一點。
第二個例子:class Object 中有一個方法equals()
public boolean Object.equals(Object) 它檢查object reference是否相同,也就是說是否指向同一個對象。假如是,則返回true, 否則返回false. 而每一個繼續class Object的類都會override這個方法。比如在Long, Integer等class中,equals比較該Ojbect是否相應的是Long, Integer類型。假如類型相同,值比較所包裹的值是否相同。假如相同,則返回true, 否則返回false.要注重的是,返回false并不說明所包裹的值不相同,也可能是類型不同。比如下面代碼:

Long l = new Long(7);
Integer j = new Integer(7);
if(l.equals(j)) System.out.else System.out.println("Not Equal");
編譯成功,但是輸出為Not Equal, 這就是因為類型不同, 不是同為Integer或者
同為Long.

再看一下使用instanceof要注重的問題. instanceof是判定一個對象的引用(reference)
是否某一類型。比如
Integer i = new Integer(0);
System.out.println( i instanceof Integer);
返回為true,因為i是一個Integer的對象的引用。
Integer i = new Integer(0);
System.out.println( i instanceof Long);
則返回為false, 因為i不是一個Long的對象的引用。
但是,
Integer i = null;
System.out.println( i instanceof Integer);
返回值為false. 這是因為i的值為null, null不是任何對象的引用。這是需要注重的。

第四個問題,是在郵件列表,news groups中提到次數比較多的一個問題,也是很多初學java編程的人經常碰到的一個問題。以下這段代碼,編譯會出現錯誤。
[code]byte x = 100;
switch(x) {
case 100:
case 200:
case 300:
}
編譯器提示
a1.java:6: possible loss of precision
found : int
required: byte
case 200:
^
a1.java:7: possible loss of precision
found : int
required: byte
case 300:
^
2 errors

因為x為byte類型,但是300超過了byte類型的最大值127, 所以出現了錯誤。這段代碼相當于是
if(x == 100)
...
else if(x == 200)
...
else if(x == 300)
...
這樣子看錯誤原因就比較明顯了。
類似的我們還有這樣的代碼:
short x = 200;
switch(x) {
case 70000:
case 10:
case 1:
}
編譯也會出錯,提示case 7000:這一行類型不匹配。

關于primitive類型的賦值問題,還有以下兩個需要注重的問題:
這段代碼
byte b = 1;
short s = b;
不會出錯。因為,byte為8 bits, 而short為16 bits,將byte類型的數值賦予給short類型的變量不會引起數值精度問題。但是
short s = 1;
byte b = s;
則不能正確編譯。因為這樣賦值可能導致s所含數值的高8 bit被舍棄,因而數值不正確。這樣需要我們在寫程序的時候指定
byte b = (byte)s;

以便通知編譯器,"嘿, 假如有精度的損失,那是我自愿的,你不必擔心!"這樣編譯就不會出錯了。同樣的,
short s = 1;
byte b = 1;
b = b + s;
不能正確編譯。需要我們在寫程序的時候指定
b = (byte)(b + s);
這些錯誤很多人現在都會避免了。但是這樣子的代碼是否會編譯錯誤呢?
short s = 1;
byte b = 1;
b += s;
照以上的解釋,你一定認為這段代碼不能正確編譯。但是假如你實際編譯一下則會發現,它編譯通過了!為什么呢?這是因為, +=, -=, *=, /=, %=這類操作符號比較非凡,對于編譯器來說,他們相當于
b += s; -------> b = (byte)(b + s);
呵呵,有意思吧?

inner class的問題,更多的人感到迷惑。
比如,inner class是否能夠有static的變量?
一般的說法是,static inner class能夠有static的變量,而non-static inner
class則不能有static的變量。但是,假如這樣:
class outer {
class inner {
static final int i = 999;
}
}
編譯通過。而你不能這么寫:
static final int i;
就是說,一定要在聲明它的時候賦予初值, 因為i是final的,它的值不能再被改變。
關于inner class, 還有一個代碼也很能說明一些問題。

public class TestClass
{
public TestClass(int i) { }

public void m1()
{
TestClass al = new TestClass(10)
{
public void actionPerformed(ActionEvent e)
{
}
};
}
}
這說明了一下四個問題:
1. 類中的方法也可以有inner classes.(但是他們不能有static inner classes).
2. Inner class 能夠繼續包含它的外部class.
3. 匿名 inner class 可以繼續一個 class 或者 implements 一個 interface。
4. 匿名 inner class 可以有初始化參數。(假如這個class繼續的基類有相應的 constrUCtor 的話。)

再來看看動態聯編 ( dyanamic link )的問題。
考慮這段代碼:

class base{
public void whoami() {
System.out.println("Base");
}
}
class derived extends base{
public void whoami() {
System.out.println("Derived");
}
}

class test{
public static void main(String[] args) {
base b = new base();
derived d = new derived();
b.whoami();
d.whoami();
base b2 = d;
b2.whoami();
}
}
當然大家很清楚,b.whoami()打印Base, 而d.whoami()打印Derived.但是,b2.whoami()打印什么呢?也就是說,b2.whoami()將調用那一個方法呢?是基類的還是派生類的?運行以后看到,調用的是派生類的方法。這是因為java是在運行過程中采用了動態聯編的方法,在運行時刻來決定該reference指向的什么類的對象,從而決定調用哪一個類的方法,而不是根據reference的類型來決定調用哪一個類的方法。從而可以使我們通過這一機制來完成多樣化的程序。打印的結果將是Derived。
再來看另外一個類似的例子:
class base{
int i = 100;
public void print() {
System.out.println(i);
}
}
class derived extends base{
int i = 999;
public void print() {
System.out.println(i);
}
}

class test{
public static void main(String[] args) {
base b = new base();

derived d = new derived();
b.print();
System.out.print(b.i);
d.print();
System.out.print(d.i);
base b2 = d;
b2.print();
System.out.print(b2.i);
}
}
很簡單的,前面的調用:
b.print();
打印100
System.out.print(b.i);
打印100
d.print();
打印999
System.out.print(d.i);
打印999.
但是
System.out.print(b2.i);
打印什么呢?結果是100, 而不是999。這是因為,在動態聯編過程中,只是函數參與了,而對于類中的變量,則還是以靜態的方式編譯的,就是說,編譯器是憑借reference的類型來決定類變量的。b2是base類型的reference, 所以b2.i
是基類中的變量的值。

關于動態聯編,還有2個要注重的問題:
class base{
}
class derived extends base{
public void print() {
System.out.println("Derived");
}
}

class test{
public static void main(String[] args) {
base b = new base();
derived d = new derived();
d.print();
base b2 = d;
b2.print();//出錯
}
}
為什么呢?因為在編譯過程中,編譯器會檢查基類中是否有print()方法,假如沒有,則會報錯。注重:動態聯編出現在運行過程中,而不是編譯過程中。

class base{
int i = 100;
public void print() {
System.out.println(i);
}
}
class derived extends base{
int i = 999;
public void print() {
System.out.println(i);
}
}

class test{
public static void main(String[] args) {
base b = new base();
derived d = new derived();
b.print();
System.out.print(b.i);
d.print();
System.out.print(d.i);
base b2 = d;
b2.print();
System.out.print(b2.i);
derived d2 = b;//出錯
d2.print();//出錯
System.out.print(d2.i);//出錯
}
}
這是因為,在編譯過程中,derived類型的reference可以賦給base類型的reference.
而base類型的reference則不可以賦給derived類型的reference.假如要這么做,
則需要在賦值的過程中指定
derived d2 = (derived)b;
編譯才能通過。這和primitive types的賦值是一樣的道理。而編譯完成后在運行時刻還需要做進一步的檢驗,假如類型不能匹配,則會拋出
ClassCastException.
Exception in thread "main" java.lang.ClassCastException: base
at test.main(a2.java:12)

......未完,待續

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 佛教| 海原县| 顺平县| 乌拉特后旗| 柘城县| 上虞市| 鹤壁市| 焉耆| 德令哈市| 万安县| 府谷县| 宜川县| 藁城市| 伊金霍洛旗| 永兴县| 博兴县| 林甸县| 潞西市| 南安市| 大厂| 聊城市| 盐津县| 高尔夫| 丰城市| 襄樊市| 田阳县| 芷江| 江都市| 宁蒗| 徐闻县| 梨树县| 洱源县| 永州市| 寿宁县| 裕民县| 高台县| 收藏| 银川市| 八宿县| 镇远县| 景谷|