Why java.lang.Object is not abstract? [duplicate]
Asked Answered
N

14

137

Possible Duplicate:
Java: Rationale of the Object class not being declared abstract

Why is the Object class, which is base class of 'em all in Java, not abstract?

I've had this question for a really really long time and it is asked here purely out of curiosity, that's all. Nothing in my code or anybody's code is breaking because it is not abstract, but I was wondering why they made it concrete?

Why would anyone want an "instance" (and not its presence a.k.a. Reference) of this Object class? One case is a poor synchronization code which uses the instance of an Object for locking (at least I used it this way once.. my bad).

Is there any practical use of an "instance" of an Object class? And how does its instantiation fit in OOP? What would have happened if they had marked it abstract (of course after providing implementations to its methods)?

Nepenthe answered 22/1, 2010 at 14:4 Comment(6)
+1, it immediately made me think of the same question, but in respect to .NET-based languagesEmee
There seems to be a lot of confusion about the question; abstract classes do not need to have abstract methods. Rather, the question is asking "Is there any real reason we need to be able to do new Object();?" If not, Object should be abstract.Aloke
The flipside, and IMO the better question to ask, is: "Is there any real need Object should be abstract?" There isn't. So it should be concrete.Handal
The intent behind asking this question was precisely to find the reasons of making it concrete, as you need a reason to make a class abstract so do you to make it concrete, right? As for the question as to need of Object being abstract; one answer is: we are interested in Object class for the behavior it adds to subclasses and its special Super-Most base class role in inheritance. I couldn't find any use of this class's instance. If String is final for good reason so there must be a good reason why Object is non-abstract other than just they can make it non-abstract right? right?Nepenthe
+1 it is a very good question. The only correct answer can come from the designers, we can only offer our opinion. And if we're all just giving our opinion on why it's abstract, I don't think we'll ever agree, but it is fun!Twofaced
This is some of the most fundamental stuff in the Java world so it was designed very early with very little experience to build on, and the Java tradtition of not breaking existing code meant that the initial design decision stayed regardless of whether it was a good idea or not.Ketron
T
68

Without the designers of java.lang.Object telling us, we have to base our answers on opinion. There's a few questions which can be asked which may help clear it up.

Would any of the methods of Object benefit from being abstract?

It could be argued that some of the methods would benefit from this. Take hashCode() and equals() for instance, there would probably have been a lot less frustration around the complexities of these two if they had both been made abstract. This would require developers to figure out how they should be implementing them, making it more obvious that they should be consistent (see Effective Java). However, I'm more of the opinion that hashCode(), equals() and clone() belong on separate, opt-in abstractions (i.e. interfaces). The other methods, wait(), notify(), finalize(), etc. are sufficiently complicated and/or are native, so it's best they're already implemented, and would not benefit from being abstracted.

So I'd guess the answer would be no, none of the methods of Object would benefit from being abstract.

Would it be a benefit to mark the Object class as abstract?

Assuming all the methods are implemented, the only effect of marking Object abstract is that it cannot be constructed (i.e. new Object() is a compile error). Would this have a benefit? I'm of the opinion that the term "object" is itself abstract (can you find anything around you which can be totally described as "an object"?), so it would fit with the object-oriented paradigm. It is however, on the purist side. It could be argued that forcing developers to pick a name for any concrete subclass, even empty ones, will result in code which better expresses their intent. I think, to be totally correct in terms of the paradigm, Object should be marked abstract, but when it comes down to it, there's no real benefit, it's a matter of design preference (pragmatism vs. purity).

Is the practice of using a plain Object for synchronisation a good enough reason for it to be concrete?

Many of the other answers talk about constructing a plain object to use in the synchronized() operation. While this may have been a common and accepted practice, I don't believe it would be a good enough reason to prevent Object being abstract if the designers wanted it to be. Other answers have mentioned how we would have to declare a single, empty subclass of Object any time we wanted to synchronise on a certain object, but this doesn't stand up - an empty subclass could have been provided in the SDK (java.lang.Lock or whatever), which could be constructed any time we wanted to synchronise. Doing this would have the added benefit of creating a stronger statement of intent.

