Is there a way to match any class argument of the below sample routine?
class A {
public B method(Class<? extends A> a) {}
}
How can I always return a new B() regardless of which class is passed into method? The following attempt only works for the specific case where A is matched.
A a = new A();
B b = new B();
when(a.method(eq(A.class))).thenReturn(b);
EDIT: One solution is
(Class<?>) any(Class.class)
Two more ways to do it (see my comment on the previous answer by #Tomasz Nurkiewicz):
The first relies on the fact that the compiler simply won't let you pass in something of the wrong type:
when(a.method(any(Class.class))).thenReturn(b);
You lose the exact typing (the Class<? extends A>) but it probably works as you need it to.
The second is a lot more involved but is arguably a better solution if you really want to be sure that the argument to method() is an A or a subclass of A:
when(a.method(Matchers.argThat(new ClassOrSubclassMatcher<A>(A.class)))).thenReturn(b);
Where ClassOrSubclassMatcher is an org.hamcrest.BaseMatcher defined as:
public class ClassOrSubclassMatcher<T> extends BaseMatcher<Class<T>> {
private final Class<T> targetClass;
public ClassOrSubclassMatcher(Class<T> targetClass) {
this.targetClass = targetClass;
}
#SuppressWarnings("unchecked")
public boolean matches(Object obj) {
if (obj != null) {
if (obj instanceof Class) {
return targetClass.isAssignableFrom((Class<T>) obj);
}
}
return false;
}
public void describeTo(Description desc) {
desc.appendText("Matches a class or subclass");
}
}
Phew! I'd go with the first option until you really need to get finer control over what method() actually returns :-)
There is another way to do that without cast:
when(a.method(Matchers.<Class<A>>any())).thenReturn(b);
This solution forces the method any() to return Class<A> type and not its default value (Object).
If you have no idea which Package you need to import:
import static org.mockito.ArgumentMatchers.any;
any(SomeClass.class)
OR
import org.mockito.ArgumentMatchers;
ArgumentMatchers.any(SomeClass.class)
How about:
when(a.method(isA(A.class))).thenReturn(b);
or:
when(a.method((A)notNull())).thenReturn(b);
the solution from millhouse is not working anymore with recent version of mockito
This solution work with java 8 and mockito 2.2.9
where ArgumentMatcher is an instanceof org.mockito.ArgumentMatcher
public class ClassOrSubclassMatcher<T> implements ArgumentMatcher<Class<T>> {
private final Class<T> targetClass;
public ClassOrSubclassMatcher(Class<T> targetClass) {
this.targetClass = targetClass;
}
#Override
public boolean matches(Class<T> obj) {
if (obj != null) {
if (obj instanceof Class) {
return targetClass.isAssignableFrom( obj);
}
}
return false;
}
}
And the use
when(a.method(ArgumentMatchers.argThat(new ClassOrSubclassMatcher<>(A.class)))).thenReturn(b);
None of the examples above worked for me, as I'm required to mock one method multiple times for different class type parameters.
Instead, this works.
//Handle InstrumentType.class
Mockito.doReturn(new InstrumentTypeMapper() {
#Override
public InstrumentType map(String sourceType) throws Exception {
return InstrumentType.Unknown;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat(new ArgumentMatcher<Class<InstrumentType>>() {
#Override
public boolean matches(Class<InstrumentType> argument) {
return InstrumentType.class.isAssignableFrom(argument);
}
}));
//Handle InstrumentSubType.class
Mockito.doReturn(new InstrumentSubTypeMapper() {
#Override
public InstrumentSubType map(String sourceType) throws Exception {
return InstrumentSubType.istNone;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat(new ArgumentMatcher<Class<InstrumentSubType>>() {
#Override
public boolean matches(Class<InstrumentSubType> argument) {
return InstrumentSubType.class.isAssignableFrom(argument);
}
}));
This is the short version:
Mockito.doReturn(new InstrumentTypeMapper() {
#Override
public InstrumentType map(String sourceType) throws Exception {
return InstrumentType.Unknown;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat((ArgumentMatcher<Class<InstrumentType>>) InstrumentType.class::isAssignableFrom));
Mockito.doReturn(new InstrumentSubTypeMapper() {
#Override
public InstrumentSubType map(String sourceType) throws Exception {
return InstrumentSubType.istNone;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat((ArgumentMatcher<Class<InstrumentSubType>>) InstrumentSubType.class::isAssignableFrom));
As you can see, I'm using custom ArgumentMatchers together with argThat, not sure if there is a shorter way that also works.
Related
The below get method given Sonar issue:
Generic wildcard types should not be used in return types.
I need some expert help to refactor this code to avoid that Sonar issue. I try different ways like Entity<D.Id> but I haven't idea how to combine with Entity<C.Id>.
public interface Identity {
//
}
public interface Entity<I extends Identity> {
//
}
public interface D
extends Entity<D.Id>
{
}
public interface C
extends Entity<C.Id>
{
}
protected Entity<? extends Identity> get(final String value)
{
if (value == 'valuD')
{
return new D() //return object;
}
else
{
return new C() //return object;
}
}
Assume we have the following interface and implementations:
interface Matcher<T>{
boolean matches(T arg);
}
class NumberMatcher<T extends Number> implements Matcher<T>{
#Override
public boolean matches(T arg){...}
}
class StringMatcher extends Matcher<String>{
#Override
public boolean matches(String arg){ ...}
}
class CustomMatcher extends NumberMatcher<Integer> {
public boolean matches(String arg){...}
#Override
public boolean matches(Integer arg){...}
}
What I need is the type of the parameter of the matches(T) method of a given Matcher implementation.
NumberMatcher numberMatcher = new NumberMatcher<Long>();
StringMatcher stringMatcher = new StringMatcher();
CustomMatcher customMatcher = new CustomMatcher();
Matcher<Date> dateMatcher = new Matcher<Date>(){...};
getArgumentType(numberMatcher) // should return Number.class
getArgumentType(stringMatcher) // should return String.class
getArgumentType(customMatcher) // should return Integer.class
getArgumentType(dateMatcher ) // should return Object.class
Here is a implementation that works except of the CustomMatcher case, cause it fails to detect the overriden matches(..) method and returns String.class instead of Integer.class.
Class<?> getArgumentType(Matcher<?> matcher) {
Method[] methods = matcher.getClass().getMethods();
for (Method method : methods) {
if (isMatchesMethod(method)) {
return method.getParameterTypes()[0];
}
}
throw new NoSuchMethodError("Method 'matches(T)' not found!");
}
private boolean isMatchesMethod(Method method) {
if (!isPublic(method.getModifiers()))
return false;
if (method.getParameterCount() != 1)
return false;
return method.getName().equals("matches");
}
EDIT:
I am looking for a solution that doesn't need to specify the argument type like this:
interface Matcher<T>{
boolean matches(T arg);
Class<T> argumentType();
}
As long as you can edit the implementations, you can use a marker annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface ThisIsTheOne {
}
public class CustomMatcher extends NumberMatcher<Integer> {
#Override
#ThisIsTheOne
public boolean matches(Integer arg){ return true; }
public boolean matches(String arg){ return true; }
}
private static boolean isMatchesMethod(Method method) {
if (method.getAnnotation(ThisIsTheOne.class) != null) {
return true;
}
// do the same as before, so it works on non-annotated methods too
}
This will return Integer.class for CustomMatcher.
I don't think there's a way to retrieve this information at runtime, since Method-s don't know where they come from. This is probably intentional, as multiple interfaces can define the same method signature.
Say, i have a generic type as below
public class GenericType<T> {
private T someVar;
public void setVar(T var) { this.someVar = var; }
//Rest of the code
}
I want to allow it to take only specific types(String/Integer/Double). I know about bounded wildcards but they don't help me here. In setVar(), I can check the instanceof and throw an Exception if type is not Integer/String etc. Is this the best way to do it?
I have the same problem when doing operations on this type. Depending on the type, I want to do different operations. Inheritance and bounded wildcards seem like the way to go in general for this kind of problem but these are primitive wrappers.
Using Inheritance:
Parent.java
public abstract class Parent<T> {
public abstract void display(T t);
}
ChildString.java
public class ChildString extends Parent<String> {
#Override
public void display(String t) {
// Do something here...
}
}
ChildInteger.java
public class ChildInteger extends Parent<Integer> {
#Override
public void display(Integer t) {
// Do something here...
}
}
ChildDouble.java
public class ChildDouble extends Parent<Double> {
#Override
public void display(Double t) {
// Do something here...
}
}
And access the class child rather than you directly access the parent class.
Update
Here another example:
GenericType.java
public class GenericType {
public void display(Object t) {
String msg;
if(t instanceof String) {
msg = "String";
} else if (t instanceof Integer) {
msg = "Integer";
} else if (t instanceof Double) {
msg = "Double";
} else {
msg = "Another Object";
}
System.out.println(msg);
}
}
SpecificGeneric.java
public class SpecificGeneric {
public static void main(String[] args) {
GenericType basicType = new GenericType();
basicType.display(new String());
basicType.display(new Integer(1));
basicType.display(new Double(0.1));
}
}
You cannot (more than extends something, but in your case you want few unrelated types, so it does not help).
What you can, is check instance passed to method (you already know it). If you want one instace of generic class for eg. String another for Integers, but don't allow eg. Point2D, you can make constructor with parameter Class clazz and check when constructing whether its allowed.
If you are more paranoid, you can store that clazz and in all function compare whether parameter is actualy that class.
This way, you can still create MyClass, but cannot create instance with this type. (But you can cast it, co its not fool proof)
Inferring the desired type say GenericType<Double> and using instanceof when neccesary is the quickest and easy option. Alternatively overload setVar(..) to accept the restricted types in your Generic class.
public static class GenericType<T>
{
private T someVar;
public void setVar(String var)
{
this.someVar = (T) var;
}
public void setVar(Integer var)
{
this.someVar = (T) var;
}
public void setVar(Double var)
{
this.someVar = (T) var;
}
}
Before I look through my generic data structure for a value's index, I'd like to see if it is even an instance of the type this has been parametrized to.
But Eclipse complains when I do this:
#Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
This is the error message:
Cannot perform instanceof check against type parameter E. Use instead its erasure Object since generic type information will be erased at runtime
What is the better way to do it?
The error message says it all. At runtime, the type is gone, there is no way to check for it.
You could catch it by making a factory for your object like this:
public static <T> MyObject<T> createMyObject(Class<T> type) {
return new MyObject<T>(type);
}
And then in the object's constructor store that type, so variable so that your method could look like this:
if (arg0 != null && !(this.type.isAssignableFrom(arg0.getClass())) {
return -1;
}
Two options for runtime type checking with generics:
Option 1 - Corrupt your constructor
Let's assume you are overriding indexOf(...), and you want to check the type just for performance, to save yourself iterating the entire collection.
Make a filthy constructor like this:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
Then you can use isAssignableFrom to check the type.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
Each time you instantiate your object you would have to repeat yourself:
new MyCollection<Apples>(Apples.class);
You might decide it isn't worth it. In the implementation of ArrayList.indexOf(...), they do not check that the type matches.
Option 2 - Let it fail
If you need to use an abstract method that requires your unknown type, then all you really want is for the compiler to stop crying about instanceof. If you have a method like this:
protected abstract void abstractMethod(T element);
You can use it like this:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
You are casting the object to T (your generic type), just to fool the compiler. Your cast does nothing at runtime, but you will still get a ClassCastException when you try to pass the wrong type of object into your abstract method.
NOTE 1: If you are doing additional unchecked casts in your abstract method, your ClassCastExceptions will get caught here. That could be good or bad, so think it through.
NOTE 2: You get a free null check when you use instanceof. Since you can't use it, you may need to check for null with your bare hands.
Old post, but a simple way to do generic instanceOf checking.
public static <T> boolean isInstanceOf(Class<T> clazz, Class<T> targetClass) {
return clazz.isInstance(targetClass);
}
Provided your class extends a class with a generic parameter, you can also get this at runtime via reflection, and then use that for comparison, i.e.
class YourClass extends SomeOtherClass<String>
{
private Class<?> clazz;
public Class<?> getParameterizedClass()
{
if(clazz == null)
{
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
clazz = (Class<?>)pt.getActualTypeArguments()[0];
}
return clazz;
}
}
In the case above, at runtime you will get String.class from getParameterizedClass(), and it caches so you don't get any reflection overhead upon multiple checks. Note that you can get the other parameterized types by index from the ParameterizedType.getActualTypeArguments() method.
I had the same problem and here is my solution (very humble, #george: this time compiling AND working ...).
My probem was inside an abstract class that implements Observer.
The Observable fires method update(...) with Object class that can be any kind of Object.
I only want to handler Objects of type T
The solution is to pass the class to the constructor in order to be able to compare types at runtime.
public abstract class AbstractOne<T> implements Observer {
private Class<T> tClass;
public AbstractOne(Class<T> clazz) {
tClass = clazz;
}
#Override
public void update(Observable o, Object arg) {
if (tClass.isInstance(arg)) {
// Here I am, arg has the type T
foo((T) arg);
}
}
public abstract foo(T t);
}
For the implementation we just have to pass the Class to the constructor
public class OneImpl extends AbstractOne<Rule> {
public OneImpl() {
super(Rule.class);
}
#Override
public void foo(Rule t){
}
}
Or you could catch a failed attempt to cast into E eg.
public int indexOf(Object arg0){
try{
E test=(E)arg0;
return doStuff(test);
}catch(ClassCastException e){
return -1;
}
}
Technically you shouldn't have to, that's the point of generics, so you can do compile-type checking:
public int indexOf(E arg0) {
...
}
but then the #Override may be a problem if you have a class hierarchy. Otherwise see Yishai's answer.
The runtime type of the object is a relatively arbitrary condition to filter on. I suggest keeping such muckiness away from your collection. This is simply achieved by having your collection delegate to a filter passed in a construction.
public interface FilterObject {
boolean isAllowed(Object obj);
}
public class FilterOptimizedList<E> implements List<E> {
private final FilterObject filter;
...
public FilterOptimizedList(FilterObject filter) {
if (filter == null) {
throw NullPointerException();
}
this.filter = filter;
}
...
public int indexOf(Object obj) {
if (!filter.isAllows(obj)) {
return -1;
}
...
}
...
}
final List<String> longStrs = new FilterOptimizedList<String>(
new FilterObject() { public boolean isAllowed(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof String) {
String str = (String)str;
return str.length() > = 4;
} else {
return false;
}
}}
);
Let Java determine it and catch the exception bottom line.
public class Behaviour<T> {
public void behave(Object object) {
T typedObject = null;
try { typedObject = (T) object; }
catch (ClassCastException ignored) {}
if (null != typedObject) {
// Do something type-safe with typedObject
}
}
}
Let's say I have the following class:
public class Test<E> {
public boolean sameClassAs(Object o) {
// TODO help!
}
}
How would I check that o is the same class as E?
Test<String> test = new Test<String>();
test.sameClassAs("a string"); // returns true;
test.sameClassAs(4); // returns false;
I can't change the method signature from (Object o) as I'm overridding a superclass and so don't get to choose my method signature.
I would also rather not go down the road of attempting a cast and then catching the resulting exception if it fails.
An instance of Test has no information as to what E is at runtime. So, you need to pass a Class<E> to the constructor of Test.
public class Test<E> {
private final Class<E> clazz;
public Test(Class<E> clazz) {
if (clazz == null) {
throw new NullPointerException();
}
this.clazz = clazz;
}
// To make things easier on clients:
public static <T> Test<T> create(Class<T> clazz) {
return new Test<T>(clazz);
}
public boolean sameClassAs(Object o) {
return o != null && o.getClass() == clazz;
}
}
If you want an "instanceof" relationship, use Class.isAssignableFrom instead of the Class comparison. Note, E will need to be a non-generic type, for the same reason Test needs the Class object.
For examples in the Java API, see java.util.Collections.checkedSet and similar.
The method I've always used is below. It is a pain and a bit ugly, but I haven't found a better one. You have to pass the class type through on construction, as when Generics are compiled class information is lost.
public class Test<E> {
private Class<E> clazz;
public Test(Class<E> clazz) {
this.clazz = clazz;
}
public boolean sameClassAs(Object o) {
return this.clazz.isInstance(o);
}
}
I could only make it working like this:
public class Test<E> {
private E e;
public void setE(E e) {
this.e = e;
}
public boolean sameClassAs(Object o) {
return (o.getClass().equals(e.getClass()));
}
public boolean sameClassAs2(Object o) {
return e.getClass().isInstance(o);
}
}
I was just trying to do the same thing, and one neat trick i just realized is that you can can try a cast, and if the cast fails, ClassCastException will be thrown. You can can catch that, and do whatever.
so your sameClassAs method should look like:
public boolean sameClassAs(Object o) {
boolean same = false;
try {
E t = (E)o;
same = true;
} catch (ClassCastException e) {
// same is false, nothing else to do
} finally {
return same;
}
}