001///////////////////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
003// Copyright (C) 2001-2026 the original author or authors.
004//
005// This library is free software; you can redistribute it and/or
006// modify it under the terms of the GNU Lesser General Public
007// License as published by the Free Software Foundation; either
008// version 2.1 of the License, or (at your option) any later version.
009//
010// This library is distributed in the hope that it will be useful,
011// but WITHOUT ANY WARRANTY; without even the implied warranty of
012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013// Lesser General Public License for more details.
014//
015// You should have received a copy of the GNU Lesser General Public
016// License along with this library; if not, write to the Free Software
017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018///////////////////////////////////////////////////////////////////////////////////////////////
019
020package com.puppycrawl.tools.checkstyle.checks.coding;
021
022import com.puppycrawl.tools.checkstyle.StatelessCheck;
023import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
024import com.puppycrawl.tools.checkstyle.api.DetailAST;
025import com.puppycrawl.tools.checkstyle.api.TokenTypes;
026
027/**
028 * <div>
029 * Checks that the clone method is not overridden from the
030 * Object class.
031 * </div>
032 *
033 * <p>
034 * This check is almost exactly the same as the {@code NoFinalizerCheck}.
035 * </p>
036 *
037 * <p>
038 * See
039 * <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#clone()">
040 * Object.clone()</a>
041 * </p>
042 *
043 * <p>
044 * Rationale: The clone method relies on strange, hard to follow rules that
045 * are difficult to get right and do not work in all situations. In some cases,
046 * either a copy constructor or a static factory method can be used instead of
047 * the clone method to return copies of an object. For more information on rules
048 * for the clone method and its issues, see Effective Java:
049 * Programming Language Guide First Edition by Joshua Bloch pages 45-52.
050 * </p>
051 *
052 * <p>
053 * Below are some rules/reasons why the clone method should be avoided.
054 * </p>
055 * <ul>
056 * <li>
057 * Classes supporting the clone method should implement the Cloneable
058 * interface but the Cloneable interface does not include the clone method.
059 * As a result, it doesn't enforce the method override.
060 * </li>
061 * <li>
062 * The Cloneable interface forces the Object's clone method to work
063 * correctly. Without implementing it, the Object's clone method will
064 * throw a CloneNotSupportedException.
065 * </li>
066 * <li>
067 * Non-final classes must return the object returned from a call to
068 * super.clone().
069 * </li>
070 * <li>
071 * Final classes can use a constructor to create a clone which is different
072 * from non-final classes.
073 * </li>
074 * <li>
075 * If a super class implements the clone method incorrectly all subclasses
076 * calling super.clone() are doomed to failure.
077 * </li>
078 * <li>
079 * If a class has references to mutable objects then those object
080 * references must be replaced with copies in the clone method after calling super.clone().
081 * </li>
082 * <li>
083 * The clone method does not work correctly with final mutable object
084 * references because final references cannot be reassigned.
085 * </li>
086 * <li>
087 * If a super class overrides the clone method then all subclasses must
088 * provide a correct clone implementation.
089 * </li>
090 * </ul>
091 *
092 * <p>Two alternatives to the clone method, in some cases, is a copy constructor
093 * or a static factory method to return copies of an object. Both of these
094 * approaches are simpler and do not conflict with final fields. They do not
095 * force the calling client to handle a CloneNotSupportedException.  They also
096 * are typed therefore no casting is necessary. Finally, they are more
097 * flexible since they can take interface types rather than concrete classes.
098 * </p>
099 *
100 * <p>Sometimes a copy constructor or static factory is not an acceptable
101 * alternative to the clone method.  The example below highlights the
102 * limitation of a copy constructor (or static factory). Assume Square is a subclass for Shape.
103 * </p>
104 * {@snippet :
105 * Shape s1 = new Square();
106 * System.out.println(s1 instanceof Square); //true
107 * }
108 *
109 * <p>
110 * ...assume at this point the code knows nothing of s1 being a Square
111 *    that's the beauty of polymorphism but the code wants to copy
112 *    the Square which is declared as a Shape, its super type...
113 * </p>
114 * {@snippet :
115 * Shape s2 = new Shape(s1); //using the copy constructor
116 * System.out.println(s2 instanceof Square); //false
117 * }
118 *
119 * <p>
120 * The working solution (without knowing about all subclasses and doing many
121 * casts) is to do the following (assuming correct clone implementation).
122 * </p>
123 * {@snippet :
124 * Shape s2 = s1.clone();
125 * System.out.println(s2 instanceof Square); //true
126 * }
127 *
128 * <p>
129 * Just keep in mind if this type of polymorphic cloning is required
130 * then a properly implemented clone method may be the best choice.
131 * </p>
132 *
133 * <p>Much of this information was taken from Effective Java:
134 * Programming Language Guide First Edition by Joshua Bloch
135 * pages 45-52.  Give Bloch credit for writing an excellent book.
136 * </p>
137 *
138 * @since 5.0
139 */
140@StatelessCheck
141public class NoCloneCheck extends AbstractCheck {
142
143    /**
144     * A key is pointing to the warning message text in "messages.properties" file.
145     */
146    public static final String MSG_KEY = "avoid.clone.method";
147
148    /**
149     * Creates a new {@code NoCloneCheck} instance.
150     */
151    public NoCloneCheck() {
152        // no code by default
153    }
154
155    @Override
156    public int[] getDefaultTokens() {
157        return getRequiredTokens();
158    }
159
160    @Override
161    public int[] getAcceptableTokens() {
162        return getRequiredTokens();
163    }
164
165    @Override
166    public int[] getRequiredTokens() {
167        return new int[] {TokenTypes.METHOD_DEF};
168    }
169
170    @Override
171    public void visitToken(DetailAST ast) {
172        final DetailAST mid = ast.findFirstToken(TokenTypes.IDENT);
173        final String name = mid.getText();
174
175        if ("clone".equals(name)) {
176            final DetailAST params = ast.findFirstToken(TokenTypes.PARAMETERS);
177            final boolean hasEmptyParamList =
178                params.findFirstToken(TokenTypes.PARAMETER_DEF) == null;
179
180            if (hasEmptyParamList) {
181                log(ast, MSG_KEY);
182            }
183        }
184    }
185
186}