Are there any other factors which could have been adversely affected by making Object abstract?

There are several areas, separate from a pure design standpoint, which may have influenced the choice. Unfortunately, I do not know enough about them to expand on them. However, it would not suprise me if any of these had an impact on the decision:

  • Performance
  • Security
  • Simplicity of implementation of the JVM

Could there be other reasons?

It's been mentioned that it may be in relation to reflection. However, reflection was introduced after Object was designed. So whether it affects reflection or not is moot - it's not the reason. The same for generics.

There's also the unforgettable point that java.lang.Object was designed by humans: they may have made a mistake, they may not have considered the question. There is no language without flaws, and this may be one of them, but if it is, it's hardly a big one. And I think I can safely say, without lack of ambition, that I'm very unlikely to be involved in designing a key part of such a widely used technology, especially one that's lasted 15(?) years and still going strong, so this shouldn't be considered a criticism.

Having said that, I would have made it abstract ;-p

Summary
Basically, as far as I see it, the answer to both questions "Why is java.lang.Object concrete?" or (if it were so) "Why is java.lang.Object abstract?" is... "Why not?".

Twofaced answered 22/1, 2010 at 15:30 Comment(14)
The methods themselves would not have to be abstract - the point of making the class abstract is that you cannot call new Object() in code. The question is, is there really a need to every have to instantiate an Object object? Though I agree with you that the hashCode/clone thing is not best, it's not really related to the question.Aloke
Mentioning hashCode/clone was to help get an idea of which methods would benefit from being abstract, and the answer IMO turns out to be none, so I do think it is related. Good point about not being able to new up an Object, added some information about that.Twofaced
+1 for being interesting things to thing about, if nothing else.Literature
The default hashCode is so bloody useful.Borst
@Joshua: I'm not sure if you're being sarcastic, but I'll respond as though you weren't. If you were, then this is me explaining your joke :-p The default hashCode only works if you don't override equals, and the only application that it has is for correct interaction with hash based collections (e.g. Hashtable). To me, that's a poor separation of concerns, particularly for the base-iest of all base classes. Back then it probably saved a lot of time for people, but today, if you're writing hashCode methods by hand, You're Doing It Wrong (tm).Twofaced
@Grundlefleck: I'm being serious. By explicitly calling it I can get a copy of the object reference in an integer. This comes in handy when trying to debug who munged your singleton (which for me turned out to be the guy who restarted the JVM in the same PID so my other tool didn't notice).Borst
@Joshua: interesting use-case! However, as far as I can tell, there's no requirement that the method had to belong to Object. If it can be done in Object, surely it could be somewhere else i.e. in System with public static int memoryLocationOf(Object toLocate). In fact, having it that way would be a benefit - you don't lose the ability to get the memory location just because you wanted to override equals. Unless there already exists a way to get this without hashCode?Twofaced
Just thought I'd come back here to say that the hypothetical memoryLocationOf() method I talked about in the comments exists, as System.identityHashCode(Object x).Twofaced
You can generate an object that has a different class from anything else using new Object() {}.Eldwin
@Grundlefleck: It is possible to define at least two equivalence relations which would allow one to meaningfully compare any class object to any other (if an instance of Apple is asked it it's equal to an instance of Orange, it shouldn't complain; it should simply say it's not equal). The reason the semantics of equals and hashCode seem murky is that objects are forced to override one set of equivalence methods to define the relation they think the caller will want, rather than letting the caller specify which of the two relations is of interest (note that it's possible for...Pyralid
...consumers of an object instance to be interested in equivalence relation at some times, and the other relation at other times). FYI, one relation considers X and Y equivalent if replacement of any arbitrary combination of references to Y with references to X would not be expected to change semantics. The other considers them equivalent if swapping all references to X with references to Y, and vice versa, would not be affected to change semantics. The first effectively tests permanent equivalence; the second effectively tests state equivalence.Pyralid
@Twofaced Your statement regarding equals and hashCode that says This would require developers to figure out how they should be implementing them, making it more obvious that they should be consistent is not a good enough reason to make equals and hashCode abstract. A typical application contains different kinds of classes. Classes that contain business logic, class that dispatch control from one part of the application to another, etc. Such classes will not be added to a hashed Collection nor will they need to be checked for equality. equals and hashcode are optional.Disquisition
@CKing: not sure I understand your point. My opinion is that these methods should be on opt-in interfaces, for precisely the reason you mention -- not every class is hashed/checked for equality. Could you elaborate a bit, to help me understand?Twofaced
@Twofaced My bad. I may have jumped to a conclusion without reading your point about opt-in abstractions. However, making equals a part of Object allows programmers to always program to an interface by always using equals even when they are checking if two references point to the same object. If they change their mind later about what equality means to them, they can override equals without changing client code.Disquisition
H
24

