[英]Difference between Dynamic and Static type assignments in Java
給定以下類層次結構,以下語句的動態和靜態類型是什么?
類層次結構:
class Alpha {}
class Beta extends Alpha {}
class Gamma extends Alpha {}
class Epsilon extends Alpha{}
class Fruit extends Gamma{}
class Golf extends Beta {}
class Orange extends Fruit{}
對於以下每個語句,靜態類型? 動態類型?:
Fruit f = new Fruit();
Alpha a = f;
Beta b = f;
a = b;
Gamma g = f;
我的回答/問題
我知道Fruit f = new Fruit()
將是靜態和動態類型的Fruit。
Alpha a = f;
在編譯時將是Alpha類型(靜態)並在運行時鍵入Fruit(動態)。
Gamma g = f;
在編譯時將是Gamma類型(靜態)並在運行時鍵入Fruit(動態)。
但是我不知道另外兩個答案。 Beta b = f是一個實例,其中同一個超類的兩個子類彼此分配,所以我不確定它在編譯時是類型Beta還是類型Alpha(靜態)。 並且a = b是聲明后的賦值,所以我不確定答案是什么。 有人請幫幫我謝謝!
我正在匆匆打字,所以請原諒任何錯別字(我稍后會在有機會時解決這些問題)。
我知道Fruit f = new Fruit()將是靜態和動態類型的Fruit。
我認為您將static and dynamic
類型與編譯時和運行時類型混淆了一下(或者在將類型A的對象的地址分配給類型B的指針時,在C ++中使用B作為父類A.)
除了反射技巧,Java中沒有動態類型。 在編譯時,所有內容都是靜態類型的。 運行時對象的類型與編譯到的對象類型相同。
發生的事情是,您將對象引用(a,b,c,f)與在堆中實例化的實際對象(使用new
創建的任何對象)混淆。
在Java中, f
是對象引用,而不是對象本身。 而且, f
的引用類型是Fruit and sub-classes of it
。 您分配給它的對象( new Fruit()
)恰好是Fruit
類型。
現在您的示例代碼中的所有其他引用,a是reference to A and sub-classes of it
的類型reference to A and sub-classes of it
; b是reference to B and sub-classes of it
類型reference to B and sub-classes of it
; 等等
請記住這一點,因為它非常重要。
Alpha a = f; 在編譯時將是Alpha類型(靜態)並在運行時鍵入Fruit(動態)。
a的類型是'對類型A和子類的引用'。 f的類型是'類型Fruit和子類的引用'。
對象f指向的是'Fruit'類型。 當你說'a = f'時,你沒有將'f'分配給'a'。 你說'現在將引用f當前引用的東西'。
這樣分配之后,什么是a
參考? 對象引用f
在賦值時指向的類型為Fruit
的對象。
記住,a,b,g,f,它們不是對象。 它們是使用new
運算符以某種方式創建的對象的引用或句柄。
諸如a,b或f之類的引用變量是與使用new
創建的對象不同的動物。 但事實恰恰相反,前者可以指向后者。
在運行時使用new創建的對象的類型與在編譯時確定的對象的類型相同。
伽瑪g = f; 在編譯時將是Gamma類型(靜態)並在運行時鍵入Fruit(動態)。
與上述相同。 變量g
是reference to type Gamma and sub-classes
的類型reference to type Gamma and sub-classes
的對象引用。 在這個賦值中, g
被指向f
指向的同一個對象。 那個對象的類型是什么? 在編譯時給出的相同:果實。
但是我不知道另外兩個答案。 Beta b = f是一個實例,其中同一個超類的兩個子類彼此分配,所以我不確定它在編譯時是類型Beta還是類型Alpha(靜態)。
b是reference to type Beta and sub-classes of it
類型reference to type Beta and sub-classes of it
。 在賦值b = f
之后它指向的對象是Fruit
類型,它在編譯時具有的類型。
在編譯時確定對象a,b,g和f的類型。 它們是靜態類型的,不會在運行時更改。
使用new
創建的對象的類型也在編譯時確定。 它們也是靜態類型的,不會在運行時更改。
對象,stuff對象引用a,b,g和f指向運行時 ,這取決於編譯器是否發現語句有效。 賦值可以更改,但這與對象引用或對象本身是靜態還是動態類型無關。
如果要查看動態和靜態類型之間的明確區別,請考慮以下事項:
// Java, statically typed.
int x = 3;
x = 5; // good
x = "hi"; // compiler error
## Ruby, dynamically typed
x = 3 # ok
x = 5 # ok
x = "hi" # still ok
然后是強類型語言和弱/鴨類型語言之間的區別(兩者都可以動態輸入。)有很多關於這個主題的文獻。
希望能幫助到你。
以下語句的動態和靜態類型
嗯,一個語句沒有類型,至少在Java語言規范中沒有這樣的概念。 規范確實定義了兩種不同的類型: 聲明的變量類型 ,字段或參數,以及對象的運行時類 。
如名稱所示,變量,字段或參數的聲明類型是您在聲明中提到的類型。 例如,聲明Foo bar;
聲明一個變量命名的bar
類型的Foo
。
對象的運行時類由用於構造它的類實例或數組創建表達式確定,並且在該對象的整個生命周期內保持不變。
所以代碼:
Integer i = 1;
Number n = i;
Object o = n;
聲明分別為Integer
, Number
和Object
類型的3個變量,所有這些變量都引用具有運行時類Integer
的單個對象。
f
的具體運行時類型是Fruit(正如您在問題中正確指出的那樣)。
所以Beta b = f;
初始化一個聲明的,編譯時類型為Beta的變量,其運行時類型為Fruit。 這不會編譯,因為f
的編譯時類型是Fruit,而Fruit不是Beta的子類,所以f
不能分配給Beta類型的變量。
在a = b;
, b
,其運行時類型為Fruit(見上文)被賦值給變量a
,聲明為Alpha a
。 所以a
的編譯時類型是Alpha和它的運行時類型是水果。
首先澄清“參考變量”類型:
Object obj;
指向任何東西,參考變量obj將沒有類型。 現在
Object obj = new String();
System.out.println(obj.getClass());//prints class java.lang.String
obj指向String,引用變量obj指向String類型。
關鍵是Java是一種靜態類型語言,所有引用類型變量都有一個在編譯時分配的類型。 引用變量obj可以指向其他對象,只要它是Object的子類即可。 在這種情況下幾乎任何事情 考慮
Object obj = new String();
System.out.println(obj.getClass());//prints class java.lang.String
Number num = new Byte((byte)9);
obj = num;
System.out.println(obj.getClass());//prints class java.lang.Byte
在運行時,與編譯時相同,引用變量obj具有類型Byte。
對我來說,對象的靜態/動態類型與繼承有關。 更具體地說,是壓倒一切的機制。 也稱為動態多態和后期綁定。
考慮覆蓋Object類中的equals():
public class Types {
@Override
public boolean equals(Object obj){
System.out.println("in class Types equals()");
return false;//Shut-up compiler!
}
public static void main(String[] args){
Object typ = new Types();
typ.equals("Hi");//can do this as String is a subclass of Object
}
}
現在我們知道引用變量typ的類型是Types。
Object typ = new Types();
到那個時刻
typ.equals("Hi");
這就是我認為編譯器的想法。
如果等於()是
1.NOT靜態和最終,它是。
2.從基類引用(更多關於這一點)。
然后編譯器推遲調用JVM的方法。 調用的確切方法取決於調用該方法的變量的動態類型 (更快)。 在我們的例子中,參考變量是典型的。 這稱為動態方法調用。
現在引用一個基類:來自上面的代碼
Object typ = new Types();
typ.equals("Hi");
類型Object可以被視為typ的基本類型,也稱為引用變量的靜態類型 ,equals()從基類型引用,在本例中為Object。
如果我們有
Types typ = new Types();
沒有基類型的引用,因此沒有動態方法調用。
現在到參考變量的動態類型 。
Object typ = new Types();
typ.equals("Hi");
類型的動態類型是類型,根據動態方法調用,類類型中的equals()將在運行時調用。
還可以說我們有另一個擴展Types,TypesSubClass的類。 而TypesSubClass也有一個重寫的equals()。 然后
Object typ = new TypesSubClass();
typ.equals("Hi");
是否會在運行時調用類型為TypesSubClass和TypesSubClass的equals()的動態類型 。
說實話,我個人不知道為什么我們需要所有這些,並發布了一個有關此問題。 校驗
你應該看一下這篇文章: http : //www.sitepoint.com/typing-versus-dynamic-typing/
靜態類型是指語言不需要初始化變量。
例如。
/* C code */
static int num, sum; // explicit declaration
num = 5; // now use the variables
sum = 10;
sum = sum + num;
動態類型是指語言需要初始化變量。
例如。
/* Python code */
num = 10 // directly using the variable
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.