Skip to content

Commit

Permalink
MethodParameter.equals checks nesting level and containing class
Browse files Browse the repository at this point in the history
Closes gh-23352
  • Loading branch information
jhoeller committed Jul 31, 2019
1 parent c4cdb98 commit 7465878
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,6 +39,7 @@
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;

/**
* Helper class that encapsulates the specification of a method parameter, i.e. a {@link Method}
Expand All @@ -61,14 +62,15 @@ public class MethodParameter {

private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];


private final Executable executable;

private final int parameterIndex;

@Nullable
private volatile Parameter parameter;

private int nestingLevel = 1;
private int nestingLevel;

/** Map from Integer level to Integer type index */
@Nullable
Expand Down Expand Up @@ -650,12 +652,16 @@ public boolean equals(Object other) {
return false;
}
MethodParameter otherParam = (MethodParameter) other;
return (this.parameterIndex == otherParam.parameterIndex && getExecutable().equals(otherParam.getExecutable()));
return (this.containingClass == otherParam.containingClass &&
ObjectUtils.nullSafeEquals(this.typeIndexesPerLevel, otherParam.typeIndexesPerLevel) &&
this.nestingLevel == otherParam.nestingLevel &&
this.parameterIndex == otherParam.parameterIndex &&
this.executable.equals(otherParam.executable));
}

@Override
public int hashCode() {
return (getExecutable().hashCode() * 31 + this.parameterIndex);
return (31 * this.executable.hashCode() + this.parameterIndex);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,6 +22,7 @@
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.concurrent.Callable;

import org.junit.Before;
Expand Down Expand Up @@ -148,6 +149,44 @@ public void genericConstructorParameterInInnerClass() throws Exception {
methodParameter.getGenericParameterType());
}

@Test
public void multipleResolveParameterTypeCalls() throws Exception {
Method method = ArrayList.class.getMethod("get", int.class);
MethodParameter methodParameter = MethodParameter.forExecutable(method, -1);
assertEquals(Object.class, methodParameter.getParameterType());
GenericTypeResolver.resolveParameterType(methodParameter, StringList.class);
assertEquals(String.class, methodParameter.getParameterType());
GenericTypeResolver.resolveParameterType(methodParameter, IntegerList.class);
assertEquals(Integer.class, methodParameter.getParameterType());
}

@Test
public void equalsAndHashCodeConsidersContainingClass() throws Exception {
Method method = ArrayList.class.getMethod("get", int.class);
MethodParameter m1 = MethodParameter.forExecutable(method, -1);
MethodParameter m2 = MethodParameter.forExecutable(method, -1);
MethodParameter m3 = MethodParameter.forExecutable(method, -1).nested();
assertEquals(m1, m2);
assertNotEquals(m1, m3);
assertEquals(m1.hashCode(), m2.hashCode());
}

@Test
public void equalsAndHashCodeConsidersNesting() throws Exception {
Method method = ArrayList.class.getMethod("get", int.class);
MethodParameter m1 = MethodParameter.forExecutable(method, -1);
GenericTypeResolver.resolveParameterType(m1, StringList.class);
MethodParameter m2 = MethodParameter.forExecutable(method, -1);
GenericTypeResolver.resolveParameterType(m2, StringList.class);
MethodParameter m3 = MethodParameter.forExecutable(method, -1);
GenericTypeResolver.resolveParameterType(m3, IntegerList.class);
MethodParameter m4 = MethodParameter.forExecutable(method, -1);
assertEquals(m1, m2);
assertNotEquals(m1, m3);
assertNotEquals(m1, m4);
assertEquals(m1.hashCode(), m2.hashCode());
}


public int method(String p1, long p2) {
return 42;
Expand All @@ -172,4 +211,12 @@ public InnerClass(@Param String s, Callable<Integer> i) {
private @interface Param {
}

@SuppressWarnings("serial")
private static class StringList extends ArrayList<String> {
}

@SuppressWarnings("serial")
private static class IntegerList extends ArrayList<Integer> {
}

}

0 comments on commit 7465878

Please sign in to comment.