Plain instances of java.lang.Object are typically used in locking/syncronization scenarios and that's accepted practice.

Also - what would be the reason for it to be abstract? Because it's not fully functional in its own right as an instance? Could it really do with some abstract members? Don't think so. So the argument for making it abstract in the first place is non-existent. So it isn't.

Take the classic hierarchy of animals, where you have an abstract class Animal, the reasoning to make the Animal class abstract is because an instance of Animal is effectively an 'invalid' -by lack of a better word- animal (even if all its methods provide a base implementation). With Object, that is simply not the case. There is no overwhelming case to make it abstract in the first place.

Handal answered 22/1, 2010 at 14:9 Comment(19)
Sounds like a hack to meAloke
@BlueRaja please explain why synchronizing on a good old private final Object might be a hack?Bubal
Nit-picking here but I believe there's a slightly lower overhead if you use a byte[0] instead of an Object as your lock.Waldack
@Adamski: what is that belief based on?Fondle
If that is the only reason that Objects are not abstract, it is definitely a hack; why not create a Mutex object in the API?Aloke
Because any object can act as a mutex in Java, there's no reason to have a dedicated class for it.Animatism
@BlueRaja And still you have not explained why it would be a 'hack'.Handal
@Michael: Creating an Object generates slightly more bytecode than using a byte[0]. Obviously the difference is fairly trivial.Waldack
@Wim: I meant that it would be a hack in the case of the designers - if their intention in making Objects non-abstract was truly just so they they could be used as synchronization objects, the designers should have just made a dedicated synchronization object for that purpose. I still see no reason why Object should be non-abstract.Aloke
Hack or not, unless the language designers say "We made Object concrete so that it could be used in synchronisation", this can't really be a correct answer. Just because people eventually used it for synchronisation does not mean that is why it was made concrete. That's how I see it anyway.Twofaced
I did not say that that is the reason why Object was made concrete. Just that using it for said scenarios is very common and well accepted practice.Handal
@Waldack um, a byte[0] is an Object, it supports all the methods of Java.lang.Object and has a length field that needs to be initialized. I don't see how it could possibly result in less overhead.Fondle
@Wim: I know, but that is not what's being asked.Aloke
There we nowadays have java.util.concurrent.locks.Lock for.Castaway
@Wim, I understand that, but the question is not "What are the common and accepted uses for using a plain java.lang.Object?". If it were, you would be spot on and getting a +1 from me :-). But as the answer is, I don't see it as a +1 (not decided if it merits a -1 though).Twofaced
Or to use what now surely has to be considered a cliche - correlation does not imply causation. :-pTwofaced
@Michael - Try generating two classes: One which creates an Object() in it's main() method and the other which creates byte[0] and then open the byte code in a byte code editor: You'll see there's an additional overhead with Object() in calling the initializer.Waldack
+1 Without comment from the designers "There is no benefit to it being abstract" seems much more plausible to me. Even though I may disagree that there is no benefit...Twofaced
... I question your Animal analogy. Can you find or think of anything that is totally described by the term 'Object'? I think Animal and Object are the same in that regard - they are both abstract terms. It's not that there is no argument for it being abstract, it's just that there's a paradigm concept vs. pragmatic language mechanics argument.Twofaced
A
12

