views:

428

answers:

8

Why wasn't the java.lang.Object class declared to be abstract ?

Surely for an Object to be useful it needs added state or behaviour, an Object class is an abstraction, and as such it should have been declared abstract ... why did they choose not to ?

+16  A: 

An Object is useful even if it does not have any state or behaviour specific to it.

One example would be its use as a generic guard that's used for synchronization:

public class Example {
    private final Object o = new Object();

    public void doSomething() {
        synchronized (o) {
            // do possibly dangerous stuff
        }
    }
}

While this class is a bit simple in its implementation (it isn't evident here why it's useful to have an explicit object, you could just declare the method synchronized) there are several cases where this is really useful.

andri
If you have 3 methods in your class declared as synchronized, there is only one lock for all 3 methods, so only 1 of those 3 methods is invoked concurrently. If you have synchronized blocks inside your methods, you can use more than 1 object as lock.
Chochos
at least it was before java.util.concurrent or unless you're stuck in java 1.4
basszero
Why not have a Lock which extends Object if Object was abstract ?
_ande_turner_
@Ande: Yes, some things do this anyway. For example, java.awt.Component has "static class AWTTreeLock {}" and "static final Object LOCK = new AWTTreeLock();"
Michael Myers
From a strictly OO viewpoint you may well be right, there is no reason for any object to inherit from Object. The Object class is there for practical reasons, like being the top of Java's type system; your own design may not even need every object to inherit from one base class.
andri
@andri: I would use the term metamethods to describe what the methods within Object are for, as they are useful outside the system you are creating with the "Objects". I think that you get into the territory of "strange loops" when you allow Object to be instantiated.
_ande_turner_
@Ande there are a lot of things that were done pre 1.0 days that are basically poor practices, likely due to time constraints and a lack of knowledge about what the best practices were in Java (not hard to get those wrong since they were making it at the time :-)
TofuBeer
@TofuBeer: I kinda hope someone who worked on 1.0 would post "Oops." lol
_ande_turner_
"strange loops" when you allow Object to be instantiated? Huh? What in the world are you talking about?
Eddie
@Eddie: ever read Douglas Hofstadter's "Godel, Escher and Bach" ?
_ande_turner_
@Ande: Yes, I just don't understand how you mean it to apply here. Seems a big grandiose.
Eddie
@Eddie: We could just keep going around in circles, but ultimately that would prove my point not yours. :p
_ande_turner_
+4  A: 

Does Object specify methods that classes extending it must implement in order to be useful? No, and therefor it needn't be abstract.

The concept of a class being abstract has a well defined meaning that does not apply to Object.

Kris
Your "therefore" does not logically follow from your preceding statement, and the concept of a class being abstract has a well defined meaning that applies to Object.
_ande_turner_
@Ande: How do you figure? Object is useful in and of itself, as other people have shown. How do you figure that it should necessarily be abstract?
Eddie
@Ande: Abstract denotes an class whose definition is incomplete and there for an instance of the class can not be created. This clearly doesn't apply to Object, even if creating instances had no use. And others have pointed out cases where it is useful.
Kris
@Kris: An abstract should define an Abstraction; an Object should be declared abstract because the realworld environment which you are trying to conceptualize cannot instantiate unsubstantive Matter with no Potential.
_ande_turner_
+1  A: 
John Topley
Abstract classes can have non-abstract methods, so I don't see why having native methods would make a difference.
Michael Myers
abstract classes can have native methods... the native methods cannot be abstract though.
TofuBeer
@Ande: You have a feeling? Even though we've just explained that that has nothing to do with it?
Michael Myers
@mmyers: I do indeed. There are no explainations above, only statements... Something against feelings ? lol ... I love the condescention I get here as to my lack of understanding of OOP, but I like to play stupid, people expect less that way. :p
_ande_turner_
I was hoping there was some reason they had to make it non-abstract.
_ande_turner_
Ande there is no reason that they had to make it non-abstract - it was a design choice. Nothing in the language required it to be abstract (well perhaps on the day Object was created there was...)
TofuBeer
+2  A: 

I am not sure this is the reason, but it allows (or allowed, as there are now better ways of doing it) for an Object to be used as a lock:

Object lock = new Object();

....


synchronized(lock)
{
}
TofuBeer
+1  A: 

You never know when you might want to use a simple Object as a placeholder. Think of it as like having a zero in a numerical system (and null doesn't work for this, since null represents the absence of data).

Alan Daniels
There are primitives for counting though. Why drag the concept of Objects into a situation that doesn't warrant their use ?
_ande_turner_
At the veruy beginning Java didn't have primitives (not that I think that matters for this particular discussion).
TofuBeer
@Ande: Alan Daniels is not talking about counting. He's talking about using a placeholder. Primitives won't do this job since, well, they're primitive.
Eddie
@Eddie: Placeholders for what? exactly? Numbers, Values, Symbols ?
_ande_turner_
@Ande, A (common) implementation of *Set (* = some type of Set) is to use *Map and put an Object as the value, using the keys as the Set. You must put *something* as a value, thus, Object. Placeholder. There are places where you cannot use null, but must use some arbitrary Object. Placeholder.
Eddie
@Eddie: You can use an abstract to specify an Object type you wish to leave places for though. Then replace it with any Object which extends that abstract class.
_ande_turner_
+3  A: 

You can instantiate Object for synchronization locks:

Object lock = new Object();

void someMethod() {
  //safe stuff
  synchronized(lock) {
     //some code avoiding race condition
  }
}

void someOtherMethod() {
  //safe code
  synchronized(lock) {
    //some other stuff avoiding race condition
  }
}
Chochos
+2  A: 

How is Object any more offensive than null?

It makes a good place marker (as good as null anyway).

Also, I don't think it would be good design to make an object abstract without an abstract method that needs to go on it.

I'm not saying null is the best thing since sliced bread--I read an article the other day by the "Inventor" discussing the cost/value of having the concept of null... (I didn't even think null was inventable! I guess someone somewhere could claim he invented zero..) just that being able to instantiate Object is no worse than being able to pass null.

Bill K
An instantiation of a non-abstract Object in some senses is an instantiation of null, yet worse because I see arguments for its use. It is a thing with no substance nor abilities, actually perhaps it is useful to represent dark matter, hmm.
_ande_turner_
I've seen it used a lot as a simple lock when no existing object instance made sense. Why does this stress you out so much might be the better question... there are so many more egregious problems in every language out there.
Bill K
"I guess someone somewhere could claim he invented zero." The concept of zero actually was invented. From Wikipedia: "The concept of zero as a number and not merely a symbol for separation is attributed to India where by the 9th century CE practical calculations were carried out using zero"
Davy8
@Ande: Object is not a null. It's a zero-dimensional point, the smallest possible thing you can instantiate. That is very different from null. Why does it bother you that Object can be instantiated, when it is clearly so useful to be able to instantiate Object?
Eddie
@Eddie: The uses listed don't preclude them for being applied to any other instantiated Object extension.
_ande_turner_
+4  A: 

Ande, I think you are approaching this -- pun NOT intended -- with an unnecessary degree of abstraction. I think this (IMHO) unnecessary level of abstraction is what is causing the "problem" here. You are perhaps approaching this from a mathematical theoretical approach, where many of us are approaching this from a "programmer trying to solve problems" approach. I believe this difference in approach is causing the disagreements.

When programmers look at practicalities and how to actually implement something, there are a number of times when you need some totally arbitrary Object whose actual instance is totally irrelevant. It just cannot be null. The example I gave in a comment to another post is the implementation of *Set (* == Hash or Concurrent or type of choice), which is commonly done by using a backing *Map and using the Map keys as the Set. You often cannot use null as the Map value, so what is commonly done is to use a static Object instance as the value, which will be ignored and never used. However, some non-null placeholder is needed.

Another common use is with the synchronized keyword where some Object is needed to synchronize on, and you want to ensure that your synchronizing item is totally private to avoid deadlock where different classes are unintentionally synchronizing on the same lock. A very common idiom is to allocate a private final Object to use in a class as the lock. To be fair, as of Java 5 and java.util.concurrent.locks.Lock and related additions, this idiom is measurably less applicable.

Historically, it has been quite useful in Java to have Object be instantiable. You could make a good point that with small changes in design or with small API changes, this would no longer be necessary. You're probably correct in this.

And yes, the API could have provided a Placeholder class that extends Object without adding anything at all, to be used as a placeholder for the purposes described above. But -- if you're extending Object but adding nothing, what is the value in the class other than allowing Object to be abstract? Mathematically, theoretically, perhaps one could find a value, but pragmatically, what value would it add to do this?

There are times in programming where you need an object, some object, any concrete object that is not null, something that you can compare via == and/or .equals(), but you just don't need any other feature to this object. It exists only to serve as a unique identifier and otherwise does absolutely nothing. Object satisfies this role perfectly and (IMHO) very cleanly.

I would guess that this is part of the reason why Object was not declared abstract: It is directly useful for it not to be.

Eddie
+1, best answer yet.
Michael Myers
I believe that an instantiatable Object allows for idiomatic failures in a programmers comprehension of OOP as a modelling technique. If it was a bug, it is now used as a feature, and if it were not allowed originally better methodologies would now be idiomatic to Java.
_ande_turner_
+1, because whilst we may disagree, I still agree with mmyers. :p
_ande_turner_
@Ande: I do completely agree that were Object abstract, only a few small changes in API would suffice to totally replace an instantiable Object. And were it up to me, I would remove that every object in Java is also a lock and require Lock (or derivative) for synchronization.
Eddie