站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题java虚拟机详述-第二章(一)

java虚拟机详述-第二章(一)

摘要: java虚拟机详述-第二章(一)
内容: Java Programming Language Concepts

--------------------------------------------------------------------------------

The Java virtual machine was designed to support the Java programming language. Some concepts and vocabulary from the Java programming language are thus useful when attempting to understand the virtual machine. This chapter gives an overview intended to support the specification of the Java virtual machine, but is not itself a part of that specification.

The content of this chapter has been condensed from the first edition of The JavaTM Language Specification, by James Gosling, Bill Joy, and Guy Steele.1 Readers familiar with the Java programming language, but not with The JavaTM Language Specification, should at least skim this chapter for the terminology it introduces. Any discrepancies between this chapter and The JavaTM Language Specification should be resolved in favor of The JavaTM Language Specification.

This chapter does not attempt to provide an introduction to the Java programming language. For such an introduction, see The JavaTM Programming Language, Second Edition, by Ken Arnold and James Gosling.



--------------------------------------------------------------------------------

2.1 Unicode
Programs written in the Java programming language supported by JDK release 1.1.7 and the Java 2 platform, v1.2 use the Unicode character encoding, version 2.1, as specified in The Unicode Standard, Version 2.0, ISBN 0-201-48345-9, and the update information for Version 2.1 of the Unicode Standard available at http:// www.unicode.org. Programs written in the Java programming language used version 2.0.14 of the Unicode Standard in JDK releases 1.1 through 1.1.6 and used version 1.1.5 of the Unicode Standard in JDK release 1.0.
Except for comments, identifiers (§2.2), and the contents of character and string literals (§2.3), all input elements in a program written in the Java programming language are formed from only ASCII characters. ASCII (ANSI X3.4) is the American Standard Code for Information Interchange. The first 128 characters of the Unicode character encoding are the ASCII characters.



--------------------------------------------------------------------------------

2.2 Identifiers
An identifier is an unlimited-length sequence of Unicode letters and digits, the first of which must be a letter. Letters and digits may be drawn from the entire Unicode character set, which supports most writing scripts in use in the world today. This allows programmers to use identifiers in their programs that are written in their native languages.
The method (§2.10) Character.isJavaLetter returns true when passed a Unicode character that is considered to be a letter in an identifier. The method Character.isJavaLetterOrDigit returns true when passed a Unicode character that is considered to be a letter or digit in an identifier.

Two identifiers are the same only if they have the same Unicode character for each letter or digit; identifiers that have the same external appearance may still be different. An identifier must not be the same as a boolean literal (§2.3), the null literal (§2.3), or a keyword in the Java programming language.



--------------------------------------------------------------------------------

2.3 Literals
A literal is the source code representation of a value of a primitive type (§2.4.1), the String type (§2.4.8), or the null type (§2.4). String literals and, more generally, strings that are the values of constant expressions are "interned" so as to share unique instances, using the method String.intern.
The null type has one value, the null reference, denoted by the literal null. The boolean type has two values, denoted by the literals true and false.



--------------------------------------------------------------------------------

2.4 Types and Values
The Java programming language is strongly typed, which means that every variable and every expression has a type that is known at compile time. Types limit the values that a variable (§2.5) can hold or that an expression can produce, limit the operations supported on those values, and determine the meaning of those operations. Strong typing helps detect errors at compile time.
The types of the Java programming language are divided into two categories: primitive types (§2.4.1) and reference types (§2.4.6). There is also a special null type, the type of the expression null, which has no name. The null reference is the only possible value of an expression of null type and can always be converted to any reference type. In practice, the programmer can ignore the null type and just pretend that null is a special literal that can be of any reference type.

Corresponding to the primitive types and reference types, there are two categories of data values that can be stored in variables, passed as arguments, returned by methods, and operated upon: primitive values (§2.4.1) and reference values (§2.4.6).


2.4.1 Primitive Types and Values
A primitive type is a type that is predefined by the Java programming language and named by a reserved keyword. Primitive values do not share state with other primitive values. A variable whose type is a primitive type always holds a primitive value of that type.2
The primitive types are the boolean type and the numeric types. The numeric types are the integral types and the floating-point types.

The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit, and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing Unicode characters (§2.1).

The floating-point types are float and double, which are conceptually associated with the 32-bit single-precision and 64-bit double-precision IEEE 754 values and operations as specified in IEEE Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985 (IEEE, New York).

The boolean type has the truth values true and false.


