S2975: For a final class, it should be allowed to leave out super.clone()

I am using Eclipse SonarLint 4.3.12432.

I get squid:S2975, when I use the private copy constructor of my final class in clone().

public final class FinalClass implements Cloneable {
    public FinalClass() {}
    public FinalClass(FinalClass base) {}
    @Override public FinalClass clone() {
        return new FinalClass(this);  // NOSONAR false-positive squid:S2975
    }
}

Hi,

  • I don’t see you are using private copy constructor (I see only 2 public constructors)
  • If having copy constructor why having also clone?

This rule might not necessarily report the problem in your code, but some location which might lead to the problem in the future.

If you believe you are safe and there is no sense in refactoring your code, it’s ok.
Still I don’t see a consistent pattern this rule should avoid.

Hi,

Sorry, it’s a mistake, the second constructor is private:

private FinalClass(FinalClass base) {}

But my problem is independent of this. I think, the super.clone() requirement shouldn’t be applied to non-final classes. Or, is there a sane reason?

So, is the final class modifier a consistent pattern when this rule should avoid?

Hello @davidsusu,

Before digging into the problem, I want to say that the information you gave us is quite sparse, I had to extrapolate a lot. The problem discussed is interesting, and you should motivate a bit more your suggestions.

The confusion comes from the fact that you state rule S2975, but it seems to me that you are in fact discussing rule S1182.

Without this confusion, the problem is clearer: one of the concern of this rule is that if you extend a class defining clone() without a call to super.clone(), you are likely to violate the invariant #2: x.clone().getClass() == x.getClass(). If the class is final though, you are not subject to this problem.

What worries me at this point is that super.clone() is not here only for invariant #2, have you though about how it could affect them?

In addition, could you explain me why you have the need for both a clone and a copy constructor? From my point of vue, a copy constructor is here exactly to avoid all the problems of clone.

You are right, now I see that this is S1182. Hm, probably, there was something wrong with the problem view in Eclipse, sorry.

There are several reasons for using clone() instead of a constructor or static copy method. The three most important are:

  • using in a generic context, e. g. T item = item.clone() (where <T extends Cloneable>)
  • method chaining
  • the name ‘clone’ is semantic/explicit

Of course, all of these can be replaced by other patterns, but, at least for me, clone() seems to be the simplest solution.