第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java中的顯式類型轉換示例

Java中的顯式類型轉換示例

楊__羊羊 2019-12-25 14:11:09
我在http://www.javabeginner.com/learn-java/java-object-typecasting上遇到了這個示例,在談到顯式類型轉換的部分中,有一個示例使我感到困惑。這個例子:class Vehicle {    String name;    Vehicle() {        name = "Vehicle";    }}class HeavyVehicle extends Vehicle {    HeavyVehicle() {        name = "HeavyVehicle";    }}class Truck extends HeavyVehicle {    Truck() {        name = "Truck";    }}class LightVehicle extends Vehicle {    LightVehicle() {        name = "LightVehicle";    }}public class InstanceOfExample {    static boolean result;    static HeavyVehicle hV = new HeavyVehicle();    static Truck T = new Truck();    static HeavyVehicle hv2 = null;    public static void main(String[] args) {        result = hV instanceof HeavyVehicle;        System.out.print("hV is an HeavyVehicle: " + result + "\n");        result = T instanceof HeavyVehicle;        System.out.print("T is an HeavyVehicle: " + result + "\n");        result = hV instanceof Truck;        System.out.print("hV is a Truck: " + result + "\n");        result = hv2 instanceof HeavyVehicle;        System.out.print("hv2 is an HeavyVehicle: " + result + "\n");        hV = T; //Sucessful Cast form child to parent        T = (Truck) hV; //Sucessful Explicit Cast form parent to child    }}在最后一個為T分配了參考hV且類型轉換為(Truck)的行中,為什么在注釋中說這是從父級到子級的成功顯式轉換?據我了解,強制轉換(隱式或顯式)只會更改對象的聲明類型,而不會更改實際類型(除非您將新的類實例實際分配給該對象的字段引用,否則不應更改)。如果已經為hv分配了HeavyVehicle類的實例,該實例是Truck類的超類,那么如何將該字段類型轉換為一個更具體的子類,該子類從HeavyVehicle類擴展而來?據我了解,強制轉換的目的是限制對對象(類實例)某些方法的訪問。因此,您不能將對象轉換為比該對象實際分配的類具有更多方法的更具體的類。這意味著該對象只能轉換為超類或與實際實例化該類的類相同的類。這是正確的還是我錯了?我仍在學習,所以不確定這是否是正確看待事物的方法。我也知道這應該是向下轉換的示例,但是如果實際類型沒有向下轉換該對象的類的方法,則我不確定這實際上如何工作。顯式轉換是否會以某種方式更改對象的實際類型(而不僅僅是聲明的類型),從而使該對象不再是HeavyVehicle類的實例,而是現在成為Truck類的實例?
查看完整描述

3 回答

?
絕地無雙

TA貢獻1946條經驗 獲得超4個贊

引用vs對象vs類型


對我而言,關鍵是理解對象及其引用之間的區(qū)別,換句話說,就是對象及其類型之間的區(qū)別。


當我們用Java創(chuàng)建對象時,我們聲明了它的真實本質,它將永遠不會改變。但是Java中的任何給定對象都可能具有多種類型。這些類型中的某些顯然歸功于類層次結構,而其他類型則不是那么明顯(即泛型,數組)。


專門針對引用類型,類層次結構規(guī)定了子類型化規(guī)則。例如,在您的示例中,所有卡車均為重型車輛,所有重型車輛均為。因此,這種is-a關系層次結構指示卡車具有多種兼容類型。


創(chuàng)建時Truck,我們定義一個“引用”來訪問它。該引用必須具有這些兼容類型之一。


Truck t = new Truck(); //or

HeavyVehicle hv = new Truck(); //or

Vehicle h = new Truck() //or

Object o = new Truck();

因此,這里的關鍵是要認識到對對象的引用不是對象本身。創(chuàng)建的對象的性質永遠不會改變。但是我們可以使用各種兼容的引用來訪問該對象。這是這里多態(tài)性的特征之一。可以通過引用不同“兼容”類型的對象來訪問同一對象。


當我們進行任何類型的轉換時,我們只是假設不同類型的引用之間具有這種兼容性。


向上轉換或擴展參考轉換


現在,有了類型引用Truck,我們可以輕松得出結論,它始終與類型引用兼容Vehicle,因為所有卡車都是Vehicles。因此,我們可以不使用顯式強制轉換就向上引用該參考。


Truck t = new Truck();

Vehicle v = t;

這也稱為擴展引用轉換,基本上是因為當您進入類型層次結構時,類型會變得更加通用。


如果需要,可以在此處使用顯式轉換,但這不是必需的。我們可以看到t和所引用的實際對象v是相同的。是,并且將永遠是Truck。


向下轉換或縮小參考轉換


現在,有了類型的引用,Vechicle我們不能“安全地”得出結論,它實際上引用了Truck。畢竟,它也可以引用其他形式的車輛。例如


Vehicle v = new Sedan(); //a light vehicle