2.4.2 Operators on Integral Values
The Java programming language provides a number of operators that act on integral values, including numerical comparison, arithmetic operators, increment and decrement, bitwise logical and shift operators, and numeric cast (§2.6.9).
Operands of certain unary and binary operators are subject to numeric promotion (§2.6.10).

The built-in integer operators do not indicate (positive or negative) overflow in any way; they wrap around on overflow. The only integer operators that can throw an exception are the integer divide and integer remainder operators, which can throw an ArithmeticException if the right-hand operand is zero.

Any value of any integral type may be cast to or from any numeric type. There are no casts between integral types and the type boolean.


2.4.3 Floating-Point Types, Value Sets, and Values
The IEEE 754 standard includes not only positive and negative sign-magnitude numbers, but also positive and negative zeros, positive and negative infinities, and a special Not-a-Number value (hereafter abbreviated as "NaN"). The NaN value is used to represent the result of certain invalid operations such as dividing zero by zero.
Every implementation of the Java programming language is required to support two standard sets of floating-point values, called the float value set and the double value set. In addition, an implementation of the Java programming language may support either or both of two extended-exponent floating-point value sets, called the float-extended-exponent value set and the double-extended-exponent value set. These extended-exponent value sets may, under certain circumstances, be used instead of the standard value sets to represent the values of expressions of type float or double.

The finite nonzero values of any floating-point value set can all be expressed in the form s · m· 2(e -N + 1), where s is +1 or -1, m is a positive integer less than 2N, and e is an integer between Emin = - (2K - 1-2) and Emax = 2K - 1-1, inclusive, and where N and K are parameters that depend on the value set. Some values can be represented in this form in more than one way; for example, supposing that a value v in a value set might be represented in this form using certain values for s, m, and e, then if it happened that m was even and e was less than 2K -1, one could halve m and increase e by 1 to produce a second representation for the same value v. A representation in this form is called normalized if m 2N -1; otherwise the representation is said to be denormalized. If a value in a value set cannot be represented in such a way that m 2N -1, then the value is said to be a denormalized value, because it has no normalized representation.

The constraints on the parameters N and K (and on the derived parameters Emin and Emax) for the two required and two optional floating-point value sets are summarized in Table 2.1.

Parameter float float-extended-exponent double double-extended-exponent
N 24 24 53 53
K 8 11 11 15
Emax +127 +1023 +1023 +16383
Emin -126 -1022 -1022 -16382





Where one or both extended-exponent value sets are supported by an implementation, then for each supported extended-exponent value set there is a specific implementation-dependent constant K, whose value is constrained by Table 2.1; this value K in turn dictates the values for Emin and Emax.

Each of the four value sets includes not only the finite nonzero values that are ascribed to it above, but also the five values positive zero, negative zero, positive infinity, negative infinity, and NaN.

Note that the constraints in Table 2.1 are designed so that every element of the float value set is necessarily also an element of the float-extended-exponent value set, the double value set, and the double-extended-exponent value set. Likewise, each element of the double value set is necessarily also an element of the double-extended-exponent value set. Each extended-exponent value set has a larger range of exponent values than the corresponding standard value set, but does not have more precision.

The elements of the float value set are exactly the values that can be represented using the single floating-point format defined in the IEEE 754 standard, except that there is only one NaN value (IEEE 754 specifies 224 - 2 distinct NaN values). The elements of the double value set are exactly the values that can be represented using the double floating-point format defined in the IEEE 754 standard, except that there is only one NaN value (IEEE 754 specifies 253 - 2 distinct NaN values). Note, however, that the elements of the float-extended-exponent and double-extended-exponent value sets defined here do not correspond to the values that can be represented using IEEE 754 single extended and double extended formats, respectively.

The float, float-extended-exponent, double, and double-extended-exponent value sets are not types. It is always correct for an implementation of the Java programming language to use an element of the float value set to represent a value of type float; however, it may be permissible in certain regions of code for an implementation to use an element of the float-extended-exponent value set instead. Similarly, it is always correct for an implementation to use an element of the double value set to represent a value of type double; however, it may be permissible in certain regions of code for an implementation to use an element of the double-extended-exponent value set instead.

Except for NaN, floating-point values are ordered; arranged from smallest to largest, they are negative infinity, negative finite nonzero values, positive and negative zero, positive finite nonzero values, and positive infinity.

On comparison, positive zero and negative zero are equal; thus the result of the expression 0.0 == -0.0 is true and the result of 0.0 > -0.0 is false. But other operations can distinguish positive and negative zero; for example, 1.0/0.0 has the value positive infinity, while the value of 1.0/-0.0 is negative infinity.

