| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| NoCloneCheck |
|
| 1.0;1 |
| 1 | //////////////////////////////////////////////////////////////////////////////// | |
| 2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
| 3 | // Copyright (C) 2001-2014 Oliver Burn | |
| 4 | // | |
| 5 | // This library is free software; you can redistribute it and/or | |
| 6 | // modify it under the terms of the GNU Lesser General Public | |
| 7 | // License as published by the Free Software Foundation; either | |
| 8 | // version 2.1 of the License, or (at your option) any later version. | |
| 9 | // | |
| 10 | // This library is distributed in the hope that it will be useful, | |
| 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 | // Lesser General Public License for more details. | |
| 14 | // | |
| 15 | // You should have received a copy of the GNU Lesser General Public | |
| 16 | // License along with this library; if not, write to the Free Software | |
| 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 18 | //////////////////////////////////////////////////////////////////////////////// | |
| 19 | package com.puppycrawl.tools.checkstyle.checks.coding; | |
| 20 | ||
| 21 | /** | |
| 22 | * <p> | |
| 23 | * Checks that the clone method is not overridden from the | |
| 24 | * Object class. | |
| 25 | * </p> | |
| 26 | * | |
| 27 | * <p> | |
| 28 | * Rationale: The clone method relies on strange/hard to follow rules that | |
| 29 | * do not work it all situations. Consequently, it is difficult to | |
| 30 | * override correctly. Below are some of the rules/reasons why the clone | |
| 31 | * method should be avoided. | |
| 32 | * | |
| 33 | * <ul> | |
| 34 | * <li> | |
| 35 | * Classes supporting the clone method should implement the Cloneable | |
| 36 | * interface but the Cloneable interface does not include the clone method. | |
| 37 | * As a result, it doesn't enforce the method override. | |
| 38 | * </li> | |
| 39 | * <li> | |
| 40 | * The Cloneable interface forces the Object's clone method to work | |
| 41 | * correctly. Without implementing it, the Object's clone method will | |
| 42 | * throw a CloneNotSupportedException. | |
| 43 | * </li> | |
| 44 | * <li> | |
| 45 | * Non-final classes must return the object returned from a call to | |
| 46 | * super.clone(). | |
| 47 | * </li> | |
| 48 | * <li> | |
| 49 | * Final classes can use a constructor to create a clone which is different | |
| 50 | * from non-final classes. | |
| 51 | * </li> | |
| 52 | * <li> | |
| 53 | * If a super class implements the clone method incorrectly all subclasses | |
| 54 | * calling super.clone() are doomed to failure. | |
| 55 | * </li> | |
| 56 | * <li> | |
| 57 | * If a class has references to mutable objects then those object | |
| 58 | * references must be replaced with copies in the clone method | |
| 59 | * after calling super.clone(). | |
| 60 | * </li> | |
| 61 | * <li> | |
| 62 | * The clone method does not work correctly with final mutable object | |
| 63 | * references because final references cannot be reassigned. | |
| 64 | * </li> | |
| 65 | * <li> | |
| 66 | * If a super class overrides the clone method then all subclasses must | |
| 67 | * provide a correct clone implementation. | |
| 68 | * </li> | |
| 69 | * </ul> | |
| 70 | * </p> | |
| 71 | * | |
| 72 | * <p> | |
| 73 | * Two alternatives to the clone method, in some cases, is a copy constructor | |
| 74 | * or a static factory method to return copies of an object. Both of these | |
| 75 | * approaches are simpler and do not conflict with final fields. They do not | |
| 76 | * force the calling client to handle a CloneNotSupportedException. They also | |
| 77 | * are typed therefore no casting is necessary. Finally, they are more | |
| 78 | * flexible since they can take interface types rather than concrete classes. | |
| 79 | * </p> | |
| 80 | * | |
| 81 | * <p> | |
| 82 | * Sometimes a copy constructor or static factory is not an acceptable | |
| 83 | * alternative to the clone method. The example below highlights the | |
| 84 | * limitation of a copy constructor (or static factory). Assume | |
| 85 | * Square is a subclass for Shape. | |
| 86 | * | |
| 87 | * <pre> | |
| 88 | * Shape s1 = new Square(); | |
| 89 | * System.out.println(s1 instanceof Square); //true | |
| 90 | * </pre> | |
| 91 | * | |
| 92 | * ...assume at this point the code knows nothing of s1 being a Square | |
| 93 | * that's the beauty of polymorphism but the code wants to copy | |
| 94 | * the Square which is declared as a Shape, its super type... | |
| 95 | * | |
| 96 | * <pre> | |
| 97 | * Shape s2 = new Shape(s1); //using the copy constructor | |
| 98 | * System.out.println(s2 instanceof Square); //false | |
| 99 | * </pre> | |
| 100 | * | |
| 101 | * The working solution (without knowing about all subclasses and doing many | |
| 102 | * casts) is to do the following (assuming correct clone implementation). | |
| 103 | * | |
| 104 | * <pre> | |
| 105 | * Shape s2 = s1.clone(); | |
| 106 | * System.out.println(s2 instanceof Square); //true | |
| 107 | * </pre> | |
| 108 | * | |
| 109 | * Just keep in mind if this type of polymorphic cloning is required | |
| 110 | * then a properly implemented clone method may be the best choice. | |
| 111 | * </p> | |
| 112 | * | |
| 113 | * <p> | |
| 114 | * Much of this information was taken from Effective Java: | |
| 115 | * Programming Language Guide First Edition by Joshua Bloch | |
| 116 | * pages 45-52. Give Bloch credit for writing an excellent book. | |
| 117 | * </p> | |
| 118 | * | |
| 119 | * <p> | |
| 120 | * This check is almost exactly the same as the {@link NoFinalizerCheck} | |
| 121 | * </p> | |
| 122 | * | |
| 123 | * @author Travis Schneeberger | |
| 124 | * @version 1.0 | |
| 125 | * @see java.lang.Object#clone() | |
| 126 | * @see java.lang.Cloneable | |
| 127 | * @see java.lang.CloneNotSupportedException | |
| 128 | */ | |
| 129 | public class NoCloneCheck extends AbstractIllegalMethodCheck | |
| 130 | { | |
| 131 | /** | |
| 132 | * Creates an instance. | |
| 133 | */ | |
| 134 | public NoCloneCheck() | |
| 135 | { | |
| 136 | 1 | super("clone", "avoid.clone.method"); |
| 137 | 1 | } |
| 138 | } |