如果您v在代碼中的某處找到引用,卻不知道引用的是哪個特定對象,則不能“安全地”論證它是指向a Truck還是指向a Sedan或任何其他種類的車輛。


編譯器很清楚,它不能對所引用對象的真實性質提供任何保證。但是程序員通過閱讀代碼可以確定他/她正在做什么。像上述情況一樣,您可以清楚地看到它Vehicle v引用了Sedan。


在這些情況下,我們可以進行下調。之所以這樣稱呼,是因為我們要沿著類型層次結構前進。我們也稱此為縮窄參考轉換。我們可以說


Sedan s = (Sedan) v;

這總是需要顯式的強制轉換,因為編譯器不能確定這樣做是否安全,這就是為什么這就像問程序員“您確定自己在做什么嗎?”。如果您對編譯器撒謊,則ClassCastException在執(zhí)行此代碼時會在運行時得到。


其他種類的分型規(guī)則


Java中還有其他子類型化規(guī)則。例如,還有一個稱為數字提升的概念,它可以自動強制表達式中的數字。像


double d = 5 + 6.0;

在這種情況下,由兩種不同類型(整數和雙精度型)組成的表達式在評估該表達式之前將整數強制轉換/強制為雙精度型,從而產生雙精度值。


您也可以進行原始的向上轉換和向下轉換。如


int a = 10;

double b = a; //upcasting

int c = (int) b; //downcasting

在這些情況下,當信息可能丟失時,需要進行顯式轉換。


某些子類型化規(guī)則可能不那么明顯,例如在數組的情況下。例如,所有引用數組都是的子類型Object[],而原始數組則不是。


對于泛型,尤其是使用通配符(如super和)時extends,情況變得更加復雜。像


List<Integer> a = new ArrayList<>();

List<? extends Number> b = a;


List<Object> c = new ArrayList<>(); 

List<? super Number> d = c;

其中的類型b是的類型的子類型a。的類型d是的類型的子類型c。


裝箱和拆箱也受制于某些強制轉換規(guī)則(不過,在我看來,這也是一種強制形式)。


查看完整回答
反對 回復 2019-12-25
?
不負相思意

TA貢獻1777條經驗 獲得超10個贊

你答對了。您只能將對象成功地強制轉換為其類,其某些父類或該對象或其父級實現的某些接口。如果將其強制轉換為某些父類或接口,則可以將其強制轉換為原始類型。


否則(雖然可以在源代碼中使用它),它將導致運行時ClassCastException。


投射通常用于使在同一字段中存儲不同的東西(具有相同的接口或父類,例如您的所有汽車)或具有相同類型的集合(例如Vehicle)成為可能,以便您可以使用他們以同樣的方式。


如果您隨后希望獲得完全訪問權限,則可以將其撤回(例如,車輛到卡車)


在示例中,我非常確定最后一條語句無效,并且注釋完全錯誤。


查看完整回答
反對 回復 2019-12-25
?
開心每一天1111

TA貢獻1836條經驗 獲得超13個贊

最后一行代碼可以毫無例外地編譯并成功運行。它所做的是完全合法的。


hV最初是指類型為HeavyVehicle的對象(我們將此對象稱為h1):


static HeavyVehicle hV = new HeavyVehicle(); // hV now refers to h1.

稍后,我們將hV引用為卡車類型的另一個對象(我們將此對象稱為t1):


hV = T; // hV now refers to t1.

最后,我們使T參考t1。


T = (Truck) hV; // T now refers to t1.

T已經提到了t1,因此該語句沒有任何改變。


如果已經為hv分配了HeavyVehicle類的實例,該實例是Truck類的超類,那么如何將該字段類型轉換為一個更具體的子類,該子類從HeavyVehicle類擴展而來?

當我們到達最后一行時,hV不再引用HeavyVehicle的實例。它指的是Truck的一個實例。將Truck的實例強制轉換為Truck類型是沒有問題的。


這意味著該對象只能轉換為超類或與實際實例化該類的類相同的類。這是正確的還是我錯了?

基本上是,但是不要將對象本身與引用該對象的變量混淆。見下文。


顯式轉換是否會以某種方式更改對象的實際類型(而不僅僅是聲明的類型),從而使該對象不再是HeavyVehicle類的實例,而是現在成為Truck類的實例?

否。對象一旦創(chuàng)建,就無法更改其類型。它不能成為另一個類的實例。


重申一下,最后一行沒有任何變化。T在該行之前指的是t1,在其后指的是t1。


那么,為什么在最后一行必須進行顯式強制轉換(卡車)?我們基本上只是在幫助編譯器。


我們知道,到那時,hV引用了類型為Truck的對象,因此可以將類型為Truck的對象分配給變量T。但是編譯器還不足夠聰明。編譯器希望我們保證,當到達該行并嘗試進行分配時,它將找到一個正在等待它的Truck實例。


查看完整回答
反對 回復 2019-12-25
  • 3 回答
  • 0 關注
  • 561 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號