From everything I've read, it seems that Object does not need to be concrete, and in fact should have been abstract.

Not only is there no need for it to be concrete, but after some more reading I am convinced that Object not being abstract is in conflict with the basic inheritance model - we should not be allowing abstract subclasses of a concrete class, since subclasses should only add functionality.
Clearly this is not the case in Java, where we have abstract subclasses of Object.

Aloke answered 22/1, 2010 at 15:24 Comment(16)
@BlueRaja All well and good laying into me for not quite answering a question, but how does your response provide an answer to the question:"Why is Object not abstract?", and with it, most of the other answers on here too.Handal
@Wim: There doesn't seem to be a real answer to that question, other than "It was a design mistake;" hence the "Object should have been abstract."Aloke
@Wim: Because I also replied to your answer, I'm assuming you thought I was "laying into you" as well. Please note that I've no interest in attacking people personally, I just want to see the best quality answers on the site, and I'm doing that by questioning your answer. There was no ill-will, or "laying into" intended. I obviously can't speak for BlueRaja, but it seems to me he was only doing the same.Twofaced
we should not be allowing abstract subclasses of a concrete class. Why?Yorktown
I don't see how extending a concrete class with an abstract class violates the idea of adding functionality. I could have a concrete class A which provides 4 functions, then extend it with class B which provides 1 more function, but that function is abstract because there can be different implementations for different subclasses. Like, Employee is concrete and has functions like recordHoursWorked and enrollInRetirementPlan. Then I extend it with Salesman which has calculateCommission, but this is abstract because we have subclasses of Salesman who have different commission rules.Mayonnaise
@Twofaced No, it's fine, I understand. I was reading too much into it, I'm sure BlueRaja also didn't mean it like that. I shouldn't have used such emotive terminology. ;-)Handal
@Jay: Using is-a terminology, if A is a concrete thing, and B is-a A, then it should follow to reason that B is a concrete thing. If you are extending A to a B with added methods which aren't implemented, then 99/100 times what you really want is an interface (the other 1/100, what you really want is to push the methods up to A and make A abstract).Aloke
I personally don't see "does not need to be concrete" == "in fact should have been abstract." Also, the link you provided simply says "it should have been" and then goes on to discuss what other sorts of things could be done when it is decided that it is abstract. That reference you provided really doesn't seem to provide any sort of support to your argument. So I agree with "It doesn't need to be concrete" but I sill would like to see some reason why it should be abstract. I have yet to see any defects arise from someone accidentally creating an Object. How would it benefit?Theron
@Andrew: one possible drawback from instantiating an Object type is that the type does not communicate intent at all. Granted variable/method names will do the job, but I reckon I could find a decent, real-world example of this if I looked. I'm still seeing a fine line between "doesn't need to be concrete" == "should have been abstract", I guess it would come down to taste :-)Twofaced
@BlueRaja: Fine, let's use "is a" terminology. Salesman is an Employee. FullTimeSalesman is a Salesman. PartTimeSalesman is a Salesman. Salesman is abstract because it has methods which can only be implemented at the FullTime/PartTime level. How does that violate the "is a" concept? I am adding functionality at each level. The fact that at one level we create a duality which is not resolved until the next level seems completely legitimate to me. (continued ...)Mayonnaise
Now, if someone said that Employee has a concrete function, and that salesman makes this same function abstract, then you would be taking away information. (I don't think that's possible to do in Java, but whatever.) But if Salesman adds an abstract function that is not implemented until we get to FullTimeSalesman and PartTimeSalesman, no information has been subtracted at any step.Mayonnaise
@Jay: If I were designing that, I'd make Employee abstract and Salesman concrete; full-time/part-time status would be a property of Employee. If there were enough other types of Employees who collect commission, I'd either create an abstract CommissionEmployee class, or an ICollectsCommission interface, depending on how (dis)similar the algorithms for calculating commission were.Aloke
@BlueRaja: My assumptions in constructing the example were: (a) There are employees wo are not salesmen (a not unreasonable assumption) and who we do not need to further distinguish, so that Employee must be concrete. (b) The fulltime/parttime distinction is only relevant in our system when calculating commissions, and so only applies to salesman. If you're going to insist that all employees could be classified as FT or PT, okay, fine, make it "Retail Salesman" and "Wholesale Salesman" if you prefer. (continued ...)Mayonnaise
In any case, if the question is, "Could I come up with a solution that does not violate your 'abstract cannot extend concrete' rule, even if it is more complex and unnatural than other possible solutions?" I'm sure the answer is "Yes". But why would you want to? This gets back to my original question: What purpose does such a rule serve? Why is it a good rule that we would even want to consider following?Mayonnaise
@Jay: I would want to because the design is cleaner; that is why the abstract keyword exists (like final)Aloke
It doesn't make the design any cleaner, and it certainly is not why the abstract keyword exists.Yorktown
Z
11