NaN is unordered, so the numerical comparison operators <, <=, >, and >= return false if either or both operands are NaN. The equality operator == returns false if either operand is NaN, and the inequality operator != returns true if either operand is NaN. In particular, x != x is true if and only if x is NaN, and (x=y) will be false if x or y is NaN.

Any value of a floating-point type may be cast to or from any numeric type. There are no casts between floating-point types and the type boolean.


2.4.4 Operators on Floating-Point Values
The Java programming language provides a number of operators that act on floating-point values, including numerical comparison, arithmetic operators, increment and decrement, and numeric cast (§2.6.9).
If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other operand is integral. Operands of certain unary and binary operators are subject to numeric promotion (§2.6.10).

The values returned by operators on floating-point numbers are those specified by IEEE 754. In particular, the Java programming language requires support of IEEE 754 denormalized floating-point numbers and gradual underflow, which make it easier to prove desirable properties of particular numerical algorithms.

The Java programming language requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision. Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one having zero as its least significant bit is chosen. This is the IEEE 754 standard's default rounding mode known as round to nearest mode.

When converting a floating-point value to an integer, round towards zero mode is used (§2.6.3). Round towards zero mode acts as though the number were truncated, discarding the significand bits. Round towards zero mode chooses as its result the format's value closest to and no greater in magnitude than the infinitely precise result.

The floating-point operators of the Java programming language produce no exceptions (§2.16). An operation that overflows produces a signed infinity; an operation that underflows produces a denormalized value or a signed zero; and an operation that has no mathematically definite result produces NaN. All numeric operations (except for numeric comparison) with NaN as an operand produce NaN as a result.

Any value of any floating-point type may be cast (§2.6.9) to or from any numeric type. There are no casts between floating-point types and the type boolean.


2.4.5 Operators on boolean Values
The boolean operators include relational operators and logical operators. Only boolean expressions can be used in control flow statements and as the first operand of the conditional operator ?:. An integral value x can be converted to a value of type boolean, following the C language convention that any nonzero value is true, by the expression x!=0. An object reference obj can be converted to a value of type boolean, following the C language convention that any reference other than null is true, by the expression obj!=null.
There are no casts between the type boolean and any other type.


2.4.6 Reference Types, Objects, and Reference Values
There are three kinds of reference types: the class types (§2.8), the interface types (§2.13), and the array types (§2.15). An object is a dynamically created class instance or an array. The reference values (often just references) are pointers to these objects and a special null reference, which refers to no object.
A class instance is explicitly created by a class instance creation expression, or by invoking the newInstance method of class Class. An array is explicitly created by an array creation expression. An object is created in the heap and is garbage-collected after there are no more references to it. Objects cannot be reclaimed or freed by explicit language directives.

There may be many references to the same object. Most objects have state, stored in the fields of objects that are instances of classes or in the variables that are the components of an array object. If two variables contain references to the same object, the state of the object can be modified using one variable's reference to the object, and then the altered state can be observed through the other variable's reference.

Each object has an associated lock (§2.19, §8.13) that is used by synchronized methods and by the synchronized statement to provide control over concurrent access to state by multiple threads (§2.19, §8.12).

Reference types form a hierarchy. Each class type is a subclass of another class type, except for the class Object (§2.4.7), which is the superclass (§2.8.3) of all other class and array types. All objects, including arrays, support the methods of class Object. String literals (§2.3) are references to instances of class String (§2.4.8).


2.4.7 The Class Object
The standard class Object is the superclass (§2.8.3) of all other classes. A variable of type Object can hold a reference to any object, whether it is an instance of a class or an array. All class and array types inherit the methods of class Object.

2.4.8 The Class String
Instances of class String represent sequences of Unicode characters (§2.1). A String object has a constant, unchanging value. String literals (§2.3) are references to instances of class String.

2.4.9 Operators on Objects
The operators on objects include field access, method invocation, cast, string concatenation, comparison for equality, instanceof, and the conditional operator ?:.


--------------------------------------------------------------------------------

2.5 Variables
A variable is a storage location. It has an associated type, sometimes called its compile-time type, that is either a primitive type (§2.4.1) or a reference type (§2.4.6). A variable always contains a value that is assignment compatible (§2.6.7) with its type. A variable of a primitive type always holds a value of that exact primitive type. A variable of reference type can hold either a null reference or a reference to any object whose class is assignment compatible (§2.6.7) with the type of the variable.
Compatibility of the value of a variable with its type is guaranteed by the design of the language because default values (§2.5.1) are compatible and all assignments to a variable are checked, at compile time, for assignment compatibility. There are seven kinds of variables:


