java重寫和編譯器
1. java什麼是方法重寫的語法規則
一、方法的重寫。
1、重寫只能出現在繼承關系之中。當一個類繼承它的父類方法時,都有機會重寫該父類的方法。一個特例是父類的方法被標識為final。重寫的主要優點是能夠定義某個子類型特有的行為。
class Animal {
public void
eat(){
System.out.println ("Animal is eating.");
}
}
class Horse extends Animal{
public void eat(){
System.out.println ("Horse is
eating.");
}
}
2、對於從父類繼承來的抽象方法,要麼在子類用重寫的方式設計該方法,要麼把子類也標識為抽象的。所以抽象方法可以說是必須要被重寫的方法。
3、重寫的意義。
重寫方法可以實現多態,用父類的引用來操縱子類對象,但是在實際運行中對象將運行其自己特有的方法。
public class Test {
public static
void main (String[] args) {
Animal h = new Horse();
h.eat();
}
}
class Animal {
public void eat(){
System.out.println ("Animal is
eating.");
}
}
class Horse extends
Animal{
public void
eat(){
System.out.println ("Horse is eating.");
}
public void
buck(){
}
}
一個原則是:使用了什麼引用,編譯器就會只調用引用類所擁有的方法。如果調用子類特有的方法,如上例的h.buck();
編譯器會抱怨的。也就是說,編譯器只看引用類型,而不是對象類型。
4、重寫方法的規則。
若想實現一個合格重寫方法,而不是重載,那麼必須同時滿足下面的要求!
重寫規則之一:重寫方法不能比被重寫方法限制有更嚴格的訪問級別。
(但是可以更廣泛,比如父類方法是包訪問許可權,子類的重寫方法是public訪問許可權。)
比如:Object類有個toString()方法,開始重寫這個方法的時候我們總容易忘記public修飾符,編譯器當然不會放過任何教訓我們的機會。出錯的原因就是:沒有加任何訪問修飾符的方法具有包訪問許可權,包訪問許可權比public當然要嚴格了,所以編譯器會報錯的。
重寫規則之二:參數列表必須與被重寫方法的相同。
重寫有個孿生的弟弟叫重載,也就是後面要出場的。如果子類方法的參數與父類對應的方法不同,那麼就是你認錯人了,那是重載,不是重寫。
重寫規則之三:返回類型必須與被重寫方法的返回類型相同。
父類方法A:void
eat(){} 子類方法B:int eat(){} 兩者雖然參數相同,可是返回類型不同,所以不是重寫。
父類方法A:int
eat(){} 子類方法B:long eat(){}
返回類型雖然兼容父類,但是不同就是不同,所以不是重寫。
重寫規則之四:重寫方法不能拋出新的異常或者比被重寫方法聲明的檢查異常更廣的檢查異常。但是可以拋出更少,更有限或者不拋出異常。
例:
import java.io.*;
public class Test
{
public static void main (String[]
args) {
Animal h =
new Horse();
try
{
h.eat();
}
catch (Exception e) {
}
}
}
class Animal
{
public void eat() throws
Exception{
System.out.println ("Animal is eating.");
throw new
Exception();
}
}
class Horse extends
Animal{
public void eat() throws
IOException{
System.out.println ("Horse is eating.");
throw new
IOException();
}
}
這個例子中,父類拋出了檢查異常Exception,子類拋出的IOException是Exception的子類,也即是比被重寫的方法拋出了更有限的異常,這是可以的。如果反過來,父類拋出IOException,子類拋出更為寬泛的Exception,那麼不會通過編譯的。
注意:這種限制只是針對檢查異常,至於運行時異常RuntimeException及其子類不再這個限制之中。
重寫規則之五:不能重寫被標識為final的方法。
重寫規則之六:如果一個方法不能被繼承,則不能重寫它。
比較典型的就是父類的private方法。下例會產生一個有趣的現象。
public class Test {
public static
void main (String[] args) {
//Animal h = new Horse();
Horse h = new
Horse();
h.eat();
}
}
class Animal {
private void eat(){
System.out.println ("Animal is
eating.");
}
}
class Horse extends
Animal{
public void
eat(){
System.out.println ("Horse is eating.");
}
}
這段代碼是能通過編譯的。表面上看來違反了第六條規則,但實際上那是一點巧合。Animal類的eat()方法不能被繼承,因此Horse類中的eat()方法是一個全新的方法,不是重寫也不是重載,只是一個只屬於Horse類的全新的方法!這點讓很多人迷惑了,但是也不是那麼難以理解。
main()方法如果是這樣:
Animal h = new Horse();
//Horse h = new
Horse();
h.eat();
編譯器會報錯,為什麼呢?Horse類的eat()方法是public的啊!應該可以調用啊!請牢記,多態只看父類引用的方法,而不看子類對象的方法!
2. Java主要有那些特性
Java主要有哪些的特性?
Java由美國SUN公司(被oracle公司收購)發明於1995年,是目前業界應用最廣泛、使用人數最多的語言,連續多年排名世界第一,可以稱之為「計算機語言界的英語」。
那麼Java這么高的評價它的特點有哪些,下面我來為題主解答:
一、跨平台/可移植性
這是Java的核心優勢。Java在設計時就很注重移植和跨平台性。比如:Java的int永遠都是32位。不像C++可能是16,32,可能是根據編譯器廠商規定的變化。這樣的話程序的移植就會非常麻煩。
Java首先利用文本編輯器編寫 Java源程序,源文件的後綴名為.java;再利用編譯器(javac)將源程序編譯成位元組碼文件,位元組碼文件的後綴名為.class; 最後利用虛擬機(解釋器,java)解釋執行。如下圖所示:
二、安全性
Java適合於網路/分布式環境,為了達到這個目標,在安全性方面投入了很大的精力,使Java可以很容易構建防病毒,防篡改的系統。比如Java取消了強大但又危險的指針。由於指針可進行移動運算,指針可隨便指向一個內存區域,而不管這個區域是否可用,這樣做是危險的。
三、面向對象
面向對象是一種程序設計技術,非常適合大型軟體的設計和開發。由於C++為了照顧大量C語言使用者而兼容了C,使得自身僅僅成為了帶類的C語言,多少影響了其面向對象的徹底性!Java則是完全的面向對象語言。
四、簡單性
Java就是C++語法的簡化版,我們也可以將Java稱之為「C++-」。跟我念「C加加減」,指的就是將C++的一些內容去掉;比如:頭文件,指針運算,結構,聯合,操作符重載,虛基類等等。同時,由於語法基於C語言,因此學習起來完全不費力。
五、高性能
Java最初發展階段,總是被人詬病「性能低」;客觀上,高級語言運行效率總是低於低級語言的,這個無法避免。Java語言本身發展中通過虛擬機的優化提升了幾十倍運行效率。比如,通過JIT(JUST IN TIME)即時編譯技術提高運行效率。 將一些「熱點」位元組碼編譯成本地機器碼,並將結果緩存起來,在需要的時候重新調用。這樣的話,使Java程序的執行效率大大提高,某些代碼甚至接近C++的效率。
因此,Java低性能的短腿,已經被完全解決了。業界發展上,我們也看到很多C++應用轉到Java開發,很多C++程序員轉型為Java程序員。
六、分布式
Java是為Internet的分布式環境設計的,因為它能夠處理TCP/IP協議。事實上,通過URL訪問一個網路資源和訪問本地文件是一樣簡單的。Java還支持遠程方法調用(RMI,Remote Method Invocation),使程序能夠通過網路調用方法。
七、多線程
多線程的使用可以帶來更好的交互響應和實時行為。 Java多線程的簡單性是Java成為主流伺服器端開發語言的主要原因之一。
八、健壯性
Java是一種健壯的語言,吸收了C/C++ 語言的優點,但去掉了其影響程序健壯性的部分(如:指針、內存的申請與釋放等)。Java程序不可能造成計算機崩潰。即使Java程序也可能有錯誤。如果出現某種出乎意料之事,程序也不會崩潰,而是把該異常拋出,再通過異常處理機制加以處理。
以上幾種特性你了解到啦嗎? 記得給個贊!
3. Java 方法重寫問題
重寫: 重寫方法必須和被重寫方法具有 相同的 方法名、參數列表、和返回值類型。
必須和父類的參數列表相同為什麼:
上面說的不錯,是為了多態,重寫是多態的必要條件之一,多態說白了就是程序執行前(包括編寫代碼時和編譯.java源文件的時候)你調的是父類被重寫這方法,真正在運行時(程序執行以後),實際當中,動態綁定(在運行期間真正的new出該對象來,對象內部有一個指針,指向該對象重寫的寫個方法),調用的是子類重寫的這個方法。
方法的參數是形參,形參的作用是接收調用該方法時傳過來的實參,形參屬於局部變數,那麼毫無疑問方法內部是要使用這些個參數做一些事情的,重寫要求參數列表必須相同,如果不相同,那麼你調父類被重寫的這個方法,參數列表不同,那實際當中還執行子類這重寫方法,那不矛盾么?內部不混亂了么?參數對不上號,人家重寫方法內部要用這參數怎麼辦啊?
下面這個不太肯定,不過我還是說一下我的看法:
構造方法能不能被繼承,new一個子類對象出來的時候,子類對象裡麵包含著一個父類對象,也就是說,父類對象的所有東西子類對象全部都擁有了,全部都繼承下來了,但是有些東西你是有擁有權,沒有使用權,比方說private的方法,構造方法是new一個對象的時候必然要調用的方法,初始化對象用的,這個方法比較特殊,不像一般的方法一樣,是為了做一件事兒,它就是new對象時候調的方法,我認為構造方法還是繼承下來了,但是你用不了,無法用子類對象的引用去調用構造方法。
4. java中,在子類中是否允許有一個方法和父類的方法名字相同,而類型不同
在Java SE 5.0之前的版本,子類覆蓋父類的方法時,返回類型必須一樣。
之後的版本允許子類的覆蓋方法的返回類型是原返回類型的子類型。