I can think of several cases where instances of Object are useful:

  • Locking and synchronization, like you and other commenters mention. It is probably a code smell, but I have seen Object instances used this way all the time.
  • As Null Objects, because equals will always return false, except on the instance itself.
  • In test code, especially when testing collection classes. Sometimes it's easiest to fill a collection or array with dummy objects rather than nulls.
  • As the base instance for anonymous classes. For example:
    Object o = new Object() {...code here...}
Zoie answered 22/1, 2010 at 14:21 Comment(2)
"As the base instance for anonymous classes." -> this can also be done when Object is abstractCarmelocarmen
All very valid points, but all can be done as good other ways when Object is abstract.Castaway
H
7

I think it probably should have been declared abstract, but once it is done and released it is very hard to undo without causing a lot of pain - see Java Language Spec 13.4.1:

"If a class that was not abstract is changed to be declared abstract, then preexisting binaries that attempt to create new instances of that class will throw either an InstantiationError at link time, or (if a reflective method is used) an InstantiationException at run time; such a change is therefore not recommended for widely distributed classes."

Hayrack answered 22/1, 2010 at 15:50 Comment(2)
Interesting. Was this addition in reference to discussion about making Object abstract, or a general point?Twofaced
IIRC this is just part of a chapter with general binary compatibility advice.Nickola
S
5

From time to time you need a plain Object that has no state of its own. Although such objects seem useless at first sight, they still have utility since each one has different identity. Tnis is useful in several scenarios, most important of which is locking: You want to coordinate two threads. In Java you do that by using an object that will be used as a lock. The object need not have any state its mere existence is enough for it to become a lock:

class MyThread extends Thread {
   private Object lock;
   public MyThread(Object l) { lock = l; }

   public void run() { 

      doSomething();
      synchronized(lock) {
          doSomethingElse();
      } 
   }
}

Object lock = new Object();
new MyThread(lock).start();
new MyThread(lock).start();

In this example we used a lock to prevent the two threads from concurrently executing doSomethingElse()

If Object were abstract and we needed a lock we'd have to subclass it without adding any method nor fields just so that we can instantiate lock.

Coming to think about it, here's a dual question to yours: Suppose Object were abstract, will it define any abstract methods? I guess the answer is No. In such circumstances there is not much value to defining the class as abstract.

