📄 8.doc.html
字号:
the class variable totalMoves can be used only within the class <code>Point</code>; it is not
inherited by the subclass <code>Point3d</code>. A compile-time error occurs at the point where
method <code>move</code> of class <code>Point3d</code> tries to increment totalMoves.
<p><a name="23530"></a>
<h4>8.2.1.4 Accessing Members of Inaccessible Classes</h4>
<a name="23515"></a>
Even though a class might not be declared <code>public</code>, instances of the class might be
available at run time to code outside the package in which it is declared if it has a
<code>public</code> superclass or superinterface. An instance of the class can be assigned to a
variable of such a <code>public</code> type. An invocation of a <code>public</code> method of the object
referred to by such a variable may invoke a method of the class if it implements or
overrides a method of the <code>public</code> superclass or superinterface. (In this situation,
the method is necessarily declared <code>public</code>, even though it is declared in a class
that is not <code>public</code>.)
<p><a name="23519"></a>
Consider the compilation unit:<p>
<pre><br><a name="36842"></a>package points;
<br></pre><pre><a name="36843"></a>
public class Point {
<a name="36844"></a> public int x, y;
<a name="36847"></a> public void move(int dx, int dy) {
<a name="36848"></a> x += dx; y += dy;
<a name="36849"></a> }
<a name="36850"></a>}
</pre><a name="36865"></a>
and another compilation unit of another package:
<p><pre><br><a name="23520"></a>package morePoints;
<br></pre><pre><a name="23521"></a>
class Point3d extends points.Point {
<a name="23522"></a> public int z;
<a name="36870"></a> public void move(int dx, int dy, int dz) {
<a name="36871"></a> super.move(dx, dy); z += dz;
<a name="36872"></a> }
<a name="23523"></a>}
<br><a name="23524"></a>
public class OnePoint {
<a name="23525"></a> static points.Point getOne() { return new Point3d(); }
<a name="23526"></a>}
</pre><a name="23527"></a>
An invocation <code>morePoints.OnePoint.getOne()</code> in yet a third package would
return a <code>Point3d</code> that can be used as a <code>Point</code>, even though the type <code>Point3d</code> is
not available outside the package <code>morePoints</code>. The method <code>move</code> could then be
invoked for that object, which is permissible because method <code>move</code> of <code>Point3d</code> is
<code>public</code> (as it must be, for any method that overrides a <code>public</code> method must itself
be <code>public</code>, precisely so that situations such as this will work out correctly). The
fields <code>x</code> and <code>y</code> of that object could also be accessed from such a third package.
<p><a name="36884"></a>
While the field <code>z</code> of class <code>Point3d</code> is <code>public</code>, it is not possible to access this field from code outside the package <code>morePoints</code>, given only a reference to an instance of class <code>Point3d</code> in a variable <code>p</code> of type <code>Point</code>. This is because the expression <code>p.z</code> is not correct, as <code>p</code> has type <code>Point</code> and class <code>Point</code> has no field named <code>z</code>; also, the expression <code>((Point3d)p).z</code> is not correct, because the class type <code>Point3d</code> cannot be referred to outside package <code>morePoints</code>. The declaration of the field <code>z</code> as <code>public</code> is not useless, however. If there were to be, in package <code>morePoints</code>, a <code>public</code> subclass <code>Point4d</code> of the class <code>Point3d</code>:<p>
<pre><br><a name="36889"></a>package morePoints;
<br></pre><pre><a name="36890"></a>
public class Point4d extends Point3d {
<a name="36891"></a> public int w;
<a name="36892"></a> public void move(int dx, int dy, int dz, int dw) {
<a name="36893"></a> super.move(dx, dy, dz); w += dw;
<a name="36894"></a> }
<a name="36896"></a>}
<br></pre><a name="36887"></a>
then class <code>Point4d</code> would inherit the field <code>z</code>, which, being <code>public</code>, could then be
accessed by code in packages other than <code>morePoints</code>, through variables and
expressions of the <code>public</code> type <code>Point4d</code>.
<p><a name="40898"></a>
<h2>8.3 Field Declarations</h2>
<a name="40823"></a>
The variables of a class type are introduced by <i>field declarations</i>:
<p><ul><pre>
<i>FieldDeclaration:<br>
FieldModifiers</i><sub><i>opt</i></sub><code> </code><i>Type</i><code> </code><i>VariableDeclarators</i><code> ;
</code>
<i>VariableDeclarators:<br>
</i> <i>VariableDeclarator<br>
</i> <i>VariableDeclarators</i><code> , </code><i>VariableDeclarator
</i>
<i>VariableDeclarator:<br>
</i> <i>VariableDeclaratorId<br>
</i> <i>VariableDeclaratorId</i><code> = </code><i>VariableInitializer
</i>
<i>VariableDeclaratorId:<br>
</i> <i>Identifier<br>
</i> <i>VariableDeclaratorId</i><code> [ ]
</code>
<i>VariableInitializer:<br>
</i> <i>Expression<br>
</i> <i>ArrayInitializer
</i></pre></ul><a name="78087"></a>
The <i>FieldModifiers</i> are described in <a href="8.doc.html#78091">§8.3.1</a>. The <i>Identifier</i> in a <i>FieldDeclarator</i>
may be used in a name to refer to the field. The name of a field has as its scope
<a href="6.doc.html#33623">(§6.3)</a> the entire body of the class declaration in which it is declared. More than
one field may be declared in a single field declaration by using more than one
declarator; the <i>FieldModifiers</i> and <i>Type</i> apply to all the declarators in the declaration.
Variable declarations involving array types are discussed in <a href="10.doc.html#25891">§10.2</a>.
<p><a name="29989"></a>
It is a compile-time error for the body of a class declaration to contain declarations of two fields with the same name. Methods and fields may have the same name, since they are used in different contexts and are disambiguated by the different lookup procedures <a href="6.doc.html#20569">(§6.5)</a>.<p>
<a name="36999"></a>
If the class declares a field with a certain name, then the declaration of that field is said to <i>hide</i> <a href="6.doc.html#34133">(§6.3.1)</a> any and all accessible declarations of fields with the same name in the superclasses and superinterfaces of the class.<p>
<a name="38152"></a>
If a field declaration hides the declaration of another field, the two fields need not have the same type.<p>
<a name="38148"></a>
A class inherits from its direct superclass and direct superinterfaces all the fields of the superclass and superinterfaces that are both accessible to code in the class and not hidden by a declaration in the class.<p>
<a name="37087"></a>
It is possible for a class to inherit more than one field with the same name <a href="8.doc.html#40491">(§8.3.3.3)</a>. Such a situation does not in itself cause a compile-time error. However, any attempt within the body of the class to refer to any such field by its simple name will result in a compile-time error, because such a reference is ambiguous.<p>
<a name="37038"></a>
There might be several paths by which the same field declaration might be inherited from an interface. In such a situation, the field is considered to be inherited only once, and it may be referred to by its simple name without ambiguity.<p>
<a name="37037"></a>
A hidden field can be accessed by using a qualified name (if it is <code>static</code>) or by using a field access expression <a href="15.doc.html#41267">(§15.10)</a> that contains the keyword <code>super</code> or a cast to a superclass type. See <a href="15.doc.html#20860">§15.10.2</a> for discussion and an example.<p>
<a name="78091"></a>
<h3>8.3.1 Field Modifiers</h3>
<ul><pre>
<i>FieldModifiers:<br>
FieldModifier<br>
FieldModifiers</i><code> </code><i>FieldModifier
</i>
<i>FieldModifier: one of<br>
</i><code>public protected private<br>
final static transient volatile
</code></pre></ul><a name="35964"></a>
The access modifiers <code>public</code>, <code>protected</code>, and <code>private</code> are discussed in <a href="6.doc.html#33916">§6.6</a>. A
compile-time error occurs if the same modifier appears more than once in a field
declaration, or if a field declaration has more than one of the access modifiers
<code>public</code>, <code>protected</code>, and <code>private</code>. If two or more (distinct) field modifiers
appear in a field declaration, it is customary, though not required, that they appear
in the order consistent with that shown above in the production for <i>FieldModifier</i>.
<p><a name="37544"></a>
<h4>8.3.1.1 static Fields</h4>
<a name="230789"></a>
If a field is declared <code>static</code>, there exists exactly one incarnation of the field, no
matter how many instances (possibly zero) of the class may eventually be created.
A <code>static</code> field, sometimes called a <i>class variable</i>, is incarnated when the class is
initialized <a href="12.doc.html#44557">(§12.4)</a>.
<p><a name="230793"></a>
A field that is not declared <code>static</code> (sometimes called a non-<code>static</code> field) is called an <i>instance variable</i>. Whenever a new instance of a class is created, a new variable associated with that instance is created for every instance variable declared in that class or any of its superclasses.<p>
<a name="38985"></a>
The example program:<p>
<pre><a name="37567"></a>
class Point {
<a name="37568"></a> int x, y, useCount;
<a name="37569"></a> Point(int x, int y) { this.x = x; this.y = y; }
<a name="37572"></a> final static Point origin = new Point(0, 0);
<a name="37573"></a>}
<br><a name="37574"></a>
class Test {
<a name="37575"></a> public static void main(String[] args) {
<a name="37576"></a> Point p = new Point(1,1);
<a name="37577"></a> Point q = new Point(2,2);
<a name="37578"></a> p.x = 3; p.y = 3; p.useCount++; p.origin.useCount++;
<a name="37579"></a> System.out.println("(" + q.x + "," + q.y + ")");
<a name="37615"></a> System.out.println(q.useCount);
<a name="37581"></a> System.out.println(q.origin == Point.origin);
<a name="37662"></a> System.out.println(q.origin.useCount);
<a name="37582"></a> }
<a name="37583"></a>}
</pre><a name="37584"></a>
prints:
<p><pre><a name="37585"></a>
(2,2)
<a name="37618"></a>0
<a name="37587"></a>true
<a name="37667"></a>1
</pre><a name="37588"></a>
showing that changing the fields <code>x</code>, <code>y</code>, and <code>useCount</code> of <code>p</code> does not affect the fields
of <code>q</code>, because these fields are instance variables in distinct objects. In this example,
the class variable <code>origin</code> of the class <code>Point</code> is referenced both using the class
name as a qualifier, in <code>Point.origin</code>, and using variables of the class type in
field access expressions <a href="15.doc.html#41267">(§15.10)</a>, as in <code>p.origin</code> and <code>q.origin</code>. These two ways
of accessing the <code>origin</code> class variable access the same object, evidenced by the
fact that the value of the reference equality expression <a href="15.doc.html#236163">(§15.20.3)</a>:
<p><pre><a name="227823"></a><code>q.origin==Point.origin
</code></pre><a name="227825"></a>
is <code>true</code>. Further evidence is that the incrementation:
<p><pre><a name="37670"></a>p.origin.useCount++;
</pre><a name="37671"></a>
causes the value of q.origin.useCount to be <code>1</code>; this is so because <code>p.origin</code> and
<code>q.origin</code> refer to the same variable.
<p><a name="35962"></a>
<h4>8.3.1.2 final Fields</h4>
<a name="14727"></a>
A field can be declared <code>final</code>, in which case its declarator must include a variable
initializer or a compile-time error occurs. Both class and instance variables
(<code>static</code> and non-<code>static</code> fields) may be declared <code>final</code>.
<p><a name="37504"></a>
Any attempt to assign to a <code>final</code> field results in a compile-time error. Therefore, once a <code>final</code> field has been initialized, it always contains the same value. If a <code>final</code> field holds a reference to an object, then the state of the object may be changed by operations on the object, but the field will always refer to the same object. This applies also to arrays, because arrays are objects; if a <code>final</code> field holds a reference to an array, then the components of the array may be changed by operations on the array, but the field will always refer to the same array.<p>
<a name="14728"></a>
Declaring a field <code>final</code> can serve as useful documentation that its value will not change, can help to avoid programming errors, and can make it easier for a compiler to generate efficient code.<p>
<a name="37005"></a>
In the example:<p>
<pre><a name="37006"></a>
class Point {
<a name="37053"></a> int x, y;
<a name="37066"></a> int useCount;
<a name="37049"></a> Point(int x, int y) { this.x = x; this.y = y; }
<a name="37058"></a> final static Point origin = new Point(0, 0);
<a name="37056"></a>}
</pre><a name="37059"></a>
the class <code>Point</code> declares a <code>final</code> class variable <code>origin</code>. The <code>origin</code> variable
holds a reference to an object that is an instance of class <code>Point</code> whose coordinates
are (0, 0). The value of the variable <code>Point.origin</code> can never change, so it always
refers to the same <code>Point</code> object, the one created by its initializer. However, an
operation on this <code>Point</code> object might change its state-for example, modifying its
<code>useCount</code> or even, misleadingly, its <code>x</code> or <code>y</code> coordinate.
<p><a name="78119"></a>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -