Java Class — Object

Object class is present in java.lang package. Every class in Java is directly or indirectly derived from the Object class. If a Class does not extend any other class then it is direct child class of Object and if extends other class then it is an indirectly derived. Therefore the Object class methods are available to all Java classes. Hence Object class acts as a root of inheritance hierarchy in any Java Program.

Methods in Object class

//1
private static native void registerNatives();
    static {
        registerNatives();
    }

//2 Returns the runtime class of this Object.
public final native Class<?> getClass();

//3 Returns a hash code value for the object.
public native int hashCode();

//4 Indicates whether some other object is "equal to" this one.
public boolean equals(Object obj) {
        return (this == obj);
    }

//5 Creates and returns a copy of this object
protected native Object clone() throws CloneNotSupportedException;

//6 Returns a string representation of the object.
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

//7 Wakes up a single thread that is waiting on this object's monitor.
public final native void notify();

//8 Wakes up all threads that are waiting on this object's monitor.
public final native void notifyAll();

//9 Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
public final native void wait(long timeout) throws InterruptedException;

//10 Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException("nanosecond timeout value out of range");
        }
        if (nanos > 0) {
            timeout++;
        }
        wait(timeout);
    }

//11 Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object
public final void wait() throws InterruptedException {
        wait(0);
    }

//12 Called by the garbage collector on an object when garbage collection determines that there are no more references to the object
protected void finalize() throws Throwable { }
1. registerNatives()

Normally, in order for the JVM to find your native functions, they have to be named a certain way.
e.g., for java.lang.Object.registerNatives, the corresponding C function is named Java_java_lang_Object_registerNatives. By using registerNatives (or rather, the JNI function RegisterNatives), you can name your C functions whatever you want.

Here's the associated C code (from OpenJDK 6):

static JNINativeMethod methods[] = {
    {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};

JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}

(Notice that Object.getClass is not in the list; it will still be called by the "standard" name of Java_java_lang_Object_getClass.) For the functions listed, the associated C functions are as listed in that table, which is handier than writing a bunch of forwarding functions.

Registering native functions is also useful if you are embedding Java in your C program and want to link to functions within the application itself (as opposed to within a shared library), or the functions being used aren't otherwise "exported", since these would not normally be found by the standard method lookup mechanism. Registering native functions can also be used to "rebind" a native method to another C function (useful if your program supports dynamically loading and unloading modules, for example).


2. getClass()

The function of method getClass() seems to be very straightforward, but if you think more over it, you will find something worth pondering.
A.class | a.getClass() | instanceof
The difference between A.class and a.getClass():
They are actually different with regards to where you can use them. A.class works at compile time while a.getClass() requires an instance of type A and works at runtime.

The difference between a.getClass() and instanceof:
When rewrite equals() method,
Without using instanceof:

if (obj == null)
  return false;
if (getClass() != obj.getClass())
  return false;

Using instanceof:

if (obj == null)
  return false;
if (!(obj instanceof MyClass))
  return false;
  • instanceof tests whether the object reference on the left-hand side (LHS) is an instance of the type on the right-hand side (RHS) or some subtype.
  • getClass() == ... tests whether the types are identical.

3. hashCode()

How to override hashCode() method
(1) Classic way

public class User {
    private String name;
    private int age;
    private String passport;

    //getters and setters, constructor

    @Override
    public boolean equals(Object o) {

        if (o == this) return true;
        if (!(o instanceof User)) {
            return false;
        }

        User user = (User) o;

        return user.name.equals(name) &&
                user.age == age &&
                user.passport.equals(passport);
    }

    //Idea from effective Java : Item 9
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + name.hashCode();
        result = 31 * result + age;
        result = 31 * result + passport.hashCode();
        return result;
    }

}

The 17 and 31 hash code idea is from the classic Java book – effective Java : item 9

The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i. Modern VMs do this sort of optimization automatically.
To conclude, it's because the reasons below:

  1. Choose odd number to multiply because no information lost.
  2. Choose prime number because its a traditional behavior.
  3. Choose 31 because it can be optimized by VM.
    (2) JDK7
import java.util.Objects;

public class User {
    private String name;
    private int age;
    private String passport;

    //getters and setters, constructor

    @Override
    public boolean equals(Object o) {

        if (o == this) return true;
        if (!(o instanceof User)) {
            return false;
        }
        User user = (User) o;
        return age == user.age &&
                Objects.equals(name, user.name) &&
                Objects.equals(passport, user.passport);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, passport);
    }

}

(3) Apache Commons Lang
Alternatively, you can use the Apache Commons Lang EqualsBuilder and HashCodeBuilder function.

import org.apache.commons.lang3.builder;

public class User {
    private String name;
    private int age;
    private String passport;

    //getters and setters, constructor