Stibine answered 22/1, 2010 at 14:16 Comment(4)
Hmm... Wouldn't you be better off using the new java.util.concurrent stuff these daysMonopolize
Do you know of any evidence that is the reason Object is not abstract? Sure, it was useful, but did it cause the original decision to make it concrete?Twofaced
"If Object were abstract and we needed a lock we'd have to subclass it without adding any method nor fields just so that we can instantiate lock." - Yes, but this could be done once, in the SDK, so you use the java.lang.Lock (or whatever) object, and you're better expressing your intent. It's not like everyone would have to make a new empty class every single time they wanted to synchronise a lock.Twofaced
@Grundlefleck: One disadvantage of making Object concrete is that it forces every object to expose its identity to the outside world; from an OOP perspective, if code says ImmutablePoint foo1 = ImmutablePoint.Create(3,4), foo2 = ImmutablePoint.Create(3,4); there's no particular reason outside code should be able to tell whether foo1 and foo2 are distinct instances of ImmutablePoint. If things like synchronized only worked with types that implement IdentifiableByReference, the abstraction that immutable objects encapsulating the same data are indistinguishable could be upheld.Pyralid
F
5

I don't understand why most seem to believe that making a fully functional class, which implements all of its methods in a use full way abstract would be a good idea.
I would rather ask why make it abstract? Does it do something it shouldn't? is it missing some functionality it should have? Both those questions can be answered with no, it is a fully working class on its own, making it abstract just leads to people implementing empty classes.

public class UseableObject extends AbstractObject{}

UseableObject inherits from abstract Object and surprise it can be implemented, it does not add any functionality and its only reason to exist is to allow access to the methods exposed by Object.
Also I have to disagree with the use in "poor" synchronisation. Using private Objects to synchronize access is safer than using synchronize(this) and safer as well as easier to use than the Lock classes from java util concurrent.

Figurative answered 22/1, 2010 at 18:14 Comment(3)
In response to "Why make it abstract?" I would say, because it doesn't mean anything to be "an object". In fact, the word 'object' is an abstract term. What I mean is, if you look around, there will be nothing you can find which you can completely describe as "an object", there will always be a concrete term for a concrete thing. I guess it's a trade off between the pragmatism of allowing something that can be useful but doesn't really make sense vs. the precise idea of the paradigm. It doesn't make a huge difference, but it is fun to think about :)Twofaced
@Twofaced they could have called it MinimalJavaObject then it would describe the minimal implemation of any Object in java, which is something concrete, but I have to agree that there certainly was a tradeof for pragmatism, I have jet to see a flawless programming language:).Figurative
hmmmm, I suppose that does make sense.Twofaced
M
3

Seems to me there's a simple question of practicality here. Making a class abstract takes away the programmer's ability to do something, namely, to instantiate it. There is nothing you can do with an abstract class that you cannot do with a concrete class. (Well, you can declare abstract functions in it, but in this case we have no need to have abstract functions.) So by making it concrete, you make it more flexible.

Of course if there was some active harm that was done by making it concrete, that "flexibility" would be a drawback. But I can't think of any active harm done by making Object instantiable. (Is "instantiable" a word? Whatever.) We could debate whether any given use that someone has made of a raw Object instance is a good idea. But even if you could convince me that every use that I have ever seen of a raw Object instance was a bad idea, that still wouldn't prove that there might not be good uses out there. So if it doesn't hurt anything, and it might help, even if we can't think of a way that it would actually help at the moment, why prohibit it?

Mayonnaise answered 22/1, 2010 at 23:17 Comment(0)
L
2

I think all of the answers so far forget what it was like with Java 1.0. In Java 1.0, you could not make an anonymous class, so if you just wanted an object for some purpose (synchronization or a null placeholder) you would have to go declare a class for that purpose, and then a whole bunch of code would have these extra classes for this purpose. Much more straight forward to just allow direct instantiation of Object.

Sure, if you were designing Java today you might say that everyone should do:

 Object NULL_OBJECT = new Object(){};

But that was not an option in 1.0.

Lancinate answered 22/1, 2010 at 17:0 Comment(0)
C
1

I suspect the designers did not know in which way people may use an Object may be used in the future, and therefore didn't want to limit programmers by enforcing them to create an additional class where not necessary, eg for things like mutexes, keys etc.

Calv answered 22/1, 2010 at 16:25 Comment(0)
G
0

It also means that it can be instantiated in an array. In the pre-1.5 days, this would allow you to have generic data structures. This could still be true on some platforms (I'm thinking J2ME, but I'm not sure)

