thinking in Java 笔记 6

来源:互联网 发布:怎么查网络是否到期 编辑:程序博客网 时间:2024/05/21 09:16

p.170   Initializing the base class

//: reusing/Cartoon.java

// Constructor calls during inheritance.
import static net.mindview.util.Print.*;
class Art {
Art() { print("Art constructor"); }
}
class Drawing extends Art {
Drawing() { print("Drawing constructor"); }
}
public class Cartoon extends Drawing {
public Cartoon() { print("Cartoon constructor"); }
public static void main(String[] args) {
Cartoon x = new Cartoon();
}
} /* Output:
Art constructor
Drawing constructor
Cartoon constructor
*///:~
You can see that the construction happens from the base “outward,” so the base class is
initialized before the derived-class constructors can access it. Even if you don’t create a
constructor for Cartoon( ), the compiler will synthesize a default constructor for you that

calls the base class constructor.


p.200 Choosing composition vs. inheritance

 The is-a relationship is expressed with
inheritance, and the has-a relationship is expressed with composition.


p.180 protect

It says “This is private as far as the class
user is concerned, but available to anyone who inherits from this class or anyone else in the
same package.” (In Java, protected also provides package access.)


p.183 final data

A field that is both static and final has only one piece of storage that cannot be changed.
When final is used with object references rather than primitives, the meaning can be
confusing. With a primitive, final makes the value a constant, but with an object reference,
final makes the reference a constant. Once the reference is initialized to an object, it can
never be changed to point to another object. However, the object itself can be modified; Java
does not provide a way to make any arbitrary object a constant. (You can, however, write
your class so that objects have the effect of being constant.) This restriction includes arrays,
which are also objects.
Here’s an example that demonstrates final fields. Note that by convention, fields that are
both static and final (that is, compile-time constants) are capitalized and use underscores
to separate words.
//: reusing/FinalData.java
// The effect of final on fields.
import java.util.*;
import static net.mindview.util.Print.*;
class Value {
int i; // Package access
public Value(int i) { this.i = i; }
}
public class FinalData {
private static Random rand = new Random(47);
private String id;
public FinalData(String id) { this.id = id; }
// Can be compile-time constants:
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
// Typical public constant:
public static final int VALUE_THREE = 39;
// Cannot be compile-time constants:
private final int i4 = rand.nextInt(20);
static final int INT_5 = rand.nextInt(20);
private Value v1 = new Value(11);
private final Value v2 = new Value(22);
private static final Value VAL_3 = new Value(33);
// Arrays:
private final int[] a = { 1, 2, 3, 4, 5, 6 };
public String toString() {
return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
}
Reusing Classes 183 
public static void main(String[] args) {
FinalData fd1 = new FinalData("fd1");
//! fd1.valueOne++; // Error: can’t change value
fd1.v2.i++; // Object isn’t constant!
fd1.v1 = new Value(9); // OK -- not final
for(int i = 0; i < fd1.a.length; i++)
fd1.a[i]++; // Object isn’t constant!
//! fd1.v2 = new Value(0); // Error: Can’t
//! fd1.VAL_3 = new Value(1); // change reference
//! fd1.a = new int[3];
print(fd1);
print("Creating new FinalData");
FinalData fd2 = new FinalData("fd2");
print(fd1);
print(fd2);
}
} /* Output:
fd1: i4 = 15, INT_5 = 18
Creating new FinalData
fd1: i4 = 15, INT_5 = 18
fd2: i4 = 13, INT_5 = 18
*///:~
Since valueOne and VALUE_TWO are final primitives with compile-time values, they
can both be used as compile-time constants and are not different in any important way.
VALUE_THREE is the more typical way you’ll see such constants defined: public so
they’re usable outside the package, static to emphasize that there’s only one, and final to
say that it’s a constant. Note that final static primitives with constant initial values (that is,
compile-time constants) are named with all capitals by convention, with words separated by
underscores. (This is just like C constants, which is where the convention originated.)
Just because something is final doesn’t mean that its value is known at compile time. This is
demonstrated by initializing i4 and INT_5 at run time using randomly generated numbers.
This portion of the example also shows the difference between making a final value static or
non-static. This difference shows up only when the values are initialized at run time, since
the compile-time values are treated the same by the compiler. (And presumably optimized
out of existence.) The difference is shown when you run the program. Note that the values of
i4 for fd1 and fd2 are unique, but the value for INT_5 is not changed by creating the second
FinalData object. That’s because it’s static and is initialized once upon loading and not
each time a new object is created.
The variables v1 through VAL_3 demonstrate the meaning of a final reference. As you can
see in main( ), just because v2 is final doesn’t mean that you can’t change its value.
Because it’s a reference, final means that you cannot rebind v2 to a new object. You can also
see that the same meaning holds true for an array, which is just another kind of reference.
(There is no way that I know of to make the array references themselves final.) Making
references final seems less useful than making primitives final.


final arguments

final methods:explicitly prevent overriding 不允许子类改变父类的一些行为


0 0