A class variable is a field of a class type declared using the keyword static (§2.9.1) within a class declaration, or with or without the keyword static in an interface declaration. Class variables are created when the class or interface is loaded (§2.17.2) and are initialized on creation to default values (§2.5.1). The class variable effectively ceases to exist when its class or interface is unloaded (§2.17.8).

An instance variable is a field declared within a class declaration without using the keyword static (§2.9.1). If a class T has a field a that is an instance variable, then a new instance variable a is created and initialized to a default value (§2.5.1) as part of each newly created object of class T or of any class that is a subclass of T. The instance variable effectively ceases to exist when the object of which it is a field is no longer referenced, after any necessary finalization of the object (§2.17.7) has been completed.

Array components are unnamed variables that are created and initialized to default values (§2.5.1) whenever a new object that is an array is created (§2.17.6). The array components effectively cease to exist when the array is no longer referenced.

Method parameters name argument values passed to a method. For every parameter declared in a method declaration, a new parameter variable is created each time that method is invoked. The new variable is initialized with the corresponding argument value from the method invocation. The method parameter effectively ceases to exist when the execution of the body of the method is complete.

Constructor parameters name argument values passed to a constructor. For every parameter declared in a constructor declaration, a new parameter variable is created each time a class instance creation expression or explicit constructor invocation is evaluated. The new variable is initialized with the corresponding argument value from the creation expression or constructor invocation. The constructor parameter effectively ceases to exist when the execution of the body of the constructor is complete.

An exception-handler parameter variable is created each time an exception is caught by a catch clause of a try statement (§2.16.2). The new variable is initialized with the actual object associated with the exception (§2.16.3). The exception-handler parameter effectively ceases to exist when execution of the block associated with the catch clause (§2.16.2) is complete.

Local variables are declared by local variable declaration statements. Whenever the flow of control enters a block or a for statement, a new variable is created for each local variable declared in a local variable declaration statement immediately contained within that block or for statement. The local variable is not initialized, however, until the local variable declaration statement that declares it is executed. The local variable effectively ceases to exist when the execution of the block or for statement is complete.
2.5.1 Initial Values of Variables
Every variable in a program must have a value before it is used:

Each class variable, instance variable, and array component is initialized with a default value when it is created:

For type byte, the default value is zero, that is, the value of (byte)0.

For type short, the default value is zero, that is, the value of (short)0.

For type int, the default value is zero, that is, 0.

For type long, the default value is zero, that is, 0L.

For type float, the default value is positive zero, that is, 0.0f.

For type double, the default value is positive zero, that is, 0.0.

For type char, the default value is the null character, that is, '\u0000'.

For type boolean, the default value is false.

For all reference types (§2.4.6), the default value is null (§2.3).

Each method parameter (§2.5) is initialized to the corresponding argument value provided by the invoker of the method.

Each constructor parameter (§2.5) is initialized to the corresponding argument value provided by an object creation expression or explicit constructor invocation.

An exception-handler parameter (§2.16.2) is initialized to the thrown object representing the exception (§2.16.3).

A local variable must be explicitly given a value, by either initialization or assignment, before it is used.
2.5.2 Variables Have Types, Objects Have Classes
Every object belongs to some particular class. This is the class that was mentioned in the class instance creation expression that produced the object, or the class whose class object was used to invoke the newInstance method to produce the object. This class is called the class of the object. An object is said to be an instance of its class and of all superclasses of its class. Sometimes the class of an object is called its "runtime type," but "class" is the more accurate term.
(Sometimes a variable or expression is said to have a "runtime type," but that is an abuse of terminology; it refers to the class of the object referred to by the value of the variable or expression at run time, assuming that the value is not null. Properly speaking, type is a compile-time notion. A variable or expression has a type; an object or array has no type, but belongs to a class.)

The type of a variable is always declared, and the type of an expression can be deduced at compile time. The type limits the possible values that the variable can hold or the expression can produce at run time. If a runtime value is a reference that is not null, it refers to an object or array that has a class (not a type), and that class will necessarily be compatible with the compile-time type.

Even though a variable or expression may have a compile-time type that is an interface type, there are no instances of interfaces (§2.13). A variable or expression whose type is an interface type can reference any object whose class implements that interface.

Every array also has a class. The classes for arrays have strange names that are not valid identifiers; for example, the class for an array of int components has the name "[I".



--------------------------------------------------------------------------------