Gharry answered 22/1, 2010 at 14:25 Comment(1)
You could have, say, a generic array of type Object[] even if Object were abstract - you'd just need to fill it with Object-subtypes.Aloke
C
-4

Reasons why Object needs to be concrete.

  1. reflection
    see Object.getClass()

  2. generic use (pre Java 5)

  3. comparison/output
    see Object.toString(), Object.equals(), Object.hashCode(), etc.

  4. syncronization
    see Object.wait(), Object.notify(), etc.

Even though a couple of areas have been replaced/deprecated, there was still a need for a concrete parent class to provide these features to every Java class.

The Object class is used in reflection so code can call methods on instances of indeterminate type, i.e. 'Object.class.getDeclaredMethods()'. If Object were to be Abstract then code that wanted to participate would have to implement all abstract methods before client code could use reflection on them.

According to Sun, An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed. This also means you can't call methods or access public fields of an abstract class.

Example of an abstract root class:

abstract public class AbstractBaseClass
{
    public Class clazz;

    public AbstractBaseClass(Class clazz)
   {
       super();
       this.clazz = clazz;
   }
}

A child of our AbstractBaseClass:

public class ReflectedClass extends AbstractBaseClass  
{
    public ReflectedClass() 
    {
       super(this);
    }

    public static void main(String[] args)  
    {
        ReflectedClass me = new ReflectedClass();
    }
}

This will not compile because it's invalid to reference 'this' in a constructor unless its to call another constructor in the same class. I can get it to compile if I change it to:

   public ReflectedClass()
   {
       super(ReflectedClass.class);
   }  

but that only works because ReflectedClass has a parent ("Object") which is 1) concrete and 2) has a field to store the type for its children.

A example more typical of reflection would be in a non-static member function:

public void foo()
{
    Class localClass = AbstractBaseClass.clazz;  
}

This fails unless you change the field 'clazz' to be static. For the class field of Object this wouldn't work because it is supposed to be instance specific. It would make no sense for Object to have a static class field.

Now, I did try the following change and it works but is a bit misleading. It still requires the base class to be extended to work.

public void genericPrint(AbstractBaseClass c)
{
    Class localClass = c.clazz;
    System.out.println("Class is: " + localClass);
}

public static void main(String[] args)
{
    ReflectedClass me = new ReflectedClass();
    ReflectedClass meTwo = new ReflectedClass();

    me.genericPrint(meTwo);
}

Pre-Java5 generics (like with arrays) would have been impossible

Object[] array = new Object[100];
array[0] = me;
array[1] = meTwo;

Instances need to be constructed to serve as placeholders until the actual objects are received.

