@@ -111,6 +111,12 @@ public J visitNewClass(J.NewClass newClass, ExecutionContext ctx) {
111111 TypeUtils .isOfClassType (n .getClazz () != null ? n .getClazz ().getType () : null , "java.util.HashMap" )) {
112112 Statement statement = body .getStatements ().get (0 );
113113 if (statement instanceof J .Block ) {
114+ // Skip when the result is assigned to a concrete `HashMap` declared type rather
115+ // than `Map`: the immutable `Map.of(..)` is not assignable to `HashMap`, and
116+ // `HashMap`-only methods may be invoked on the variable later (issue #1148).
117+ if (isAssignedToConcreteHashMap ()) {
118+ return n ;
119+ }
114120 List <Statement > putStatements = ((J .Block ) statement ).getStatements ();
115121 List <Expression > args = new ArrayList <>();
116122 boolean useEntries = putStatements .size () > 10 ;
@@ -194,6 +200,19 @@ private J reattachPairPrefixes(J applied, List<J.MethodInvocation> puts, boolean
194200 return nc .withArguments (Collections .singletonList (mapCall .withArguments (withPrefixes )));
195201 }
196202
203+ /**
204+ * Returns {@code true} when the {@code new HashMap<>() {{ ... }}} currently being visited is
205+ * the initializer of a variable whose declared type is the concrete {@code java.util.HashMap}
206+ * rather than the {@code Map} interface. In that case the immutable {@code Map.of(..)} result
207+ * would not be assignable, and {@code HashMap}-specific methods may be used later, so the
208+ * rewrite is skipped (issue #1148).
209+ */
210+ private boolean isAssignedToConcreteHashMap () {
211+ Object parent = getCursor ().getParentTreeCursor ().getValue ();
212+ return parent instanceof J .VariableDeclarations .NamedVariable &&
213+ TypeUtils .isOfClassType (((J .VariableDeclarations .NamedVariable ) parent ).getType (), "java.util.HashMap" );
214+ }
215+
197216 @ Override
198217 public J visitBlock (J .Block block , ExecutionContext ctx ) {
199218 Map <UUID , List <J .MethodInvocation >> rewrites = new HashMap <>();
0 commit comments