<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    junhong

    Thinking in java review 2

    ?

    1.????? The only place a label is useful in Java is right before an iteration

    statement. And that means right before—it does no good to put any other

    statement between the label and the iteration. And the sole reason to put

    a label before an iteration is if you’re going to nest another iteration or a

    switch inside it. That’s because the break and continue keywords will

    normally interrupt only the current loop, but when used with a label

    they’ll interrupt the loops up to where the label exists:

    label1:

    outer-iteration {

    inner-iteration {

    //…

    break ; // 1

    //…

    continue ; // 2

    //…

    continue label1; // 3

    //…

    break label1; // 4

    }

    }

    In case 1, the break breaks out of the inner iteration and you end up in

    the outer iteration. In case 2, the continue moves back to the beginning

    of the inner iteration. But in case 3, the continue label1 breaks out of

    the inner iteration and the outer iteration, all the way back to label1.

    Then it does in fact continue the iteration, but starting at the outer

    iteration. In case 4, the break label1 also breaks all the way out to

    label1 , but it does not re-enter the iteration. It actually does break out of

    both iterations.

    ?

    2.???????

    It’s important to remember that the only reason to use labels in Java is

    when you have nested loops and you want to break or continue through

    more than one nested level

    ?3.???????

    switch( integral-selector) {

    case integral-value1 : statement; break;

    case integral-value2 : statement; break;

    case integral-value3 : statement; break;

    case integral-value4 : statement; break;

    case integral-value5 : statement; break;

    // ...

    default: statement;

    }

    Integral-selector is an expression that produces an integral value.
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    4. Suppose you’re inside a method and you’d like to get the reference to the

    current object. Since that reference is passed secretly by the compiler,

    there’s no identifier for it. However, for this purpose there’s a keyword:

    this . The this keyword—which can be used only inside a method—

    produces the reference to the object the method has been called for. You

    can treat this reference just like any other object reference

    ?4.???????
    Normally, when you say this, it is in the sense of “this object” or “the

    current object,” and by itself it produces the reference to the current

    object. In a constructor, the this keyword takes on a different meaning

    when you give it an argument list: it makes an explicit call to the

    constructor that matches that argument list Thus you have a

    straightforward way to call other constructors

    ?

    ?5.????? 垃圾回收器并不一定會回收未用的對象(因為垃圾回收器只有在內存不夠用時才啟動,所以如果未用對象已經產生了,但是內存還有很多,這時垃圾回收器就不會執行,垃圾對象就不會被回收了)。
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    When the garbage collector is ready to release the storage used for your object, it will first call finalize( ), and only on the next garbage-collection pass will it reclaim the object’s memory. So if you choose to use finalize( ), it gives you the ability to perform some important cleanup at the time of garbage collection.

    當你調用, System.gc() 時,這時虛擬機會盡最大可能去回收內存,但是它也不能保證100%的去掉用垃圾回收器去收集垃圾對象,如果調用了垃圾回收器 ,他的 finalize() 函數也會被調用,但是如果是系統運行完了以后也沒有瀕臨內存用完時,這是 garbage collector 就不會被調用來回收內存的。這樣對象也就沒有被回收。

    ?

    <!--[if !supportLists]--> 6.????? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    If you remember this, you will stay out of trouble. What it means is that if

    there is some activity that must be performed before you no longer need

    an object, you must perform that activity yourself. Java has no destructor

    or similar concept, so you must create an ordinary method to perform this

    cleanup

    <!--[if !supportLists]--> 7.????? <!--[endif]--> 一個文件可以沒有public class,如果有public class,則必須要與文件名同名

    <!--[if !supportLists]--> 8.????? <!--[endif]--> class 不能是private ,protected,但是inner class 是特例
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    chapter 6 reuse class
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 9.????? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    You can create a main( ) for each one of your classes, and it’s often recommended to code this way so that your test code is wrapped in with the class. Even if you have a lot of classes in a program, only the main( ) for the class invoked on the command line will be called. (As long as main( ) is public, it doesn’t matter whether the class that it’s part of is public.)

    <!--[if !supportLists]--> 10.? <!--[endif]--> 調用同一個class內的構造函數用this(參數),調用base class 的函數用super.函數(參數)就可以了。調用base class 的構造函數用super(parameter)
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 11.? <!--[endif]--> ?

    When you create an object of the derived class, it contains within it a subobject of the base class. This subobject is the same as if you had created an object of the base class by itself. It’s just that, from the outside, the subobject of the base class is wrapped within

    the derived-class object. baseclass 對象是包含在 subclass 的對象內的)

    ?

    <!--[if !supportLists]--> 12.???? <!--[endif]-->
    Java automatically inserts calls to the base-class constructor in the derived-class constructor

    ?

    <!--[if !supportLists]--> 13.? <!--[endif]--> 總結(personal):默認情況下,derived class的默認構造函數會在其第一條語句加入super()來調用base class 的默認構造函數。如果base class 沒有默認構造函數就會報錯。但是如果要在derived class中調用非默認的base class 構造函數,則必須手工調用super(parameter),且這句必須在derived class 構造函數的第一句。如果你在derived class中沒有調用base class 的構造函數,則derived class 構造函數會調用base class 的默認構造函數
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 14.? <!--[endif]--> 不能在繼承過程中降低權限。

    <!--[if !supportLists]--> 15.? <!--[endif]-->

    Base class

    Other part of subclass except the part in base class

    Subclass object

    對于一個derived class 對象而言,他已經包含base class對象,如上圖所示,可以用測試內存地址驗證

    Class A

    {A(){System.out.println(this);

    }

    Class B extends A

    {B(){System.out.println(this);}

    }

    ?

    <!--[if !vml]-->?15.bmp<!--[endif]-->


    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 16.? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    Composition is generally used when you want the features of an existing class inside your new class, but not its interface. That is, you embed an object so that you can use it to implement functionality in your new class, but the user of your new class sees the interface you’ve defined for the new class rather than the interface from the embedded object. For this effect, you embed private objects of existing classes inside your new class.

    <!--[if !supportLists]--> 17.? <!--[endif]-->
    That is, protected in Java is automatically “friendly.

    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 18.? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    you should use inheritance sparingly,( 只有在明顯能夠產生實用價值時,才使用繼承,還有要考慮 polymorphism),One of the clearest ways to determine whether you

    should use composition or inheritance is to ask whether you’ll ever need

    to upcast from your new class to the base class. If you must upcast, then

    inheritance is necessary, but if you don’t need to upcast, then you should

    look closely at whether you need inheritance.

    ?

    <!--[if !supportLists]--> 19.? <!--[endif]--> java 沒有提供任何的機制可以保持對象的內容不變。對array也是這樣的

    <!--[if !supportLists]--> 20.? <!--[endif]--> 初始化的順序
    base class
    裝載-base class中的static 變量初始化->derived class static變量初始化-base class 對象的初始化(1,數據成員初始化為默認值,for reference ,it is null. 2, 構造函數執行)-> derived class 對象初始化
    注:當你在derived class 中時,base class 應該已經可以初始化完畢,可以使用了。

    <!--[if !supportLists]--> 21.? <!--[endif]--> java 中的所有函數,除了被聲明為final,皆使用后期綁定。

    <!--[if !supportLists]--> 22.??? <!--[endif]--> Inheritance vs composition
    A better approach is to choose composition first, when it’s not obvious which one you should use. Composition does not force a design into an inheritance hierarchy. But composition is also more flexible since it’s possible to dynamically choose a type (and thus behavior) when using composition, whereas inheritance requires an exact type to be known at compile-time.(當你不知道該選擇“繼承“,或“組合“是,最好先選擇組合,組合不會強迫你的設計出現一大串繼承階層架構。組合手法彈性比較大)

    <!--[if !supportLists]--> 23.??? <!--[endif]-->
    a good guideline for constructors is, “Do as little as possible to set the object into a good state, and if you can possibly avoid it, don’t call any methods.”

    <!--[if !supportLists]--> 24.? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    import java.util.*;

    class Useful {

    public void f() {}

    Chapter 7: Polymorphism 345

    public void g() {}

    }

    class MoreUseful extends Useful {

    public void f() {}

    public void g() {}

    public void u() {}

    public void v() {}

    public void w() {}

    }

    public class RTTI {

    public static void main(String[] args) {

    Useful[] x = {

    new Useful(),

    new MoreUseful()

    };

    x[0].f();

    x[1].g();

    // Compile-time: method not found in Useful:

    /* x[1] 在執行時期才可以知道其類型是 MoreUseful, 所以這里編譯不了

    //! x[1].u();

    ((MoreUseful)x[1]).u(); // Downcast/RTTI

    ((MoreUseful)x[0]).u(); // Exception thrown

    }

    }

    <!--[if !supportLists]--> 25.? <!--[endif]--> interface 中的data 默認是public static final.函數為public .
    請千萬記住,interface 存在的根本理由是: 能夠被向上轉型至多個基本型別。
    如果你的base class 可以不帶任何函數定義或任何成員變量,應優先使用interface
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 26.? <!--[endif]--> 所有的class的定義,無論是在函數內,或任意{}語句內,該class的定義都會和其他class一起被編譯出來
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 27.??? <!--[endif]-->
    If you’re defining an anonymous inner class and want to use an object

    that’s defined outside the anonymous inner class, the compiler requires

    that the outside object be final

    <!--[if !supportLists]--> 28.? <!--[endif]--> 總結(personal):non-static inner class 不能包含任何static 數據、method
    static inner class
    卻可以包含static data,or static methond,當然也可以包含non-static 成員。
    static inner class
    就說明它與外圍class沒有聯系,和一個單獨的class 一樣。
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    ??? E.g non-static inner class can not have static data.bmp

    <!--[if !supportLists]--> 29.??? <!--[endif]-->
    So one way to look at the inner class is as the completion of the solution of the multiple-inheritance problem. Interfaces solve part of the problem, but inner classes effectively allow “multiple implementation inheritance.” That is, inner classes effectively allow you to inherit from more than one non-interface.

    <!--[if !supportLists]--> 30.<!--[endif]-->
    chapter 9

    <!--[if !supportLists]--> 31.???? <!--[endif]-->
    Arrays provides the overloaded method equals( ) to compare entire arrays for equality. Again, these are overloaded for all the primitives, and for Object. To be equal, the arrays must have the same number of elements and each element must be equivalent to each corresponding element in the other array, using the equals( ) for each element. (For primitives, that primitive’s wrapper class equals( ) is used; Integer.equals( ) for int.

    <!--[if !supportLists]--> 32.??? <!--[endif]--> 使某個class具有比較能力有兩種方法,1、可以實現java.lang.Comparable interface,只有一個函數compareTo()在這個interface,接受另外一個Object做為parameter.2、實現Comparator interface, 兩個函數在這個interface 內,: compare() equal().
    by creating a separateclass that implements an interface called Comparator. This has two methods, compare( ) and equals( ). However, you don’t have to implement equals( ) except for special performance needs, because anytime you create a class it is implicitly inherited from Object, which has an equals( ). So you can just use the default Object equals( ) and satisfy the contract imposed by the interface.

    ?

    <!--[if !supportLists]--> 33.??? <!--[endif]-->
    Unlike arrays, the containers print nicely without any help

    <!--[if !supportLists]--> 34.? <!--[endif]--> remember the following diagram

    <!--[if !vml]--><!--[endif]-->34.bmp
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 35.??? <!--[endif]-->
    Notice that there’s no get( ) function for random-access element selection. That’s because Collection also includes Set, which maintains its own internal ordering (and thus makes random-access lookup meaningless). Thus, if you want to examine all the elements of a Collection you must use an iterator; that’s the only way to fetch things back

    <!--[if !supportLists]--> 36.??? <!--[endif]-->
    The form for the definitions for equals( ) and hashCode( ) will be described later in this chapter. You must define an equals( ) in both cases, but the hashCode( ) is absolutely necessary only if the class will be placed in a HashSet (which is likely, since that should generally be your first choice as a Set implementation). However, as a programming style you should always override hashCode( ) when you override equals( ). This process will be fully detailed later in this chapter.

    ?

    <!--[if !supportLists]--> 37.??? <!--[endif]-->
    In the previous example, a standard library class (Integer) was used as a

    key for the HashMap. It worked fine as a key, because it has all the necessary wiring to make it work correctly as a key. But a common pitfall occurs with HashMaps when you create your own classes to be used as keys. For example, consider a weather predicting system that matches Groundhog objects to Prediction objects. It seems fairly

    straightforward—you create the two classes, and use Groundhog as the

    key and Prediction as the value:

    //: c09:SpringDetector.java

    // Looks plausible, but doesn't work.

    import java.util.*;

    class Groundhog {

    int ghNumber;

    Groundhog(int n) { ghNumber = n; }

    }

    class Prediction {

    boolean shadow = Math.random() > 0.5;

    public String toString() {

    if(shadow)

    return "Six more weeks of Winter!";

    else

    return "Early Spring!";

    }

    }

    public class SpringDetector {

    public static void main(String[] args) {

    HashMap hm = new HashMap();

    for(int i = 0; i < 10; i++)

    hm.put(new Groundhog(i), new Prediction());

    System.out.println("hm = " + hm + "\n");

    System.out.println(

    "Looking up prediction for Groundhog #3:");

    Groundhog gh = new Groundhog(3);

    if(hm.containsKey(gh))

    System.out.println((Prediction)hm.get(gh));

    else

    System.out.println("Key not found: " + gh);

    }

    } ///:~

    Each Groundhog is given an identity number, so you can look up a

    Prediction in the HashMap by saying, “Give me the Prediction

    associated with Groundhog number 3.” The Prediction class contains

    a boolean that is initialized using Math.random( ), and a toString( )

    that interprets the result for you. In main( ), a HashMap is filled with

    Groundhog s and their associated Predictions. The HashMap is

    printed so you can see that it has been filled. Then a Groundhog with an

    identity number of 3 is used as a key to look up the prediction for

    Groundhog #3 (which you can see must be in the Map).

    It seems simple enough, but it doesn’t work. The problem is that

    Groundhog is inherited from the common root class Object (which is

    what happens if you don’t specify a base class, thus all classes are

    ultimately inherited from Object) ?It is Object’s hashCode( ) method

    that is used to generate the hash code for each object, and by default it

    just uses the address of its object. Thus, the first instance of Groundhog(3) does not produce a hash code equal to the hash code forthe second instance of Groundhog(3) that we tried to use as a lookup.

    You might think that all you need to do is write an appropriate override

    for hashCode( ). But it still won’t work until you’ve done one more

    thing: override the equals( ) that is also part of Object. This method is

    used by the HashMap when trying to determine if your key is equal to

    any of the keys in the table. Again, the default Object.equals( ) simply

    compares object addresses, so one Groundhog(3) is not equal to

    another Groundhog(3).

    Thus, to use your own classes as keys in a HashMap, you must override

    both hashCode( ) and equals( )

    ?

    <!--[if !supportLists]--> 38.??? <!--[endif]-->

    in hashset or hashmap ,first of all you? produce the hashcode, then,use hashcode /capacity(number of buckets) to get the index of the array,A[index]refer to a array of elements? with the same hashcode value

    Slot or bucket

    EntrySet

    HashSet or HashMap 的內部表示

    <!--[if !vml]--> 39.bmp<!--[endif]-->

    The most important factor in creating a hashCode( ) is that, regardless

    of when hashCode( ) is called, it produces the same value for a

    particular object every time it is called.

    So if your hashCode( ) depends on mutable data in the object the user must

    be made aware that changing the data will effectively produce a different

    key by generating a different hashCode( ).

    ?

    <!--[if !supportLists]--> 39.??? <!--[endif]-->
    Strings have the special characteristic that if a program has several String objects that contain identical character sequences, then those String objects all map to the

    same memory

    chapter 10 Exception

    <!--[if !supportLists]--> 40.?? <!--[endif]-->
    When you throw an exception, several things happen. First, the exception

    object is created in the same way that any Java object is created: on the

    heap, with new. Then the current path of execution (the one you couldn’t

    continue) is stopped and the reference for the exception object is ejected

    from the current context. At this point the exception handling mechanism

    takes over and begins to look for an appropriate place to continue

    executing the program

    <!--[if !supportLists]--> 41.??? <!--[endif]-->
    Like any object in Java, you always create exceptions on the heap using

    new , which allocates storage and calls a constructor. There are two constructors in all standard exceptions: the first is the default constructor,

    and the second takes a string argument so you can place pertinent

    information in the exception:

    ?

    <!--[if !supportLists]--> 42.? <!--[endif]--> 總結(personal: 1override 函數只能擲出base class 明確列出的異常,當interface 中的某個函數也存在base class中時,interface 中的函數異常是不能在實現類中改變在實現類中這個函數的異常。2、在derived class中的函數可以不擲出base class規定的異常,但是如果要throws exception,則,這個exception 必須是base class中明確列出來的。
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    <!--[if !supportLists]--> 43.??? <!--[endif]-->
    The restriction on exceptions does not apply to constructors. You can see in StormyInning that a constructor can throw anything it wants, regardless of what the base-class constructor throws. However, since a base-class constructor must always be called one way or another (here, the default constructor is called automatically), the derived-class constructor must declare any base-class constructor exceptions in its exception specification. Note that a derived-class constructor cannot catch exceptions thrown by its base-class constructor.

    chapter 11 : java i/o

    <!--[if !supportLists]--> 44.?? <!--[endif]-->
    Serializing an object is quite simple, as long as the object implements the

    Serializable interface (this interface is just a flag and has no methods).

    When serialization was added to the language, many standard library

    classes were changed to make them serializable, including all of the

    wrappers for the primitive types, all of the container classes, and many

    others. Even Class objects can be serialized.

    <!--[if !supportLists]--> 45.? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    To serialize an object, you create some sort of OutputStream object and

    then wrap it inside an ObjectOutputStream object. At this point you

    need only call writeObject( ) and your object is serialized and sent to

    the OutputStream. To reverse the process, you wrap an InputStream

    inside an ObjectInputStream and call readObject( ). What comes

    back is, as usual, a reference to an upcast Object, so you must downcast

    to set things straight.

    A particularly clever aspect of object serialization is that it not only saves

    an image of your object but it also follows all the references contained in

    your object and saves those objects, and follows all the references in each

    of those objects

    ?

    <!--[if !supportLists]--> 46.??? <!--[endif]-->
    Note that no constructor, not even the default constructor, is called in the

    process of deserializing a Serializable object. The entire object is

    restored by recovering data from the InputStream.

    Object serialization is byte-oriented (not Unicode -oriented), and thus uses the InputStream and OutputStream hierarchies.

    ?

    <!--[if !supportLists]--> 47.???????????? <!--[endif]--> 使用Externalizable

    //: c11:Blip3.java

    // Reconstructing an externalizable object.

    import java.io.*;

    import java.util.*;

    class Blip3 implements Externalizable {

    int i;

    String s; // No initialization

    public Blip3() {

    System.out.println("Blip3 Constructor");

    // s, i not initialized

    }

    public Blip3(String x, int a) {

    System.out.println("Blip3(String x, int a)");

    s = x;

    i = a;

    // s & i initialized only in nondefault

    // constructor.

    }

    public String toString() { return s + i; }

    public void writeExternal(ObjectOutput out)

    throws IOException {

    System.out.println("Blip3.writeExternal");

    // You must do this:

    out.writeObject(s);

    out.writeInt(i);

    }

    public void readExternal(ObjectInput in)

    throws IOException, ClassNotFoundException {

    System.out.println("Blip3.readExternal");

    // You must do this:

    s = (String)in.readObject();

    i =in.readInt();

    }

    public static void main(String[] args)

    throws IOException, ClassNotFoundException {

    System.out.println("Constructing objects:");

    Blip3 b3 = new Blip3("A String ", 47);

    System.out.println(b3);

    ObjectOutputStream o =

    new ObjectOutputStream(

    new FileOutputStream("Blip3.out"));

    System.out.println("Saving object:");

    o.writeObject(b3);

    o.close();

    // Now get it back:

    ObjectInputStream in =

    new ObjectInputStream(

    new FileInputStream("Blip3.out"));

    System.out.println("Recovering b3:");

    b3 = (Blip3)in.readObject();

    System.out.println(b3);

    }

    } ///:~

    You can control the process of serialization by implementing the

    Externalizable interface instead of the Serializable interface. The

    Externalizable interface extends the Serializable interface and adds

    two methods, writeExternal( ) and readExternal( ), that are

    automatically called for your object during serialization and

    deserialization so that you can perform your special operations.

    ?

    When b1 is recovered, the Blip1 default constructor is called. This is

    different from recovering a Serializable object, in which the object is

    constructed entirely from its stored bits, with no constructor calls. With

    an Externalizable object, all the normal default construction behavior

    occurs (including the initializations at the point of field definition), and

    then readExternal( ) is called. You need to be aware of this—in

    particular, the fact that all the default construction always takes place—to

    produce the correct behavior in your Externalizable objects.

    If you are inheriting from an Externalizable object, you’ll typically call

    the base-class versions of writeExternal( ) and readExternal( ) to

    provide proper storage and retrieval of the base-class components.

    ?

    So to make things work correctly you must not only write the important

    data from the object during the writeExternal( ) method (there is no

    default behavior that writes any of the member objects for an

    Externalizable object), but you must also recover that data in the

    readExternal( ) method. This can be a bit confusing at first because the

    default construction behavior for an Externalizable object can make it

    seem like some kind of storage and retrieval takes place automatically. It

    does not.

    ?

    ?

    <!--[if !supportLists]--> 48.??? <!--[endif]-->
    One way to prevent sensitive parts of your object from being serialized is

    to implement your class as Externalizable, as shown previously. Then

    nothing is automatically serialized and you can explicitly serialize only the

    necessary parts inside writeExternal( ).

    If you’re working with a Serializable object, however, all serialization

    happens automatically. To control this, you can turn off serialization on a

    field-by-field basis using the transient keyword, which says “Don’t

    bother saving or restoring this—I’ll take care of it.

    <!--[if !supportLists]--> 49.??? <!--[endif]-->
    Since Externalizable objects do not store any of their fields by default,

    the transient keyword is for use with Serializable objects only.

    <!--[if !supportLists]--> 50.? <!--[endif]--> Externalizable 的替代寫法

    ? ? ? ? If you’re not keen on implementing the Externalizable interface, there’s

    another approach. You can implement the Serializable interface and

    add (notice I say “add” and not “override” or “implement”) methods

    called writeObject( ) and readObject( ) that will automatically be

    called when the object is serialized and deserialized, respectively. That is,

    if you provide these two methods they will be used instead of the default

    serialization.

    The methods must have these exact signatures:

    private void

    writeObject(ObjectOutputStream stream)

    throws IOException;

    private void

    readObject(ObjectInputStream stream)

    throws IOException, ClassNotFoundException

    ?

    It would appear that when you call

    ObjectOutputStream.writeObject( ) , the Serializable object that

    you pass it to is interrogated (using reflection, no doubt) to see if it

    implements its own writeObject( ). If so, the normal serialization

    process is skipped and the writeObject( ) is called. The same sort of

    situation exists for readObject( ).

    ?

    There’s one other twist. Inside your writeObject( ), you can choose to

    perform the default writeObject( ) action by calling

    defaultWriteObject( ) . Likewise, inside readObject( ) you can call

    defaultReadObject( )


    If you are going to use the default mechanism to write the non-transient

    parts of your object, you must call defaultWriteObject( ) as the first

    operation in writeObject( ) and defaultReadObject( ) as the first

    operation in readObject( ).

    ?

    <!--[if !supportLists]--> 51.? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    animals: [Bosco the dog[Animal@1cc76c], House@1cc769

    , Ralph the hamster[Animal@1cc76d], House@1cc769

    , Fronk the cat[Animal@1cc76e], House@1cc769

    ]

    animals1: [Bosco the dog[Animal@1cca0c], House@1cca16

    , Ralph the hamster[Animal@1cca17], House@1cca16

    , Fronk the cat[Animal@1cca1b], House@1cca16

    ]

    animals2: [Bosco the dog[Animal@1cca0c], House@1cca16

    , Ralph the hamster[Animal@1cca17], House@1cca16

    , Fronk the cat[Animal@1cca1b], House@1cca16

    ]

    animals3: [Bosco the dog[Animal@1cca52], House@1cca5c

    , Ralph the hamster[Animal@1cca5d], House@1cca5c

    , Fronk the cat[Animal@1cca61], House@1cca5c

    ]

    ?

    As long as you’re serializing everything to a single stream, you’ll be able to

    recover the same web of objects that you wrote, with no accidental

    duplication of objects. Of course, you can change the state of your objects

    in between the time you write the first and the last, but that’s your

    responsibility—the objects will be written in whatever state they are in

    (and with whatever connections they have to other objects) at the time

    you serialize them.

    ?

    Chapter 12 RTTI

    <!--[if !supportLists]--> 52.??? <!--[endif]-->
    There’s a Class object for each class that is part of your program. That is,

    each time you write and compile a new class, a single Class object is also

    created (and stored, appropriately enough, in an identically named .class

    file). At run-time, when you want to make an object of that class, the Java

    Virtual Machine (JVM) that’s executing your program first checks to see if

    the Class object for that type is loaded. If not, the JVM loads it by finding

    the .class file with that name. Thus, a Java program isn’t completely

    loaded before it begins, which is different from many traditional

    languages.

    Once the Class object for that type is in memory, it is used to create all

    objects of that type.

    ?

    <!--[if !supportLists]--> 53.? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    Java provides a second way to produce the reference to the Class object,

    using a class literal. In the above program this would look like:

    ?

    Gum.class;

    ?

    which is not only simpler, but also safer since it’s checked at compiletime

    <!--[if !vml]-->?54.bmp<!--[endif]-->

    <!--[if !supportLists]--> 54.??? <!--[endif]-->
    instanceof says “are you this class, or a class derived from this class?” On the other hand, if you compare the actual Class objects using ==, there is no concern with

    inheritance—it’s either the exact type or it isn’

    ?

    <!--[if !supportLists]--> 1.???????? <!--[endif]--> chapter 14 multithread

    <!--[if !supportLists]--> 2.??????? <!--[endif]--> ?

    regardless of whether you’re explicitly using threads, you can produce the current

    thread used by your program with Thread and the static sleep( ) method.

    <!--[if !supportLists]--> 3.??????? <!--[endif]-->
    The simplest way to create a thread is to inherit from class Thread, which has all the wiring necessary to create and run threads. The most important method for Thread is run( ), which you must override to make the thread do your bidding. Thus, run( ) is the code that will be executed “simultaneously” with the other threads in a program.

    <!--[if !supportLists]--> 4.??????? <!--[endif]-->
    When main( ) creates the Thread objects it isn’t capturing the

    references for any of them. An ordinary object would be fair game for

    garbage collection, but not a Thread. Each Thread “registers” itself so

    there is actually a reference to it someplace and the garbage collector can’t

    clean it up.

    <!--[if !supportLists]--> 5.??????? <!--[endif]-->
    .
    A “daemon” thread is one that is supposed to provide a general service in

    the background as long as the program is running, but is not part of the

    essence of the program. Thus, when all of the non-daemon threads

    complete, the program is terminated. Conversely, if there are any nondaemon

    threads still running, the program doesn’t terminate. (There is,

    for instance, a thread that runs main( ).)

    <!--[if !supportLists]--> 6.??????? <!--[endif]-->
    Java has built-in support to prevent collisions over one kind of resource:

    the memory in an object. Since you typically make the data elements of a

    class private and access that memory only through methods, you can

    prevent collisions by making a particular method synchronized. Only

    one thread at a time can call a synchronized method for a particular

    object (although that thread can call more than one of the object’s

    synchronized methods). Here are simple synchronized methods:

    synchronized void f() { /* ... */ }

    synchronized void g(){ /* ... */ }

    Each object contains a single lock (also called a monitor) that is

    automatically part of the object (you don’t have to write any special code).

    When you call any synchronized method, that object is locked and no

    other synchronized method of that object can be called until the first

    one finishes and releases the lock. In the example above, if f( ) is called

    for an object, g( ) cannot be called for the same object until f( ) is

    completed and releases the lock. Thus, there’s a single lock that’s shared

    by all the synchronized methods of a particular object, and this lock

    prevents common memory from being written by more than one method

    at a time (i.e., more than one thread at a time).

    There’s also a single lock per class (as part of the Class object for the

    class), so that synchronized static methods can lock each other out

    from simultaneous access of static data on a class-wide basis.

    <!--[if !supportLists]--> 7.??????? <!--[endif]-->
    You’ll notice that both run( ) and synchTest( ) are synchronized. If

    you synchronize only one of the methods, then the other is free to ignore

    the object lock and can be called with impunity. This is an important

    point: Every method that accesses a critical shared resource must be

    synchronized or it won’t work right

    <!--[if !supportLists]--> 8.??????? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    What we’d like for this example is a way to isolate only part of the code

    inside run( ). The section of code you want to isolate this way is called a

    critical section and you use the synchronized keyword in a different

    way to set up a critical section. Java supports critical sections with the

    synchronized block; this time synchronized is used to specify the object

    whose lock is being used to synchronize the enclosed code:

    synchronized(syncObject) {

    // This code can be accessed

    // by only one thread at a time

    }

    Before the synchronized block can be entered, the lock must be acquired

    on syncObject. If some other thread already has this lock, then the block

    cannot be entered until the lock is given up.

    <!--[if !supportLists]--> 9.??????? <!--[endif]-->
    <!--[if !supportLineBreakNewLine]-->
    <!--[endif]-->

    Blocking

    A thread can be in any one of four states:

    1. New : The thread object has been created but it hasn’t been started

    yet so it cannot run.

    2. Runnable : This means that a thread can be run when the timeslicing

    mechanism has CPU cycles available for the thread. Thus,

    the thread might or might not be running, but there’s nothing to

    prevent it from being run if the scheduler can arrange it; it’s not

    dead or blocked.

    3. Dead : The normal way for a thread to die is by returning from its

    run( ) method. You can also call stop( ), but this throws an

    exception that’s a subclass of Error (which means you aren’t

    forced to put the call in a try block). Remember that throwing an

    exception should be a special event and not part of normal program

    execution; thus the use of stop( ) is deprecated in Java 2. There’s

    also a destroy( ) method (which has never been implemented)

    that you should never call if you can avoid it since it’s drastic and

    doesn’t release object locks.

    4. Blocked : The thread could be run but there’s something that

    prevents it. While a thread is in the blocked state the scheduler will

    simply skip over it and not give it any CPU time. Until a thread

    reenters the runnable state it won’t perform any operations.

    Becoming blocked

    The blocked state is the most interesting one, and is worth further

    examination. A thread can become blocked for five reasons:

    1. You’ve put the thread to sleep by calling sleep(milliseconds), in

    which case it will not be run for the specified time.

    2. You’ve suspended the execution of the thread with suspend( ). It

    will not become runnable again until the thread gets the

    resume( ) message (these are deprecated in Java 2, and will be

    examined further).

    3. You’ve suspended the execution of the thread with wait( ). It will

    not become runnable again until the thread gets the notify( ) or

    notifyAll( ) message. (Yes, this looks just like number 2, but

    there’s a distinct difference that will be revealed.)

    4. The thread is waiting for some I/O to complete.

    5. The thread is trying to call a synchronized method on another

    object, and that object’s lock is not available.

    You can also call yield( ) (a method of the Thread class) to voluntarily

    give up the CPU so that other threads can run. However, the same thing

    happens if the scheduler decides that your thread has had enough time

    and jumps to another thread. That is, nothing prevents the scheduler

    from moving your thread and giving time to some other thread. When a

    thread is blocked, there’s some reason that it cannot continue running.

    <!--[if !supportLists]--> 10.?? <!--[endif]-->
    it’s important to understand that both sleep( )

    and suspend( ) do not release the lock as they are called. You must be

    aware of this when working with locks. On the other hand, the method

    wait( ) does release the lock when it is called, which means that other

    synchronized methods in the thread object could be called during a

    wait( ) .

    ?

    <!--[if !supportLists]--> 11.???? <!--[endif]--> ?

    One fairly unique aspect of wait( ) and notify( ) is that both methods are

    part of the base class Object and not part of Thread as are sleep( ),

    suspend( ) , and resume( ). Although this seems a bit strange at first—

    to have something that’s exclusively for threading as part of the universal

    base class—it’s essential because they manipulate the lock that’s also part

    of every object. As a result, you can put a wait( ) inside any

    synchronized method, regardless of whether there’s any threading

    going on inside that particular class. In fact, the only place you can call

    wait( ) is within a synchronized method or block. If you call wait( ) or

    notify( ) within a method that’s not synchronized, the program will

    compile, but when you run it you’ll get an

    IllegalMonitorStateException with the somewhat nonintuitive

    message “current thread not owner.” Note that sleep( ), suspend( ),

    and resume( ) can all be called within non-synchronized methods

    since they don’t manipulate the lock.

    ?

    ?

    ?

    ?

    posted on 2006-06-28 17:46 junhong 閱讀(1777) 評論(0)  編輯  收藏 所屬分類: java技術

    主站蜘蛛池模板: 国产精品成人啪精品视频免费| 亚洲日本中文字幕区| 久久久久亚洲国产| 无码国产精品一区二区免费I6| 亚洲AV无一区二区三区久久| 羞羞视频在线免费观看| 国产免费啪嗒啪嗒视频看看| 亚洲精品久久无码av片俺去也| 无码国产精品久久一区免费| 亚洲精品无码av片| 国产免费久久精品| 瑟瑟网站免费网站入口| 久久影院亚洲一区| 黄色片免费在线观看| 亚洲va久久久噜噜噜久久狠狠| a级男女仿爱免费视频| 亚洲熟妇无码AV在线播放| www一区二区www免费| 亚洲女久久久噜噜噜熟女| 99久久国产精品免费一区二区| 亚洲AV日韩AV永久无码下载| **真实毛片免费观看| 亚洲综合小说另类图片动图 | 亚洲精品高清在线| 国产免费网站看v片在线| 久久久久久亚洲av成人无码国产| 青青草无码免费一二三区| 亚洲欧洲日产v特级毛片| 国产成在线观看免费视频| 久久无码av亚洲精品色午夜| 亚洲第一区精品日韩在线播放| 亚洲日韩在线观看免费视频| 亚洲尹人九九大色香蕉网站| 国产成在线观看免费视频| 香蕉国产在线观看免费| 精品日韩亚洲AV无码一区二区三区 | 亚洲一欧洲中文字幕在线| 国产又黄又爽又刺激的免费网址| 一区二区三区免费视频播放器| 久久久久亚洲精品美女| 成年女人毛片免费观看97|