編譯期只會檢查實例聲明的類型和強制轉化的類型是否存在extend/implement關系,因為從聲明變數類型,到強制轉化變數的類型之間可能存在編譯期無法解析的代碼,雖然示例中只是一個簡單的賦值,肉眼就可以判斷實際類型,但是對於編譯器來說是無法判斷的,舉個簡單的例子:
public static void foo(boolean flag) {
Useful xx = flag ? new Useful() : new MoreUseful();
((MoreUseful)xx).g(); // 編譯器如何判斷此處是否有錯誤?
// flag=false的時候可以正常運行,就不能說這里有編譯期錯誤}public static void main(String[] args) {
foo(true);
foo(false);
}
② 求教JAVA編譯與運行的區別。
編譯只是編譯成了位元組碼,就是可執行的.class文件
運行時識別,主要是java的RTTI(運行時類型識別)機制和反射機制,而兩者之間的區別在於:
」對RTTI來說,編譯器在編譯期打開和檢查.class文件。(換句話說,我們可以用「普通」的方式調用一個對象的所有方法。),而對於反射機制來說,.class文件在編譯期是不可獲取的,所以是在運行期打開和檢查.class文件。「
但是同樣的,反射也需要載入這個類的Class對象,所以那個類的class對象對於jvm必須是可取的的,比如在本地機器上,或者通過網路取得,比如取得一串位元組串。
具體的內容可以參考《Thinking
in
java》的」類型識別「那一章,講的比較詳細的
③ JAVA多態中的隱藏和覆蓋
Java的引用變數有兩個類型,一個是編譯時類型,一個是運行時類型
編譯時類型:由聲明該變數時使用的類型決定
運行時類型:由該變數指向的對象類型決定
如果編譯時類型和運行時類型不一致,會出現所謂的多態。因為子類其實是一種特殊的父類,因此java允許把一個子類對象直接賦值給一個父類引用變數,無須任何類型轉換,或者被稱為向上轉型,由系統自動完成。
如 Father f = new Son(); Son是Father的子類
引用變數f就會出現編譯時類型和運行時類型不一致的情況 編譯時是Father類型的 運行時是Son類型的
當變數的編譯時類型和運行時類型不一致時,通過變數訪問它所引用的對象的實例時,該實例變數的值由聲明該變數的類型決定。
通過變數訪問它所引用的對象的方法時,該方法的行為由所引用的對象實際類型所決定。
④ 為什麼數組要在編譯期確定大小
從變成方面來看:定義一個數組是要用到數據類型的(byte,short,int,long,float,double,char)的, 而調用這些數據類型會在堆中建立該數組的對象,如果想要這個數組有值,那就一定會在數據區開區間,建立該對象的值。所以數組如果要有意義,編譯期肯定要賦值。否則雖然不會報錯,但莫名其面佔用存儲空間總歸不好。
⑤ 按異常在編譯時是否被檢測來分,異常可以分成哪兩種
檢查時異常(checkException)和運行時異常(runtime Exception)
⑥ C++類型轉換規則、何時發生隱式類型轉換及強制類型轉換適用場合
C++做為強類型語言,要求編譯期的類型聲明與檢查,要求表達式中各操作數的類型(包括賦值操作的左值和右值,以及形參和實參)具有一致性,但同時也允許一定的靈活性,允許類型在一定程度上的兼容,也就是允許類型遵循一定規則下的隱式轉換和強制轉換。
The type of the operand(s) determine whether an expression is legal and, if the expression is legal, determines the meaning of the expression. However, in C++ some types are related to one another. When two types are related, we can use an object or value of one type where an operand of the related type is expected. Two types are related if there is a conversion between them.
表達式是否合法取決於操作數的類型,而且合法的表達式其含義也由其操作數類型決定。但是,在 C++ 中,某些類型之間存在相關的依賴關系。若兩種類型相關,則可在需要某種類型的操作數位置上,使用該類型的相關類型對象或值。如果兩個類型之間可以相互 轉換 ,則稱這兩個類型相關。
1.1 The Arithmetic Conversions 算術轉換
The language defines a set of conversions among the built-in types. Among these, the most common are the arithmetic conversions , which ensure that the two operands of a binary operator, such as an arithmetic or logical operator, are converted to a common type before the operator is evaluated. That common type is also the result type of the expression.
C++ 語言為內置類型提供了一組轉換規則,其中最常用的是 算術轉換 。算術轉換保證在執行操作之前,將二元操作符(如算術或邏輯操作符)的兩個操作數轉換為同一類型,並使表達式的值也具有相同的類型。
The rules define a hierarchy of type conversions in which operands are converted to the widest type in the expression. The conversion rules are defined so as to preserve the precision of the values involved in a multi-type expression. For example, if one operand is of type long double, then the other is converted to type long double regardless of what the second type is.
算術轉換規則定義了一個類型轉換層次,該層次規定了操作數應按什麼次序轉換為表達式中最寬的類型。在包含多種類型的表達式中,轉換規則要確保計算值的精度。例如,如果一個操作數的類型是 long double,則無論另一個操作數是什麼類型,都將被轉換為 long double。
The simplest kinds of conversion are integral promotions . Each of the integral types that are smaller than int char, signed char, unsigned char, short, and unsigned shortis promoted to int if all possible values of that type fit in an int. Otherwise, the value is promoted to unsigned int. When bool values are promoted to int, a false value promotes to zero and true to one.
最簡單的轉換為 整型提升 :對於所有比 int 小的整型,包括 char、signed char、unsigned char、short 和 unsigned short,如果該類型的所有可能的值都能包容在 int 內,它們就會被提升為 int 型,否則,它們將被提升為 unsigned int。如果將 bool 值提升為 int ,則 false 轉換為 0,而 true 則轉換為 1。
需要注意的,上述所謂的轉換只是運算時的類型轉換,存儲時還會轉換為其聲明時的類型。
1.2 Conversions between Signed and Unsigned Types 有符號與無符號類型之間的轉換
When an unsigned value is involved in an expression, the conversion rules are defined to preserve the value of the operands. Conversions involving unsigned operands depend on the relative sizes of the integral types on the machine. Hence, such conversions are inherently machine dependent.
若表達式中使用了無符號( unsigned )數值,所定義的轉換規則需保護操作數的精度。unsigned 操作數的轉換依賴於機器中整型的相對大小,因此,這類轉換本質上依賴於機器。
In expressions involving shorts and ints, values of type short are converted to int. Expressions involving unsigned short are converted to int if the int type is large enough to represent all the values of an unsigned short. Otherwise, both operands are converted to unsigned int. For example, if shorts are a half word and ints a word, then any unsigned value will fit inside an int. On such a machine, unsigned shorts are converted to int.
包含 short 和 int 類型的表達式, short 類型的值轉換為 int 。如果 int 型足夠表示所有 unsigned short 型的值,則將 unsigned short 轉換為 int,否則,將兩個操作數均轉換為 unsigned int 。例如,如果 short 用半字表示而 int 用一個字表示,則所有 unsigned 值都能包容在 int 內,在這種機器上, unsigned short 轉換為 int。
The same conversion happens among operands of type long and unsigned int. The unsigned int operand is converted to long if type long on the machine is large enough to represent all the values of the unsigned int. Otherwise, both operands are converted to unsigned long.
long 和 unsigned int 的轉換也是一樣的。只要機器上的 long 型足夠表示 unsigned int 型的所有值,就將 unsigned int 轉換為 long 型,否則,將兩個操作數均轉換為 unsigned long 。
On a 32-bit machine, long and int are typically represented in a word. On such machines, expressions involving unsigned ints and longs are converted to unsigned long.
在 32 位的機器上,long 和 int 型通常用一個字長表示,因此當表達式包含 unsigned int 和 long 兩種類型,其操作數都應轉換為 unsigned long 型。
Conversions for expressions involving signed and unsigned int can be surprising. In these expressions the signed value is converted to unsigned. For example, if we compare a plain int and an unsigned int, the int is first converted to unsigned. If the int happens to hold a negative value, the result will be converted as described as belows, with all the attendant problems discussed there.
對於包含 signed 和 unsigned int 型的表達式,其轉換可能出乎我們的意料。表達式中的 signed 型數值會被轉換為 unsigned 型。例如,比較 int 型和 unsigned int 型的簡單變數,系統首先將 int 型數值轉換為 unsigned int 型,如果 int 型的值恰好為負數,其結果將以下述方法轉換,並帶來其所有副作用。
The compiler applies conversions for both built-in and class type objects as necessary. Implicit type conversions take place in the following situations:
編譯器在必要時將類型轉換規則應用到內置類型和類類型的對象上。在下列情況下,將發生隱式類型轉換:
In expressions with operands of mixed types, the types are converted to a common type:
在混合類型的表達式中,其操作數被轉換為相同的類型:
An expression used as a condition is converted to bool:
用作條件的表達式被轉換為 bool 類型:
Conditions occur as the first operand of the conditional (?:) operator and as the operand(s) to the logical NOT (!), logical AND (&&), and logical OR (||) operators. Conditions also appear in the if, while, for, and do while statements.
條件操作符(?:)中的第一個操作數以及邏輯非(!)、邏輯與(&&)和邏輯或(||)的操作數都是條件表達式。出現在 if、while、for 和 do while 語句中的同樣也是條件表達式。
An expression used to initialize or assign to a variable is converted to the type of the variable:
用一表達式初始化某個變數,或將一表達式賦值給某個變數,則該表達式被轉換為該變數的類型:
In addition,implicit conversions also occur ring function calls.
另外,在函數調用中也可能發生隱式類型轉換。
3.1 static_cast
Any type conversion that the compiler performs implicitly can be explicitly requested by using a static_cast:
編譯器隱式執行的任何類型轉換都可以由 static_cast 顯式完成:
Such casts are useful when assigning a larger arithmetic type to a smaller type. The cast informs both the reader of the program and the compiler that we are aware of and are not concerned about the potential loss of precision. Compilers often generate a warning for assignments of a larger arithmetic type to a smaller type. When we provide the explicit cast, the warning message is turned off.
當需要將一個較大的算術類型賦值給較小的類型時,使用強制轉換非常有用。此時,強制類型轉換告訴程序的讀者和編譯器:我們知道並且不關心潛在的精度損失。對於從一個較大的算術類型到一個較小類型的賦值,編譯器通常會產生警告。當我們顯式地提供強制類型轉換時,警告信息就會被關閉。
A static_cast is also useful to perform a conversion that the compiler will not generate automatically. For example, we can use a static_cast to retrieve a pointer value that was stored in a void* pointer:
如果編譯器不提供自動轉換,使用 static_cast 來執行類型轉換也是很有用的。例如,下面的程序使用 static_cast 找回存放在 void* 指針中的值:
When we store a pointer in a void* and then use a static_cast to cast the pointer back to its original type, we are guaranteed that the pointer value is preserved. That is, the result of the cast will be equal to the original address value.
可通過 static_cast 將存放在 void* 中的指針值強制轉換為原來的指針類型,此時我們應確保保持指針值。也就是說,強制轉換的結果應與原來的地址值相等。
3.2 const_cast
A const_cast, as its name implies, casts away the constness of its expression. For example, we might have a function named string_ that we are certain reads, but does not write, its single parameter of type char*. If we have access to the code, the best alternative would be to correct it to take a const char*. If that is not possible, we could call string_ on a const value using a const_cast:
const_cast ,顧名思義,將 轉換掉 表達式的 const 性質。例如,假設有函數 string_,只有唯一的參數,為 char* 類型,我們對該函數只讀不寫。在訪問該函數時,最好的選擇是修改它讓它接受 const char* 類型的參數。如果不行,可通過 const_cast 用一個 const 值調用 string_ 函數:
Only a const_cast can be used to cast away constness. Using any of the other three forms of cast in this case would result in a compile-time error. Similarly, it is a compile-time error to use the const_cast notation to perform any type conversion other than adding or removing const.
只有使用 const_cast 才能將 const 性質轉換掉。在這種情況下,試圖使用其他三種形式的強制轉換都會導致編譯時的錯誤。類似地,除了添加或刪除 const 特性,用 const_cast 符來執行其他任何類型轉換,都會引起編譯錯誤。
3.3 reinterpret_cast
A reinterpret_cast generally performs a low-level reinterpretation of the bit pattern of its operands.
reinterpret_cast 通常為操作數的位模式提供較低層次的重新解釋。
A reinterpret_cast is inherently machine-dependent. Safely using reinterpret_cast requires completely understanding the types involved as well as the details of how the compiler implements the cast.
reinterpret_cast 本質上依賴於機器。為了安全地使用 reinterpret_cast,要求程序員完全理解所涉及的數據類型,以及編譯器實現強制類型轉換的細節。
在引入命名的強制類型轉換操作符之前,顯式強制轉換用圓括弧將類型括起來實現:
The effect of this cast is the same as using the reinterpret_cast notation. However, the visibility of this cast is considerably less, making it even more difficult to track down the rogue cast.
效果與使用 reinterpret_cast 符號相同,但這種強制轉換的可視性比較差,難以跟蹤錯誤的轉換。
Depending on the types involved, an old-style cast has the same behavior as a const_cast, a static_cast, ora reinterpret_cast. When used where a static_cast or a const_cast would be legal, an old-style cast does the same conversion as the respective named cast. If neither is legal, then an old-style cast performs a reinterpret_cast. For example, we might rewrite the casts from the previous section less clearly using old-style notation:
舊式強制轉換依賴於所涉及的數據類型,具有與 const_cast、 static_cast 和 reinterpret_cast 一樣的行為。在合法使用 static_cast 或 const_cast 的地方,舊式強制轉換提供了與各自對應的命名強制轉換一樣的功能。如果這兩種強制轉換均不合法,則舊式強制轉換執行 reinterpret_cast 功能。例如,我們可用舊式符號重寫上一節的強制轉換:
By using a cast, the programmer turns off or dampens normal type-checking. We strongly recommend that programmers avoid casts and believe that most well-formed C++ programs can be written without relying on casts.
強制類型轉換關閉或掛起了正常的類型檢查。強烈建議程序員避免使用強制類型轉換,不依賴強制類型轉換也能寫出很好的 C++ 程序。
arithmetic conversion(算術轉換)
A conversion from one arithmetic type to another. In the context of the binary arithmetic operators, arithmetic conversions usually attempt to preserve precision by converting a smaller type to a larger type (e.g., small integral types, such as char and short, are converted to int).
算術類型之間的轉換。在使用二元算術操作符的地方,算術轉換通常將較小的類型轉換為較大的類型,以確保精度(例如,將小的整型 char 型和 short 型轉換為 int 型)。
dynamic_cast
Used in combination with inheritance and run-time type identification.
用於結合繼承和運行時類型識別。
implicit conversion(隱式類型轉換)
A conversion that is automatically generated by the compiler. Given an expression that needs a particular type but has an operand of a differing type , the compiler will automatically convert the operand to the desired type if an appropriate conversion exists.
編譯器自動實現的類型轉換。假設表達式需要某種特定類型的數值,但其操作數卻是其他不同的類型, 此時如果系統定義了適當的類型轉換 ,編譯器會自動根據轉換規則將該操作數轉換為需要的類型。
integral promotions(整型提升)
Subset of the standard conversions that take a smaller integral type to its most closely related larger type. Integral types (e.g. short, char, etc.) are promoted to int or unsigned int.
整型提升是標准類型轉換規則的子集,它將較小的整型轉換為最接近的較大數據類型。整型(如 short、char 等)被提升為 int 型或 unsigned int 型。
reinterpret_cast
Interprets the contents of the operand as a different type. Inherently machine-dependent and dangerous.
將操作數內容解釋為另一種不同的類型。這類強制轉換本質上依賴於機器,而且是非常危險的。
static_cast
An explicit request for a type conversion that the compiler would do implicitly. Often used to override an implicit conversion that the compiler would otherwise perform.
編譯器隱式執行的任何類型轉換都可以由 static_cast 顯式完成。我們常常使用 static_cast 取代由編譯器實現的隱式轉換。
-End-