本文目錄一覽:
- 1、在java裡面的向上轉型和向下轉型的具體好處在哪裡?
- 2、在java 中,什麼叫向上轉型?
- 3、在java 中,什麼叫向上轉型
- 4、關於java的向上轉型
- 5、java中關於向上轉型的問題
- 6、java向上轉型有什麼作用
在java裡面的向上轉型和向下轉型的具體好處在哪裡?
java裡面的向上轉型和向下轉型的具體好處如下:
1.轉型是在繼承的基礎上而言的,繼承是面向對象語言中,代碼復用的一種機制,通過繼承,子類可以復用父類的功能,如果父類不能滿足當前子類的需求,則子類可以重寫父類中的方法來加以擴展。
2.向上轉型:子類引用的對象轉換為父類類型稱為向上轉型。通俗地說就是是將子類對象轉為父類對象。此處父類對象可以是介面
向上轉型時,父類指向子類引用對象會遺失除與父類對象共有的其他方法,也就是在轉型過程中,子類的新有的方法都會遺失掉,在編譯時,系統會提供找不到方法的錯誤。實例如下:
public class Animal {
public void eat(){
System.out.println(“animal eatting…”);
}
}
class Bird extends Animal{
public void eat(){
System.out.println(“bird eatting…”);
}
public void fly(){
System.out.println(“bird flying…”);
}
}
class Main{
public static void main(String[] args) {
Animal b=new Bird(); //向上轉型
b.eat();
b.fly(); //此處提示在Animal中沒有定義fly方法。
}
在java 中,什麼叫向上轉型?
java 轉型問題其實並不複雜,只要記住一句話:父類引用指向子類對象。\x0d\x0a\x0d\x0a什麼叫父類引用指向子類對象,且聽我慢慢道來.\x0d\x0a\x0d\x0a從2個名詞開始說起:向上轉型(upcasting) 、向下轉型(downcasting).\x0d\x0a\x0d\x0a舉個例子:有2個類,Father是父類,Son類繼承自Father。\x0d\x0a\x0d\x0aFather f1 = new Son(); // 這就叫 upcasting (向上轉型)\x0d\x0a\x0d\x0a// 現在f1引用指向一個Son對象\x0d\x0a\x0d\x0aSon s1 = (Son)f1; // 這就叫 downcasting (向下轉型)\x0d\x0a\x0d\x0a// 現在f1還是指向Son對象\x0d\x0a\x0d\x0a第2個例子:\x0d\x0a\x0d\x0aFather f2 = new Father();\x0d\x0a\x0d\x0aSon s2 = (Son)f2; // 出錯,子類引用不能指向父類對象\x0d\x0a\x0d\x0a你或許會問,第1個例子中:Son s1 = (Son)f1;問什麼 是正確的呢。\x0d\x0a\x0d\x0a很簡單因為f1指向一個子類對象,Father f1 = new Son(); 子類s1引用當然可以指向子類對象了。\x0d\x0a\x0d\x0a而f2 被傳給了一個Father對象,Father f2 = new Father();子類s1引用不能指向父類對象。\x0d\x0a\x0d\x0a總結:\x0d\x0a\x0d\x0a1。父類引用指向子類對象,而子類引用不能指向父類對象。\x0d\x0a\x0d\x0a2。把子類對象直接賦給父類引用叫upcasting向上轉型,向上轉型不用強制轉換。\x0d\x0a\x0d\x0a 如:Father f1 = new Son();\x0d\x0a\x0d\x0a3。把指向子類對象的父類引用賦給子類引用叫向下轉型(downcasting),要強制轉換。\x0d\x0a\x0d\x0a 如:f1 就是一個指向子類對象的父類引用。把f1賦給子類引用s1即 Son s1 = (Son)f1;\x0d\x0a\x0d\x0a 其中f1前面的(Son)必須加上,進行強制轉換。\x0d\x0a\x0d\x0a一、向上轉型。\x0d\x0a通俗地講即是將子類對象轉為父類對象。此處父類對象可以是介面。\x0d\x0a\x0d\x0a1,向上轉型中的方法調用。\x0d\x0a\x0d\x0a看下面代碼:\x0d\x0a\x0d\x0a[java] view plaincopyprint?\x0d\x0apackage com.wensefu.others; \x0d\x0apublic class Animal { \x0d\x0a \x0d\x0a public void eat(){ \x0d\x0a System.out.println(“animal eatting…”); \x0d\x0a } \x0d\x0a} \x0d\x0aclass Bird extends Animal{ \x0d\x0a \x0d\x0a public void eat(){ \x0d\x0a System.out.println(“bird eatting…”); \x0d\x0a } \x0d\x0a \x0d\x0a public void fly(){ \x0d\x0a \x0d\x0a System.out.println(“bird flying…”); \x0d\x0a } \x0d\x0a} \x0d\x0aclass Main{ \x0d\x0a \x0d\x0a public static void main(String[] args) { \x0d\x0a \x0d\x0a Animal b=new Bird(); //向上轉型 \x0d\x0a b.eat(); \x0d\x0a //! error: b.fly(); b雖指向子類對象,但此時丟失fly()方法 \x0d\x0a dosleep(new Male()); \x0d\x0a dosleep(new Female()); \x0d\x0a } \x0d\x0a \x0d\x0a public static void dosleep(Human h) { \x0d\x0a h.sleep(); \x0d\x0a } \x0d\x0a} \x0d\x0a\x0d\x0a[java] view plaincopyprint?\x0d\x0apackage com.wensefu.others; \x0d\x0apublic class Human { \x0d\x0a public void sleep() { \x0d\x0a System.out.println(“Human sleep..”); \x0d\x0a } \x0d\x0a} \x0d\x0aclass Male extends Human { \x0d\x0a @Override \x0d\x0a public void sleep() { \x0d\x0a System.out.println(“Male sleep..”); \x0d\x0a } \x0d\x0a} \x0d\x0aclass Female extends Human { \x0d\x0a @Override \x0d\x0a public void sleep() { \x0d\x0a System.out.println(“Female sleep..”); \x0d\x0a } \x0d\x0a} \x0d\x0a\x0d\x0a注意這裡的向上轉型:\x0d\x0a Animal b=new Bird(); //向上轉型\x0d\x0a b.eat();\x0d\x0a\x0d\x0a此處將調用子類的eat()方法。原因:b實際指向的是Bird子類,故調用時會調用子類本身的方法。\x0d\x0a\x0d\x0a需要注意的是向上轉型時b會遺失除與父類對象共有的其他方法。如本例中的fly方法不再為b所有。\x0d\x0a\x0d\x0a2,向上轉型的好處。\x0d\x0a\x0d\x0a看上面的代碼,\x0d\x0a\x0d\x0a public static void dosleep(Human h) {\x0d\x0a h.sleep();\x0d\x0a }\x0d\x0a\x0d\x0a這裡以父類為參數,調有時用子類作為參數,就是利用了向上轉型。這樣使代碼變得簡潔。不然的話,\x0d\x0a如果dosleep以子類對象為參數,則有多少個子類就需要寫多少個函數。這也體現了JAVA的抽象編程思想。\x0d\x0a\x0d\x0a二、向下轉型。\x0d\x0a\x0d\x0a與向上轉型相反,即是把父類對象轉為子類對象。\x0d\x0a\x0d\x0a看下面代碼:\x0d\x0a\x0d\x0a[java] view plaincopyprint?\x0d\x0apackage com.wensefu.other1; \x0d\x0apublic class Girl { \x0d\x0a public void smile(){ \x0d\x0a System.out.println(“girl smile()…”); \x0d\x0a } \x0d\x0a} \x0d\x0aclass MMGirl extends Girl{ \x0d\x0a \x0d\x0a @Override \x0d\x0a public void smile() { \x0d\x0a \x0d\x0a System.out.println(“MMirl smile sounds sweet…”); \x0d\x0a } \x0d\x0a public void c(){ \x0d\x0a System.out.println(“MMirl c()…”); \x0d\x0a } \x0d\x0a} \x0d\x0aclass Main{ \x0d\x0a \x0d\x0a public static void main(String[] args) { \x0d\x0a \x0d\x0a Girl g1=new MMGirl(); //向上轉型 \x0d\x0a g1.smile(); \x0d\x0a \x0d\x0a MMGirl mmg=(MMGirl)g1; //向下轉型,編譯和運行皆不會出錯 \x0d\x0a mmg.smile(); \x0d\x0a mmg.c(); \x0d\x0a\x0d\x0aGirl g2=new Girl(); \x0d\x0a// MMGirl mmg1=(MMGirl)g2; //不安全的向下轉型,編譯無錯但會運行會出錯 \x0d\x0a// mmg1.smile(); \x0d\x0a// mmg1.c(); \x0d\x0a/*output: \x0d\x0a* CGirl smile sounds sweet… \x0d\x0a* CGirl smile sounds sweet… \x0d\x0a* CGirl c()… \x0d\x0a* Exception in thread “main” java.lang.ClassCastException: com.wensefu.other1.Girl \x0d\x0a* at com.wensefu.other1.Main.main(Girl.java:36) \x0d\x0a*/ \x0d\x0a if(g2 instanceof MMGirl){ \x0d\x0a MMGirl mmg1=(MMGirl)g2; \x0d\x0a mmg1.smile(); \x0d\x0a mmg1.c(); \x0d\x0a } \x0d\x0a \x0d\x0a } \x0d\x0a} \x0d\x0a\x0d\x0aGirl g1=new MMGirl(); //向上轉型\x0d\x0a g1.smile();\x0d\x0a MMGirl mmg=(MMGirl)g1; //向下轉型,編譯和運行皆不會出錯\x0d\x0a\x0d\x0a這裡的向下轉型是安全的。因為g1指向的是子類對象。\x0d\x0a\x0d\x0a而\x0d\x0aGirl g2=new Girl();\x0d\x0aMMGirl mmg1=(MMGirl)g2; //不安全的向下轉型,編譯無錯但會運行會出錯\x0d\x0a\x0d\x0a運行出錯:\x0d\x0a\x0d\x0aException in thread “main” java.lang.ClassCastException: com.wensefu.other1.Girl\x0d\x0a at com.wensefu.other1.Main.main(Girl.java:36)\x0d\x0a如代碼所示,可以通過instanceof來防止出現異常。
在java 中,什麼叫向上轉型
java 轉型問題其實並不複雜,只要記住一句話:父類引用指向子類對象。
什麼叫父類引用指向子類對象,且聽我慢慢道來.
從2個名詞開始說起:向上轉型(upcasting) 、向下轉型(downcasting).
舉個例子:有2個類,Father是父類,Son類繼承自Father。
Father f1 = new Son(); // 這就叫 upcasting (向上轉型)
// 現在f1引用指向一個Son對象
Son s1 = (Son)f1; // 這就叫 downcasting (向下轉型)
// 現在f1還是指向Son對象
第2個例子:
Father f2 = new Father();
Son s2 = (Son)f2; // 出錯,子類引用不能指向父類對象
你或許會問,第1個例子中:Son s1 = (Son)f1;問什麼 是正確的呢。
很簡單因為f1指向一個子類對象,Father f1 = new Son(); 子類s1引用當然可以指向子類對象了。
而f2 被傳給了一個Father對象,Father f2 = new Father();子類s1引用不能指向父類對象。
總結:
1。父類引用指向子類對象,而子類引用不能指向父類對象。
2。把子類對象直接賦給父類引用叫upcasting向上轉型,向上轉型不用強制轉換。
如:Father f1 = new Son();
3。把指向子類對象的父類引用賦給子類引用叫向下轉型(downcasting),要強制轉換。
如:f1 就是一個指向子類對象的父類引用。把f1賦給子類引用s1即 Son s1 = (Son)f1;
其中f1前面的(Son)必須加上,進行強制轉換。
一、向上轉型。
通俗地講即是將子類對象轉為父類對象。此處父類對象可以是介面。
1,向上轉型中的方法調用。
看下面代碼:
[java] view plaincopyprint?
package com.wensefu.others;
public class Animal {
public void eat(){
System.out.println(“animal eatting…”);
}
}
class Bird extends Animal{
public void eat(){
System.out.println(“bird eatting…”);
}
public void fly(){
System.out.println(“bird flying…”);
}
}
class Main{
public static void main(String[] args) {
Animal b=new Bird(); //向上轉型
b.eat();
//! error: b.fly(); b雖指向子類對象,但此時丟失fly()方法
dosleep(new Male());
dosleep(new Female());
}
public static void dosleep(Human h) {
h.sleep();
}
}
[java] view plaincopyprint?
package com.wensefu.others;
public class Human {
public void sleep() {
System.out.println(“Human sleep..”);
}
}
class Male extends Human {
@Override
public void sleep() {
System.out.println(“Male sleep..”);
}
}
class Female extends Human {
@Override
public void sleep() {
System.out.println(“Female sleep..”);
}
}
注意這裡的向上轉型:
Animal b=new Bird(); //向上轉型
b.eat();
此處將調用子類的eat()方法。原因:b實際指向的是Bird子類,故調用時會調用子類本身的方法。
需要注意的是向上轉型時b會遺失除與父類對象共有的其他方法。如本例中的fly方法不再為b所有。
2,向上轉型的好處。
看上面的代碼,
public static void dosleep(Human h) {
h.sleep();
}
這裡以父類為參數,調有時用子類作為參數,就是利用了向上轉型。這樣使代碼變得簡潔。不然的話,
如果dosleep以子類對象為參數,則有多少個子類就需要寫多少個函數。這也體現了JAVA的抽象編程思想。
二、向下轉型。
與向上轉型相反,即是把父類對象轉為子類對象。
看下面代碼:
[java] view plaincopyprint?
package com.wensefu.other1;
public class Girl {
public void smile(){
System.out.println(“girl smile()…”);
}
}
class MMGirl extends Girl{
@Override
public void smile() {
System.out.println(“MMirl smile sounds sweet…”);
}
public void c(){
System.out.println(“MMirl c()…”);
}
}
class Main{
public static void main(String[] args) {
Girl g1=new MMGirl(); //向上轉型
g1.smile();
MMGirl mmg=(MMGirl)g1; //向下轉型,編譯和運行皆不會出錯
mmg.smile();
mmg.c();
Girl g2=new Girl();
// MMGirl mmg1=(MMGirl)g2; //不安全的向下轉型,編譯無錯但會運行會出錯
// mmg1.smile();
// mmg1.c();
/*output:
* CGirl smile sounds sweet…
* CGirl smile sounds sweet…
* CGirl c()…
* Exception in thread “main” java.lang.ClassCastException: com.wensefu.other1.Girl
* at com.wensefu.other1.Main.main(Girl.java:36)
*/
if(g2 instanceof MMGirl){
MMGirl mmg1=(MMGirl)g2;
mmg1.smile();
mmg1.c();
}
}
}
Girl g1=new MMGirl(); //向上轉型
g1.smile();
MMGirl mmg=(MMGirl)g1; //向下轉型,編譯和運行皆不會出錯
這裡的向下轉型是安全的。因為g1指向的是子類對象。
而
Girl g2=new Girl();
MMGirl mmg1=(MMGirl)g2; //不安全的向下轉型,編譯無錯但會運行會出錯
運行出錯:
Exception in thread “main” java.lang.ClassCastException: com.wensefu.other1.Girl
at com.wensefu.other1.Main.main(Girl.java:36)
如代碼所示,可以通過instanceof來防止出現異常。
關於java的向上轉型
來自CSDN。通俗易懂。
我們在現實中常常這樣說:這個人會唱歌。在這裡,我們並不關心這個人是黑人還是白人,是成人還是小孩,也就是說我們更傾向於使用抽象概念「人」。再例如,麻雀是鳥類的一種(鳥類的子類),而鳥類則是動物中的一種(動物的子類)。我們現實中也經常這樣說:麻雀是鳥。這兩種說法實際上就是所謂的向上轉型,通俗地說就是子類轉型成父類。這也符合Java提倡的面向抽象編程思想。來看下面的代碼:
package a.b;
public class A {
public void a1() {
System.out.println(“Superclass”);
}
}
A的子類B:
package a.b;
public class B extends A {
public void a1() {
System.out.println(“Childrenclass”); //覆蓋父類方法
}
public void b1(){} //B類定義了自己的新方法
}
C類:
package a.b;
public class C {
public static void main(String[] args) {
A a = new B(); //向上轉型
a.a1();
}
}
如果運行C,輸出的是Superclass 還是Childrenclass?不是你原來預期的Superclass,而是Childrenclass。這是因為a實際上指向的是一個子類對象。當然,你不用擔心,Java虛擬機會自動準確地識別出究竟該調用哪個具體的方法。不過,由於向上轉型,a對象會遺失和父類不同的方法,例如b1()。有人可能會提出疑問:這不是多此一舉嗎?我們完全可以這樣寫:
B a = new B();
a.a1();
確實如此!但這樣就喪失了面向抽象的編程特色,降低了可擴展性。其實,不僅僅如此,向上轉型還可以減輕編程工作量。來看下面的顯示器類Monitor:
package a.b;
public class Monitor{
public void displayText() {}
public void displayGraphics() {}
}
液晶顯示器類LCDMonitor是Monitor的子類:
package a.b;
public class LCDMonitor extends Monitor {
public void displayText() {
System.out.println(“LCD display text”);
}
public void displayGraphics() {
System.out.println(“LCD display graphics”);
}
}
陰極射線管顯示器類CRTMonitor自然也是Monitor的子類:
package a.b;
public class CRTMonitor extends Monitor {
public void displayText() {
System.out.println(“CRT display text”);
}
public void displayGraphics() {
System.out.println(“CRT display graphics”);
}
}
等離子顯示器PlasmaMonitor也是Monitor的子類:
package a.b;
public class PlasmaMonitor extends Monitor {
public void displayText() {
System.out.println(“Plasma display text”);
}
public void displayGraphics() {
System.out.println(“Plasma display graphics”);
}
}
現在有一個MyMonitor類。假設沒有向上轉型,MyMonitor類代碼如下:
package a.b;
public class MyMonitor {
public static void main(String[] args) {
run(new LCDMonitor());
run(new CRTMonitor());
run(new PlasmaMonitor());
}
public static void run(LCDMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
public static void run(CRTMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
public static void run(PlasmaMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
}
可能你已經意識到上述代碼有很多重複代碼,而且也不易維護。有了向上轉型,代碼可以更為簡潔:
package a.b;
public class MyMonitor {
public static void main(String[] args) {
run(new LCDMonitor()); //向上轉型
run(new CRTMonitor()); //向上轉型
run(new PlasmaMonitor()); //向上轉型
}
public static void run(Monitor monitor) { //父類實例作為參數
monitor.displayText();
monitor.displayGraphics();
}
}
我們也可以採用介面的方式,例如:
package a.b;
public interface Monitor {
abstract void displayText();
abstract void displayGraphics();
}
將液晶顯示器類LCDMonitor稍作修改:
package a.b;
public class LCDMonitor implements Monitor {
public void displayText() {
System.out.println(“LCD display text”);
}
public void displayGraphics() {
System.out.println(“LCD display graphics”);
}
}
CRTMonitor、PlasmaMonitor類的修改方法與LCDMonitor類似,而MyMonitor可以不不作任何修改。
可以看出,向上轉型體現了類的多態性,增強了程序的簡潔性。
java中關於向上轉型的問題
RTTI機制
向上轉型的目的仍然是抽象。
比如
水果有顏色、味道。不同的水果有不同的顏色和味道。那麼當
水果
sg
=
new
橘子();
水果
sg1
=
new
蘋果();
sg.color();sg.taste();
sg1.color();sg1.taste();
sg,sg1都是水果實例的引用。但會調用不同的具體子類的方法。
其目地都是抽象。通過訪問父類或介面的方法(公共)達到一種對具體實現的封裝。對於介面的使用者來說,不需要關心實現細節。提高內聚,降低不必要的耦合。
再多說一句:注意轉型時帶來的
內存切片。
java向上轉型有什麼作用
java裡面的向上轉型和向下轉型的具體好處如下: 1.轉型是在繼承的基礎上而言的,繼承是面向對象語言中,代碼復用的一種機制,通過繼承,子類可以復用父類的功能,如果父類不能滿足當前子類的需求,則子類可以重寫父類中的方法來加以擴展。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/197647.html