Cotidal answered 22/1, 2010 at 15:1 Comment(14)
Wouldn't they have to implement all abstract methods before they would even compile?Twofaced
Once again, just because the class itself is abstract does not mean the methods have to be. See the comments to girinie's answer.Aloke
@BlueRaja, The point isn't about what has to be implemented, it is that you wouldn't be able to call Object.class as long as there were unimplemented abstract methods. The choice is Object be concrete or every class that wants to participate in reflection would have to provide implementations for any abstract methods. In other words, reflection is one of the reasons Object is not abstract.Cotidal
@Kelly, I still don't understand your point. How is 'participate in reflection' different from 'can be compiled'? I'm not too familiar with reflection, so that's maybe why I can't connect the dots. How do subclasses affect calls to Object.class.getDeclaredMethods()? Surely they just return methods which have the abstract flag set on them?Twofaced
@Kelly: "would have to provide implementations for any abstract methods." - There wouldn't be any abstract methodsAloke
@BlueRaja: An abstract class with no abstract methods? The question is asking why Object isn't abstract. The focus on the language rules around implementing an abstract class seem to miss the point of the question.Cotidal
@Kelly: ....yes, exactly. Since there would be no abstract method, saying "the client would have to implement all abstract methods before they could use reflection" is a moot point; reflection would work just the same.Aloke
@Grundlefleck: If you had to implement any unimplemented abstract methods from Object before your classes could be used with reflection, you wouldn't bother. For reflection to be universal, there needs to be a parent class that can be instantiated so methods can be called on it. This rules out java.lang.Object being an abstract base class.Cotidal
You might want to check the @since on .class. Class objects (and reflection in general) were added in the 1.1 release, well after the design decision to make Object concrete.Loge
@Kelly: that's the point I'm not getting, is it so you don't need to know the exact type? Forgetting that for a minute, has reflection been available since java.lang.Object was written? If that isn't the case then this is all moot :)Twofaced
@Kelly: there's parts of your code that doesn't work for different reasons than you seem to think. ReflectedClass can't call super(this) because this is not of type Class. Try super(this.getClass()). Also, you can't reference AbstractBaseClass.clazz because the field is not declared static and you're trying to reference it through the class rather than an instance. If you had an instance, you would be able to reference the field i.e. instanceOfSubclass.clazz. Or am I missing something?Twofaced
@Grundlefleck: Thanks for the corrections. I had moved the AbstractBaseClass.clazz into a non-static method but that didn't come across in my edit. I'll fix that. As for super(this) what I'm trying to get at is more the fact that Object has methods you can call without needed to subclass it, which only works because it is concrete. The array example at the end may be a better case for that. The comment about referencing the field through an instance is correct, it works because I had created an instance but there are places where Object.someMethod() is used without an instance.Cotidal
@Kelly: "... there are places where Object.someMethod() is used without an instance" I'm still lost, because it's valid to declare a static (but not abstract) method on an abstract class and it will work no problem. As for the array example, why do you need to have placeholders at all, why not just leave the position empty until you receive the object?Twofaced
@Alex: Thanks for the reference. I'll stop making a fool of myself and edit this answer to say "This is NOT why Object is abstract. This message will self-destruct in 3, 2, 1, +++AT0+++Cotidal
T
-6

I suspect the short answer is that the collection classes lost type information in the days before Java generics. If a collection is not generic, then it must return a concrete Object (and be downcast at runtime to whatever type it was previously).

Since making a concrete class into an abstract class would break binary compatibility (as noted upthread), the concrete Object class was kept. I would like to point out that in no case was it created for the sole purpose of sychronization; dummy classes work just as well.

The design flaw is not including generics from the beginning. A lot of design criticism is aimed at that decision and its consequences. [oh, and the array subtyping rule.]

Tardigrade answered 22/1, 2010 at 16:50 Comment(4)
"If a collection is not generic, then it must return a concrete Object" - I do not understand this comment. A collection can hold/return abstract types, it just cannot - and doesn't need to - instantiate them (thus all "instances" of the abstract-type are actually instances of a subtype). This is the way it's always worked.Aloke
-1, collection classes don't need to return concrete Objects, they return other objects (e.g. Strings) cast to Object.Volga
Even with generics, and because of type erasure don't collections sill lose type information???Theron
+1 Andrew's comment - generic types are for the compiler, there is no run time information about the types. And as far as I know, the downcasting still happens (the compiler inserts the casts and ensures they're safe). But, collections can return an abstract type, I don't think the abstract vs. concrete makes a difference for collections. In fact, did the Collections classes exist when Object was written? Binary compatibility is the reason why it can't change now, not the reason why it was designed like that to begin with.Twofaced
M
-9

Its not abstract because whenever we create a new class it extends Object class then if it was abstract you need to implement all the methods of Object class which is overhead... There are already methods implemented in that class...

Manymanya answered 22/1, 2010 at 14:24 Comment(5)
You only need to reimplement abstract methods, not every method.Gaitan
Hmm.... this question has brought out some very basic misunderstandings of what an abstract class is....Animatism
Only abstract methods need to be overriden/implemented, not all methods of an abstract class.Wish
I mean to say the methods which are abstract..I need to implementManymanya
yeah, but you could make Object abstract without making ANY of its methods abstract.Phene

© 2022 - 2024 — McMap. All rights reserved.