13

My IDE (NetBeans) type checks my Collections while I am typing code. But then, why do I have to cast the returned object of Object.clone()? Which is fine. No harm no foul. But still, I don't understand.

Is type checking, without casting, the returned object of Object.clone() not possible? The generics framework makes me think the IDE could check the type of object references on the right-side of the "=" mark without casting while I am typing? I don't get it.

addendum
My usage case was just that I had a private Calendar field, pubdate. I was going to write:

Calendar getPubdate() {
    return pubdate;
}

but there is a risk that the invoker could modify my pubdate, so I returned a copy:

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

Then, I wondered why I needed to cast pubdate.clone(). The method signature has the type right there. NetBeans should be able to figure that one out. And NetBeans seemed to be doing something similar with regard to Collections.

10
  • 5
    A short (!) code example would be helpful.
    – Doc Brown
    Commented Mar 15, 2016 at 11:41
  • 78
    The IDE is separate from the language itself, so how smart Netbeans is have no effect on how Java the language works.
    – JacquesB
    Commented Mar 15, 2016 at 11:47
  • 7
    Note, due to return type covariance, it is recommended to return MyObject from clone() rather than Object - this removes this entire issue. It is further recommended never to use clone() (Effective Java Item #11). Commented Mar 15, 2016 at 14:28
  • Is the emphasis of your question on I or on 'cast "clone()"'? Because the question resulting from the former might actually be a much better question than from the latter.
    – user541686
    Commented Mar 16, 2016 at 10:56
  • When I read the question title, the only thing I think of is this.clone() on programmer object, especially at Wed's night after Tue's release. Sorry but I have to write this comment..Why can't smart IDE just fixes all bugs for us LOL Commented Mar 16, 2016 at 12:31

4 Answers 4

54

why do I have to cast the returned object of Object.clone()?

Because it returns Object.

The generics framework makes me think the IDE could check the type of object references on the right-side of the "=" mark without casting while I am typing? I don't get it.

Object.clone is not generic.

If generics had existed when clone was designed, it probably would have looked like this (using F-Bounded Polymorphism):

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

If Java had a MyType feature, it would maybe look like this:

interface Cloneable {
  this clone();
}

But Generics didn't exist when Object.clone was designed, and Java doesn't have MyTypes, so the type-unsafe version of Object.clone is what we have to work with.

10
  • I just realized that the IDE feature that confused me was background compilation? I mean, that is what enables code completion and auto type checking with generics? Personally, I'd prefer delaying type checking until an explicit compile. But I do love code completion.
    – konishiki
    Commented Mar 15, 2016 at 14:17
  • 1
    @konishiki with Java 8 (and to some extent Java 7) type inference, in order to provide any assistance, the IDE needs to infer types. This requires partial compilation. Before type inference, no compilation is needed for autocompletion. Commented Mar 15, 2016 at 14:25
  • @BoristheSpider Thanks so much for that feedback! I definitely need to do some more testing / thinking. very much appreciated.
    – konishiki
    Commented Mar 15, 2016 at 14:33
  • Why would you need to pass original?
    – Clashsoft
    Commented Mar 15, 2016 at 20:22
  • @Clashsoft: Stupid thinko while adapting the obvious Functional Programming version. Thanks. Commented Mar 15, 2016 at 21:24
26

This is not a feature of any IDE, but of the language definition.

An IDE helps you use a programming language more efficiently, it doesn't change the semantics of that language. That means that an editor helper might automatically insert a cast when it's obvious which one you want, but it can't simply break the rules of the language and pretend that code that doesn't compile is valid.

Edit It's true that an IDE can bundle its own compiler, and in fact many do exactly that, e.g. for better error reporting with more inside information into the partial parse tree. However, it would be a very bad idea to let this internal compiler implement different language semantics than the official SDK, since that would mean that code that works in development can mysteriously start failing when installed in production - producing problems that are by definition un-debuggable!

4
  • This is what happened: I'm pretty sure code completion is an IDE feature (done via reflection). And the auto type checking I was talking about happens in the IDE (via background compilation). I hope that is what is going on.
    – konishiki
    Commented Mar 15, 2016 at 12:38
  • 1
    The IDE can very easily break all the rules of the language spec and just compile the code anyways. I know both NetBeans and Eclipse use their own compilers, for example. So in those cases IDE and compiler are effectively the same thing. Not saying it's a good idea, but C compilers certainly do it all the time.
    – MichaelS
    Commented Mar 15, 2016 at 13:34
  • @MichaelS The C language specification is designed to allow significant variation between implementations, so that different vendors can choose between different possible approaches and add extra features. This creates various areas of ambiguity in the specification, which are necessary to allow those variations. The name "C" is not trademarked, so nobody controls the use of the term. The Java specification is designed to eliminate as much ambiguity as possible, and Java is trademarked and the trademark holder enforces that it can only be used in compliant implementations.
    – Jules
    Commented Mar 15, 2016 at 20:20
  • Modern IDE's need a compiler anyway. Code completion hints require that the code before the cursor is parsed. And certainly with generics (or C++ templates) that requires a full compiler, not just a parser.
    – MSalters
    Commented Mar 16, 2016 at 11:35
3

It is due to the type signature of the Object.clone method. The type signature states that the method will return an object of type Object.

protected Object clone() throws CloneNotSupportedException

The collections will use so called generic types to substitute the type of casting automatically.

So if you have this code:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

the compiler will add the casts for you behind the scenes, so the code would actually be:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);
0

For completeness, since Java 5, covariant return types are allowed. So you can write the following:

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

With this, the following code is legal:

MyObject original = new MyObject();
MyObject clone = original.clone();

Not the answer you're looking for? Browse other questions tagged or ask your own question.