     @Override
    public boolean equals(Object o) {

        if (o == this) return true;
        if (!(o instanceof User)) {
            return false;
        }

        User user = (User) o;

        return new EqualsBuilder()
                .append(age, user.age)
                .append(name, user.name)
                .append(passport, user.passport)
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37)
                .append(name)
                .append(age)
                .append(passport)
                .toHashCode();
    }

}

4. equals()

Here I will compare equals() versus "==", when the difference is clear, then the using scenario of equals() is undoubted.
"==" compares object references, it checks to see if the two operands refer to the same object (not equivalent objects, the same object).
While equals() will only compare what it is written to compare.

  • if a class does not override the equals method, then it defaults to the equals(Object o) method of the
    closest parent class that has overridden this method.
  • If no parent classes have provided an override, then it defaults to the method from the ultimate parent class, Object. According to Object API, it's the same as "==".
    Last but not least, every time you override equals(), you should also override hashcode()

5. clone()

Firstly I will clarify the difference between = and clone().

Dog dogA = new Dog("old");
Dog dogB = dogA;
Dog dogC = (Dog)dogA.clone();
dogA.setName("new");
system.out.println(dogA.name);//new
system.out.println(dogB.name);//new
system.out.println(dogC.name);//old

When an object implements clonable, then it can use clone(). In Java, objects are manipulated through reference variables, and there is no operator for copying an object—the assignment operator duplicates the reference, not the object. The clone() method provides this missing functionality.

clone() acts like a copy constructor. Typically it calls the clone() method of its superclass to obtain the copy, etc. until it eventually reaches Object's clone() method. The special clone() method in the base class Object
provides a standard mechanism for duplicating objects.The class Object's clone() method creates and returns a copy of the object, with the same class and with all the fields having the same values.
.
The default implementation of Object.clone() performs a shallow copy. When a class desires a deep copy or some other custom behavior, they must perform that in their own clone() method after they obtain the copy from the superclass.
Some principles:
(1) Every type that needs to be cloned must have a public clone() method in its own class or a publicly accessible clone() method in one of its parent classes.
Example:
To invoke clone() on varY1, which is of type Y, then Y or a parent of Y must declare a publicly accessible clone() method. Here, it is the parent class X that provides the public clone() method.

public class X implements Cloneable {
        public X clone() throws CloneNotSupportedException {
                return (X) super.clone();
        }
}

public class Y extends X { }

public class Z extends Y { }

public class test1 {
        public void function() throws CloneNotSupportedException {
                Y varY1 = new Z();
                Y varY2 = (Y) varY1.clone();
        }
}

(2) Every class that implements clone() should call super.clone() to obtain the cloned object reference. If the class has any object references that must be cloned as well (when deep copying, for example), then the clone() method should perform any required modifications on the object before returning it. (Since Object.clone() returns an exact copy of the original object, any mutable fields such as collections and arrays would be shared between the original and the copy - which in most cases would neither be expected nor desired.)
Example:
Since class Z contains an object reference, its clone() method also clones that object reference in order to return a deep copy of the original.

public class X implements Cloneable {
        public X clone() throws CloneNotSupportedException {
                return (X) super.clone();
        }
}

public class Y extends X { }

public class ObjectABC implements Cloneable {
        public ObjectABC clone() throws CloneNotSupportedException {
                return (ObjectABC) super.clone();
        }
}

public class Z extends Y {
        private ObjectABC someABC;

        public Z clone() throws CloneNotSupportedException {
                Z newZ = (Z) super.clone();
                newZ.someABC = someABC.clone();

                return newZ;
        }
}

public class test1 {
        public void function() throws CloneNotSupportedException {
                Y varY1 = new Z();
                Y varY2 = (Y) varY1.clone();
        }
}

Generally, clone() is incompatible with final fields. Because clone() is essentially a default constructor (one that has no arguments) it is impossible to assign a final field within a clone() method; a compiler error is the result. Where the value of the field is an immutable object this is okay; just let the 'constructor' copy the reference and both the original and its clone will share the same object.


6. toString()

The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object.

getClass().getName() + '@' + Integer.toHexString(hashCode())

Effective Java suggests that the method toString should be override all the time to make it more practical.


7. notify()

I assume notify() and wait() methods are designed to implement a producer/consumer pattern.
The wait() and notify() methods are designed to provide a mechanism to allow a thread to block until a specific condition is met. For this I assume you're wanting to write a blocking queue implementation, where you have some fixed size backing-store of elements.

The first thing you have to do is to identify the conditions that you want the methods to wait for. In this case, you will want the put() method to block until there is free space in the store, and you will want the take() method to block until there is some element to return.

public class BlockingQueue<T> {

    private Queue<T> queue = new LinkedList<T>();
    private int capacity;

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void put(T element) throws InterruptedException {
        while(queue.size() == capacity) {
            wait();
        }

        queue.add(element);
        notify(); // notifyAll() for multiple producer/consumer threads
    }