2.6 Conversions and Promotions
A conversion from type S to type T allows an expression of type S to be treated at compile time as if it were of type T instead. In some cases this will require a corresponding action at run time to check the validity of the conversion or to translate the runtime value of the expression into a form appropriate for the new type T.
Numeric promotions are conversions that change an operand of a numeric operation to a wider type, or both operands of a numeric operation to a common type, so that an operation can be performed.

In the Java programming language, there are six broad kinds of conversions:


Identity conversions

Widening primitive conversions

Narrowing primitive conversions

Widening reference conversions

Narrowing reference conversions

String conversions
There are five conversion contexts in which conversion expressions can occur. Each context allows conversions in some of the above-named categories but not others. The conversion contexts are:

Assignment conversion (§2.6.7), which converts the type of an expression to the type of a specified variable. The conversions permitted for assignment are limited in such a way that assignment conversion never causes an exception.

Method invocation conversion (§2.6.8), which is applied to each argument in a method or constructor invocation, and, except in one case, performs the same conversions that assignment conversion does. Method invocation conversion never causes an exception.

Casting conversion (§2.6.9), which converts the type of an expression to a type explicitly specified by a cast operator. It is more inclusive than assignment or method invocation conversion, allowing any specific conversion other than a string conversion, but certain casts to a reference type may cause an exception at run time.

String conversion, which allows any type to be converted to type String (§2.4.8).

Numeric promotion, which brings the operands of a numeric operator to a common type so that an operation can be performed.
String conversion only applies to operands of the binary + and += operators when one of the arguments is a String; it will not be covered further.

2.6.1 Identity Conversions
A conversion from a type to that same type is permitted for any type.

2.6.2 Widening Primitive Conversions
The following conversions on primitive types are called the widening primitive conversions :

byte to short, int, long, float, or double

short to int, long, float, or double

char to int, long, float, or double

int to long, float, or double

long to float or double

float to double
Widening conversions do not lose information about the sign or order of magnitude of a numeric value. Conversions widening from an integral type to another integral type do not lose any information at all; the numeric value is preserved exactly. Conversions widening from float to double in strictfp expressions (§2.18) also preserve the numeric value exactly; however, such conversions that are not strictfp may lose information about the overall magnitude of the converted value.
Conversion of an int or a long value to float, or of a long value to double, may lose precision, that is, the result may lose some of the least significant bits of the value; the resulting floating-point value is a correctly rounded version of the integer value, using IEEE 754 round to nearest mode (§2.4.4).

According to this rule, a widening conversion of a signed integer value to an integral type simply sign-extends the two's-complement representation of the integer value to fill the wider format. A widening conversion of a value of type char to an integral type zero-extends the representation of the character value to fill the wider format.

Despite the fact that loss of precision may occur, widening conversions among primitive types never result in a runtime exception (§2.16).


2.6.3 Narrowing Primitive Conversions
The following conversions on primitive types are called narrowing primitive conversions :

byte to char

short to byte or char

char to byte or short

int to byte, short, or char

long to byte, short, char, or int

float to byte, short, char, int, or long

double to byte, short, char, int, long, or float
Narrowing conversions may lose information about the sign or order of magnitude, or both, of a numeric value (for example, narrowing an int value 32763 to type byte produces the value -5). Narrowing conversions may also lose precision.
A narrowing conversion of a signed integer to an integral type simply discards all but the n lowest-order bits, where n is the number of bits used to represent the type. This may cause the resulting value to have a different sign from the input value.

A narrowing conversion of a character to an integral type likewise simply discards all but the n lowest bits, where n is the number of bits used to represent the type. This may cause the resulting value to be a negative number, even though characters represent 16-bit unsigned integer values.

In a narrowing conversion of a floating-point number to an integral type, if the floating-point number is NaN, the result of the conversion is 0 of the appropriate type. If the floating-point number is too large to be represented by the integral type or is positive infinity, the result is the largest representable value of the integral type. If the floating-point number is too small to be represented or is negative infinity, the result is the smallest representable value of the integral type. Otherwise, the result is the floating-point number rounded towards zero to an integer value using IEEE 754 round towards zero mode (§2.4.4)

A narrowing conversion from double to float behaves in accordance with IEEE 754. The result is correctly rounded using IEEE 754 round to nearest mode (§2.4.4). A value too small to be represented as a float is converted to a positive or negative zero; a value too large to be represented as a float is converted to a positive or negative infinity. A double NaN is always converted to a float NaN.

Despite the fact that overflow, underflow, or loss of precision may occur, narrowing conversions among primitive types never result in a runtime exception.


