1.
紅河ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!
引用a的類型是animal,是cat的父類。所以是“父類引用指向子類對象”。如果是“子類引用指向父類對象”,那應(yīng)該寫成
cat
a
=
new
animal();但這顯然是不和邏輯的。
2.
你說的沒錯——“向上轉(zhuǎn)型后,父類也只能調(diào)用父類已經(jīng)有的方法”。但是子類如果覆蓋了父類的方法,那么即使向上轉(zhuǎn)型,方法的行為也表現(xiàn)為覆蓋后的行為。這也是多態(tài)的一種體現(xiàn)。向上轉(zhuǎn)型更多的用來體現(xiàn)一種編程上的“約定”。所有繼承某個類或者實現(xiàn)某個接口的類,一定包含某個方法,這樣在調(diào)用的時候,使得你也不必關(guān)系具體的實現(xiàn)細(xì)節(jié),只要知道“這個類型中的某個方法能幫我完成工作”就可以了。
3.
向下轉(zhuǎn)型,是“引用的類型”的變化,不是對象實例類型的變化。new什么,就是什么。不會因為向上或者向下轉(zhuǎn)型而改變自己的類型。
4.
最后一個問題,不管向上還是向下轉(zhuǎn)型,調(diào)用的都是實際類型中的那個方法。比如,animal
a
=
new
cat(); a.叫()。那這個叫就是cat類型實例中的“叫”方法。
呵呵,這個問題有意思了。
最大的用處是java的泛型編程,用處很大,java的集合類都是這樣的,不過由于是向下轉(zhuǎn)型,所以不是安全的。 下面是向下轉(zhuǎn)型的例子:
子類轉(zhuǎn)型成父類是向上轉(zhuǎn)型,反過來說,父類轉(zhuǎn)型成子類就是向下轉(zhuǎn)型。但是,向下轉(zhuǎn)型可能會帶來一些問題:我們可以說麻雀是鳥,但不能說鳥就是麻雀。來看下面的例子:
A類:
package a.b;
public class A {
void aMthod() {
System.out.println("A method");
}
}
A的子類B:
package a.b;
public class B extends A {
void bMethod1() {
System.out.println("B method 1");
}
void bMethod2() {
System.out.println("B method 2");
}
}
C類:
package a.b;
public class C {
public static void main(String[] args) {
A a1 = new B(); // 向上轉(zhuǎn)型
a1.aMthod(); // 調(diào)用父類aMthod(),a1遺失B類方法bMethod1()、bMethod2()
B b1 = (B) a1; // 向下轉(zhuǎn)型,編譯無錯誤,運行時無錯誤
b1.aMthod(); // 調(diào)用父類A方法
b1.bMethod1(); // 調(diào)用B類方法
b1.bMethod2(); // 調(diào)用B類方法
A a2 = new A();
B b2 = (B) a2; // 向下轉(zhuǎn)型,編譯無錯誤,運行時將出錯
b2.aMthod();
b2.bMethod1();
b2.bMethod2();
}
}
從上面的代碼我們可以得出這樣一個結(jié)論:向下轉(zhuǎn)型需要使用強制轉(zhuǎn)換。運行C程序,控制臺將輸出:
Exception in thread "main" java.lang.ClassCastException: a.b.A cannot be cast to a.b.B at
a.b.C.main(C.java:14)
A method
A method
B method 1
B method 2
其實黑體部分的向下轉(zhuǎn)型代碼后的注釋已經(jīng)提示你將發(fā)生運行時錯誤。為什么前一句向下轉(zhuǎn)型代碼可以,而后一句代碼卻出錯?這是因為a1指向一個子類B的對象,所以子類B的實例對象b1當(dāng)然也可以指向a1。而a2是一個父類對象,子類對象b2不能指向父類對象a2。那么如何避免在執(zhí)行向下轉(zhuǎn)型時發(fā)生運行時ClassCastException異常?使用5.7.7節(jié)學(xué)過的instanceof就可以了。我們修改一下C類的代碼:
A a2 = new A();
if (a2 instanceof B) {
B b2 = (B) a2;
b2.aMthod();
b2.bMethod1();
b2.bMethod2();
}
這樣處理后,就不用擔(dān)心類型轉(zhuǎn)換時發(fā)生ClassCastException異常了。
你的myq本身就是通過new出來的,為什么需要轉(zhuǎn)形呢?這里不存在任何需要轉(zhuǎn)型的要求呀!
如果需要轉(zhuǎn)型,在你調(diào)用myGet方法得到容器中的內(nèi)容時是有轉(zhuǎn)型需求的,因為你的myAdd方法添加的是Object,取出后也會是一個Object對象,即放入時是通過向上轉(zhuǎn)型過的,如果取出后不進(jìn)行向下轉(zhuǎn)型,那么取出的對象只能看作是一個Object對象。
例如:
MyQueue myq = new MyQueue();
//假設(shè)有一個類Student中有一個方法getName得到學(xué)生的姓名信息;
Student student = new Student();
student.setName("張三");
myq.add(student);
//下面的這一種方式是必須向下轉(zhuǎn)型的
Student stu = (Student)myq.myGet();
//下面的這種方式是不需要向下轉(zhuǎn)型的
Object stu1 = myq.myGet();
//因為放入的都是作為Object看待的,取出的也是Object,只有轉(zhuǎn)型成相應(yīng)的對象才能進(jìn)行
//如getName的操作
stu.getName();
//stu1.getName();錯
下轉(zhuǎn)型就是你上轉(zhuǎn)型后才能做的操作;
例如:Map map = new HashMap(); 上轉(zhuǎn)型
HashMap hmap = map;下轉(zhuǎn)型
一般上轉(zhuǎn)型都是實現(xiàn)接口編程的,減少兩個類之間的偶合;
下轉(zhuǎn)型一般是封裝好的對象在解封而已。
首先還是給出解決辦法吧:
package d;
import c.F;
public class A extends F
{
public static void main(String[] args)
{?
? A temp = new A();
? F f = (F) temp;
? if (f instanceof A)
? {?
? ? ? A a = (A) f;
? ? ? System.out.println(a.a());
? }?
}?
輸出結(jié)果:
你的要求無法實現(xiàn)。因為在你的例子中,f本身并不是由A類型向上轉(zhuǎn)型為F得來的,所以本身是不會帶有A的特性的,強制轉(zhuǎn)換為A會失敗,因為f在堆中的內(nèi)容并未包括A類型的特性。即使你強制轉(zhuǎn)換為A,A的新構(gòu)造函數(shù)并不會調(diào)用,所有A額外的特性不會在堆中聲明,所以會報錯。Java中的向下轉(zhuǎn)型是有條件的,你向下轉(zhuǎn)型的對象必須原本在堆中包含了目的類型的內(nèi)容,也就是說這個對象必須原本就是目的類型或其子類,只不過是通過向上轉(zhuǎn)型現(xiàn)在不是目的類型或其子類罷了(但是堆中還是由該目的類型的特性存在,理解這一點很重要?。?/p>
有一個簡單的辦法驗證這一點,就是你向下轉(zhuǎn)型的時候,目的類型的構(gòu)造函數(shù)并不會再一次調(diào)用,這樣一來也就不會有目的類型的特性了,調(diào)用目的類型的特性自然而然就會失敗了:
class Parent
{
public Parent()
{?
? System.out.println("This is Parent");
}?
}
public class Child extends Parent
{
public Child()
{?
? System.out.println("This is Child");
}?
public static void print()
{?
? System.out.println("print()");
}?
public static void main(String[] args)
{?
? Child test1 = new Child();
? Parent temp1 = (Parent) test1;
? Child target1 = (Child) temp1;
? target1.print();
? Parent test2 = new Parent();
? Child target2 = (Child) test2;
? target2.print(); // 報錯
}?
}
輸出結(jié)果:
還有不理解可以追問。