    public synchronized T take() throws InterruptedException {
        while(queue.isEmpty()) {
            wait();
        }

        T item = queue.remove();
        notify(); // notifyAll() for multiple producer/consumer threads
        return item;
    }
}

There are a few things to note about the way in which you must use the wait and notify mechanisms.

Firstly, you need to ensure that any calls to wait() or notify() are within a synchronized region of code (with the wait() and notify() calls being synchronized on the same object). The reason for this (other than the standard thread safety concerns) is due to something known as a missed signal.

An example of this, is that a thread may call put() when the queue happens to be full, it then checks the condition, sees that the queue is full, however before it can block another thread is scheduled. This second thread then take()'s an element from the queue, and notifies the waiting threads that the queue is no longer full. Because the first thread has already checked the condition however, it will simply call wait() after being re-scheduled, even though it could make progress.

By synchronizing on a shared object, you can ensure that this problem does not occur, as the second thread's take() call will not be able to make progress until the first thread has actually blocked.

Secondly, you need to put the condition you are checking in a while loop, rather than an if statement, due to a problem known as spurious wake-ups. This is where a waiting thread can sometimes be re-activated without notify() being called. Putting this check in a while loop will ensure that if a spurious wake-up occurs, the condition will be re-checked, and the thread will call wait() again.


8. notifyAll()

Before choosing notify() or notifyAll(), think about this question: Do you want to tell one of the waiting threads that something happened, or do you want to tell all of them at the same time?
In some cases, all waiting threads can take useful action once the wait finishes. An example would be a set of threads waiting for a certain task to finish; once the task has finished, all waiting threads can continue with their business. In such a case you would use notifyAll() to wake up all waiting threads at the same time.
Another case, for example mutually exclusive locking, only one of the waiting threads can do something useful after being notified (in this case acquire the lock). In such a case, you would rather use notify(). Properly implemented, you could use notifyAll() in this situation as well, but you would unnecessarily wake threads that can't do anything anyway.


9. wait(long timeout)
10. wait(long timeout, int nano)
11. wait()

The above three methods don't have distinct differences except for the waiting time. Actually BlockingQueue is a better mechanism in my opinion.


12. finalize()

The main two arguments against overriding Object.finalize() is that:

  • You don't get to decide when it's called.
  • It may not get called at all.

The finalize method is called when an object is about to get garbage collected. That can be at any time after it has become eligible for garbage collection.
Note that it's entirely possible that an object never gets garbage collected (and thus finalize is never called). This can happen when the object never becomes eligible for gc (because it's reachable through the entire lifetime of the JVM) or when no garbage collection actually runs between the time the object become eligible and the time the JVM stops running (this often occurs with simple test programs).
If you rely on finalize for the correct operation of your application, then you're doing something wrong. finalize should only be used for cleanup of (usually non-Java) resources. And that's exactly because the JVM doesn't guarantee that finalize is ever called on any object.

According to some experience, there is one and only one reason for overriding Object.finalize(), but it is a very good reason:
To place error logging code in finalize() which notifies you if you ever forget to invoke close().

@Override
protected void finalize() throws Throwable
{
    if( Global.DEBUG && !closed )
    {
        Log.Error( "FORGOT TO CLOSE THIS!" );
    }
    //super.finalize(); see alip's comment on why this should not be invoked.
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末闽寡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子教寂,更是在濱河造成了極大的恐慌育勺,老刑警劉巖蔑水,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啥箭,死亡現(xiàn)場離奇詭異,居然都是意外死亡爹梁,警方通過查閱死者的電腦和手機(jī)右犹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姚垃,“玉大人念链,你說我怎么就攤上這事』矗” “怎么了掂墓?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長看成。 經(jīng)常有香客問我君编,道長,這世上最難降的妖魔是什么绍昂? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮偿荷,結(jié)果婚禮上窘游,老公的妹妹穿的比我還像新娘。我一直安慰自己跳纳,他們只是感情好忍饰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寺庄,像睡著了一般艾蓝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斗塘,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天赢织,我揣著相機(jī)與錄音,去河邊找鬼馍盟。 笑死于置,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贞岭。 我是一名探鬼主播八毯,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼搓侄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了话速?” 一聲冷哼從身側(cè)響起讶踪,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泊交,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體活合,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡错维,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年隆判,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咬腕。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡举反,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布瀑构,位于F島的核電站呻征,受9級(jí)特大地震影響沐祷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攒岛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一赖临、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阵子,春花似錦思杯、人聲如沸胜蛉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春目养,著一層夾襖步出監(jiān)牢的瞬間夹囚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工夯巷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留曹鸠,地道東北人窖逗。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓金砍,卻偏偏與公主長得像局蚀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子恕稠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容