2.6.4 Widening Reference Conversions
Widening reference conversions never require a special action at run time and therefore never throw an exception at run time. Because they do not affect the Java virtual machine, they will not be considered further.

2.6.5 Narrowing Reference Conversions
The following permitted conversions are called the narrowing reference conversions:

From any class type S to any class type T, provided that S is a superclass of T. (An important special case is that there is a narrowing conversion from the class type Object to any other class type.)

From any class type S to any interface type K, provided that S is not final and does not implement K. (An important special case is that there is a narrowing conversion from the class type Object to any interface type.)

From type Object to any array type.

From type Object to any interface type.

From any interface type J to any class type T that is not final.

From any interface type J to any class type T that is final, provided that T implements J.

From any interface type J to any interface type K, provided that J is not a subinterface of K and there is no method name m such that J and K both declare a method named m with the same signature but different return types.

From any array type SC[] to any array type TC[], provided that SC and TC are reference types and there is a permitted narrowing conversion from SC to TC.
Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. If it is not, the Java virtual machine throws a ClassCastException.

2.6.6 Value Set Conversion
Value set conversion is the process of mapping a floating-point value from one value set (§2.4.3) to another without changing its type.
For each operation in an expression that is not FP-strict (§2.18), value set conversion allows an implementation of the Java programming language to choose between two options:


If the value is an element of the float-extended-exponent value set, then the implementation may map the value to the nearest element of the float value set. This conversion may result in overflow (in which case the value is replaced by an infinity of the same sign) or underflow (in which case the value may lose precision because it is replaced by a denormalized number or zero of the same sign).

If the value is an element of the double-extended-exponent value set, then the implementation may map the value to the nearest element of the double value set. This conversion may result in overflow (in which case the value is replaced by an infinity of the same sign) or underflow (in which case the value may lose precision because it is replaced by a denormalized number or zero of the same sign).
Within an FP-strict expression, value set conversion does not provide any choices; every implementation must behave in the same way:

If the value is of type float and is not an element of the float value set, then the implementation must map the value to the nearest element of the float value set. This conversion may result in overflow or underflow.

If the value is of type double and is not an element of the double value set, then the implementation must map the value to the nearest element of the double value set. This conversion may result in overflow or underflow.
Within an FP-strict expression, mapping values from the float-extended-exponent value set or double-extended-exponent value set is necessary only when a method is called whose declaration is not FP-strict and the implementation has chosen to represent the result of the method call as an element of an extended-exponent value set.
Whether in FP-strict code or code that is not FP-strict, value set conversion always leaves unchanged any value whose type is neither float nor double.


2.6.7 Assignment Conversion
Assignment conversion occurs when the value of an expression is assigned to a variable: the type of the expression must be converted to the type of the variable. Assignment contexts allow the use of an identity conversion (§2.6.1), a widening primitive conversion (§2.6.2), or a widening reference conversion (§2.6.4). In addition, a narrowing primitive conversion (§2.6.3) may be used if all of the following conditions are satisfied:

The expression is a constant expression of type int.

The type of the variable is byte, short, or char.

The value of the expression is representable in the type of the variable.
If the type of the expression can be converted to the type of a variable by assignment conversion, we say the expression (or its value) is assignable to the variable or, equivalently, that the type of the expression is assignment compatible with the type of the variable.
If the type of the variable is float or double, then value set conversion (§2.6.6) is applied after the type conversion:


If the value is of type float and is an element of the float-extended-exponent value set, then the implementation must map the value to the nearest element of the float value set. This conversion may result in overflow or underflow.

If the value is of type double and is an element of the double-extended-exponent value set, then the implementation must map the value to the nearest element of the double value set. This conversion may result in overflow or underflow.
An assignment conversion never causes an exception. A value of primitive type must not be assigned to a variable of reference type. A value of reference type must not be assigned to a variable of primitive type. A value of type boolean can be assigned only to a variable of type boolean. A value of the null type may be assigned to a variable of any reference type.
Assignment of a value of compile-time reference type S (source) to a variable of compile-time reference type T (target) is permitted:


If S is a class type:

If T is a class type, then S must be the same class as T, or S must be a subclass of T.

If T is an interface type, then S must implement interface T.

If S is an interface type:

If T is a class type, then T must be Object.

If T is an interface type, then T must be the same interface as S, or T must be a superinterface of S.

If S is an array type SC[], that is, an array of components of type SC:

If T is a class type, then T must be Object.

If T is an interface type, then T must be either Cloneable or java.io.Serializable.

If T is an array type TC[], that is, an array of components of type TC, then either

TC and SC must be the same primitive type, or

TC and SC are both reference types and type SC is assignable to TC.
2.6.8 Method Invocation Conversion
Method invocation conversion is applied to each argument value in a method or constructor invocation: the type of the argument expression must be converted to the type of the corresponding parameter. Method invocation contexts allow the use of an identity conversion (§2.6.1), a widening primitive conversion (§2.6.2), or a widening reference conversion (§2.6.4). Method invocation conversions specifically do not include the implicit narrowing of integer constants that is part of assignment conversion (§2.6.7).
If the type of an argument expression is either float or double, then value set conversion (§2.6.6) is applied after the type conversion:


If an argument value of type float is an element of the float-extended-exponent value set, then the implementation must map the value to the nearest element of the float value set. This conversion may result in overflow or underflow.

If an argument value of type double is an element of the double-extended-exponent value set, then the implementation must map the value to the nearest element of the double value set. This conversion may result in overflow or underflow.
2.6.9 Casting Conversion
Casting conversions are more powerful than assignment or method invocation conversions applied to the operand of a cast operator: the type of the operand expression must be converted to the type explicitly named by the cast operator. Casting contexts allow the use of an identity conversion (§2.6.1), a widening primitive conversion (§2.6.2), a narrowing primitive conversion (§2.6.3), a widening reference conversion (§2.6.4), or a narrowing reference conversion (§2.6.5). Thus, casting conversions are more inclusive than assignment or method invocation conversions: a cast can do any permitted conversion other than a string conversion.
Value set conversion (§2.6.6) is applied after the type conversion.

Casting can convert a value of any numeric type to any other numeric type. A value of type boolean cannot be cast to another type. A value of reference type cannot be cast to a value of primitive type.

Some casts can be proven incorrect at compile time and result in a compile-time error. Otherwise, either the cast can be proven correct at compile time, or a runtime validity check is required. (See The JavaTM Language Specification for details.) If the value at run time is a null reference, then the cast is allowed. If the check at run time fails, a ClassCastException is thrown.


2.6.10 Numeric Promotion
Numeric promotion is applied to the operands of an arithmetic operator. Numeric promotion contexts allow the use of an identity conversion (§2.6.1) or a widening primitive conversion (§2.6.2).
Numeric promotions are used to convert the operands of a numeric operator to a common type where an operation can be performed. The two kinds of numeric promotion are unary numeric promotion and binary numeric promotion. The analogous conversions in C are called "the usual unary conversions" and "the usual binary conversions." Numeric promotion is not a general feature of the Java programming language, but rather a property of specific built-in operators.

An operator that applies unary numeric promotion to a single operand of numeric type converts an operand of type byte, short, or char to int by a widening primitive conversion, and otherwise leaves the operand alone. Value set conversion (§2.6.6) is then applied. The operands of the shift operators are promoted independently using unary numeric promotions.

When an operator applies binary numeric promotion to a pair of numeric operands, the following rules apply, in order, using widening primitive conversion to convert operands as necessary:


If either operand is of type double, the other is converted to double.

Otherwise, if either operand is of type float, the other is converted to float.

Otherwise, if either operand is of type long, the other is converted to long.

Otherwise, both operands are converted to type int.
After type conversion, if any, value set conversion is applied to each operand.


--------------------------------------------------------------------------------

2.7 Names and Packages
Names are used to refer to entities declared in a program. A declared entity is a package, type, member (field or method) of a type, parameter, or local variable. Programs are organized sets of packages.

2.7.1 Simple Names and Qualified Names
A simple name is a single identifier (§2.2). Qualified names (§2.7.4) provide access to members of packages and reference types. A qualified name consists of a name, a "." token, and an identifier.
Not all identifiers are part of a name. Identifiers are also used in declarations, where the identifier determines the name by which an entity will be known, in field access expressions and method invocation expressions, and in statement labels and break and continue statements that refer to statement labels.


2.7.2 Packages
A package consists of a number of compilation units and has a hierarchical name. Packages are independently developed, and each package has its own set of names, which helps to prevent name conflicts. Each Java virtual machine implementation determines how packages, compilation units, and subpackages are created and stored; which top-level package names are in scope in a particular compilation; and which packages are accessible. Packages may be stored in a local file system, in a distributed file system, or in some form of database.
A package name component or class name might contain a character that cannot legally appear in a host file system's ordinary directory or file name: for instance, a Unicode character on a system that allows only ASCII characters in file names.

A Java virtual machine implementation must support at least one unnamed package; it may support more than one but is not required to do so. Which compilation units are in each unnamed package is determined by the host system. Unnamed packages are provided principally for convenience when developing small or temporary applications or when just beginning development.

An import declaration allows a type declared in another package to be known by a simple name rather than by the fully qualified name (§2.7.5) of the type. An import declaration affects only the type declarations of a single compilation unit. A compilation unit automatically imports each of the public type names declared in the predefined package java.lang.


2.7.3 Members
Packages and reference types have members. The members of a package (§2.7.2) are subpackages and all the class (§2.8) and interface (§2.13) types declared in all the compilation units of the package. The members of a reference type are fields (§2.9), methods (§2.10), and nested classes and interfaces.

2.7.3.1 The Members of a Package
In general, the subpackages of a package are determined by the host system. However, the standard package java always has the subpackages lang, util, io, and net. No two distinct members of the same package may have the same simple name (§2.7.1), but members of different packages may have the same simple name.

2.7.3.2 The Members of a Class Type
The members of a class type (§2.8) are fields (§2.9), methods (§2.10), and nested classes and interfaces. These include members inherited from its direct superclass (§2.8.3), if it has one, members inherited from any direct superinterfaces (§2.13.2), and any members declared in the body of the class. There is no restriction against a field and a method of a class type having the same simple name.
A class type may have two or more methods with the same simple name if they have different numbers of parameters or different parameter types in at least one parameter position. Such a method member name is said to be overloaded. A class type may contain a declaration for a method with the same name and the same signature as a method that would otherwise be inherited from a superclass or superinterface. In this case, the method of the superclass or superinterface is not inherited. If the method not inherited is abstract, the new declaration is said to implement the method; if it is not abstract, the new declaration is said to override it.


2.7.3.3 The Members of an Interface Type
The members of an interface type (§2.13) are fields, methods, and nested classes and interfaces. The members of an interface are the members inherited from any direct superinterfaces (§2.13.2) and members declared in the body of the interface.

2.7.3.4 The Members of an Array Type
The members of an array type (§2.15) are the members inherited from its superclass, the class Object (§2.4.7), and the field length, which is a constant (final) field of every array.

2.7.4 Qualified Names and Access Control
Qualified names (§2.7.1) are a means of access to members of packages and reference types; related means of access include field access expressions and method invocation expressions. All three are syntactically similar in that a "." token appears, preceded by some indication of a package, type, or expression having a type and followed by an identifier that names a member of the package or type. These are collectively known as constructs for qualified access.
The Java programming language provides mechanisms for limiting qualified access, to prevent users of a package or class from depending on unnecessary details of the implementation of that package or class. Access control also applies to constructors.

Whether a package is accessible is determined by the host system.

A class or interface may be declared public, in which case it may be accessed, using a qualified name, by any class or interface that can access the package in which it is declared. A class or interface that is not declared public may be accessed from, and only from, anywhere in the package in which it is declared.

Every field or method of an interface must be public. Every member of a public interface is implicitly public, whether or not the keyword public appears in its declaration. It follows that a member of an interface is accessible if and only if the interface itself is accessible.

A field, method, or constructor of a class may be declared using at most one of the public, private, or protected keywords. A public member may be accessed by any class or interface. A private member may be accessed only from within the class that contains its declaration. A member that is not declared public, protected, or private is said to have default access and may be accessed from, and only from, anywhere in the package in which it is declared.

A protected member of an object may be accessed only by code responsible for the implementation of that object. To be precise, a protected member may be accessed from anywhere in the package in which it is declared and, in addition, it may be accessed from within any declaration of a subclass of the class type that contains its declaration, provided that certain restrictions are obeyed.


2.7.5 Fully Qualified Names
Every package, class, interface, array type, and primitive type has a fully qualified name. It follows that every type except the null type has a fully qualified name.

The fully qualified name of a primitive type is the keyword for that primitive type, namely, boolean, char, byte, short, int, long, float, or double.

The fully qualified name of a named package that is not a subpackage of a named package is its simple name.

The fully qualified name of a named package that is a subpackage of another named package consists of the fully qualified name of the containing package followed by "." followed by the simple (member) name of the subpackage.

The fully qualified name of a class or interface that is declared in an unnamed package is the simple name of the class or interface.

The fully qualified name of a class or interface that is declared in a named package consists of the fully qualified name of the package followed by "." followed by the simple name of the class or interface.

The fully qualified name of an array type consists of the fully qualified name of the component type of the array type followed by "[]".

--------------------------------------------------------------------------------
Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
↑返回目录
前一篇: java虚拟机详述-第二章(二)
后一篇: Java常见问题集锦-from sun.com