簡體   English   中英

Java中動態和靜態類型賦值之間的區別

[英]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(動態)。

與上述相同。 變量greference 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類型,它在編譯時具有的類型。

  1. 在編譯時確定對象a,b,g和f的類型。 它們是靜態類型的,不會在運行時更改。

  2. 使用new創建的對象的類型也在編譯時確定。 它們也是靜態類型的,不會在運行時更改。

  3. 對象,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;

聲明分別為IntegerNumberObject類型的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()的動態類型

說實話,我個人不知道為什么我們需要所有這些,並發布了一個有關此問題。 校驗

在像Java這樣的靜態類型語言中動態方法解析背后的原因是什么

你應該看一下這篇文章: 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM