Method chaining results in unchecked call warning - java

I have got the following interface which is implemented by the following class. For this class, I would like to be able to use method chaining, which is why I added a "return this" at the end of the addFilter() method:
public interface IFilteredDataService<B extends Bean> extends IDataService<B>
{
FilteredDataService applyFilter(Predicate<B> filter);
}
public class FilteredDataService<B extends Bean> implements IFilteredDataService<B>
{
#Override
public FilteredDataService addFilter(Predicate<B> filter)
{
filters.add(filter);
return this;
}
}
When I use the addFilter() method in the following way, everything is fine:
someInstance.addFilter(foo);
someInstance.addFilter(bar);
When I use the method chaining like this:
someInstance.addFilter(foo).addFilter(bar);
it still works fine, but I get the following warning:
Unchecked call to 'addFilter(Predicate<B>)' as a member of raw type 'FilteredDataService'.
I was not able to figure out why this happens and how to remove it. Any help would be greatly appreciated.

You're missing the generic information in your return value, returning a raw (non-generic) FilteredDataService.
Use public FilteredDataService<B> addFilter(Predicate<B> filter) to keep the generics.

When you want to use generic and chain this method, you have to create fully generic method (include returning) as Kayaman wrote. And take a look at what you getting:
Unchecked call to 'addFilter(Predicate)' as a member of raw type 'FilteredDataService'.
In simple translation: You are calling method which should accept generic param (addFilter(Predicate filter)) but you are sending nongeneric param during chaining (return this; = FilteredDataService -> Non-Generic).
Just for clarify :o)

Related

Calling a lambda function later with different objects/arguments

I am a newbie in java functional interfaces so I want to see if this is possible and if not please explain me why not and what is possible in order to achieve my idea
I have these classes
public class A {
...
public String getInfo();
...
}
public class B {
...
public String getOtherInfo();
...
}
I want to pass the references to these functions to another object like this:
obj.init(A::getInfo)
obj.init(B::getOtherInfo)
so that later I can use/call these functions on different objects of type A or B inside the build functions:
obj.build(a1);
obj.build(a2);
...
obj.build(b1);
obj.build(b2);
PS1 I cannot use regular interfaces for this cause there are lot of getters and lots of classes similar to A which I want to use for this procedure and they are not related with one another
PS2 I try to avoid reflection cause you cannot trace the function calls
PS3 my example is not exactly working as is it throws this error: "non static method cannot be referenced from a static context"
A::get is a Java Method Reference. You should be able to store it for use later. As it's an instance method you'll need the instance object as well. So something like this might work:
Function<A,String> getFunction = A::get;
And whenever you need to use it you can do
//assuming you have an object instance of A which is a
getFunction.apply(a)
You can also pass it to other methods by declaring the method to take a functional parameter like this:
public void someOtherMethod(Function<A,String> param) {
//do whatever with param.
//invoke this with an instance of A when you're ready
param.apply(a);
}
Here's a reference that might help: https://www.baeldung.com/java-8-double-colon-operator
Made 2 mistakes
should have used Function<T, R> instead of Supplier
the error is thrown even if there is a slight mismatch of parameters even on the generic types. So an example of my function which accepts the Function parameter should be declared like this:
public <T extends Base> init (Function <T, String> f){
this.f = f;
}
and later I do something like:
public String build (A a){
return this.f.apply(a);
}
(so I had to make A, B implement some useless interface)

Java interface hierarchy and it's methods with bounded type Generics

I have a scenario where I found to build a hierarchy of type as follows:
IComponent (interface) -> AComponent (class)
Here I want IComponent to contain a method exeucte() which would be implemented by all the classes which implement this interface. Now, apart from the component hierarchy I also want a request/response format for all the components so I thought of below things:
IComponentRequest -> AComponentRequest
IComponentResponse -> IComponentResponse
Now I want to declare the execute() method in IComponent in such a way that all the classes which want to implement can follow the request and response classes of the above mentioned request/response hierarchy. Explaining in terms of code, I am currently declaring the method as below:
public interface IComponent<IComponentRequest,IComponentResponse> {
IComponentResponse execute(IComponentRequest request);
}
What I actually want is something like :
<Any type which implements IComponentResponse> execute(<Any type which implements IComponentRequest> request) {
}
I tried using generics like :
public interface IComponent<REQUEST,RESPONSE> {}
But in these cases I face issue in implementations while calling methods and receiving responses that REQUEST and RESPONSE are not any particular java types. Hence, I again went on to use the proper interfaces IComponentRequest and IComponentResponse but there I am not able to apply bounded generics.
Can someone please help on what am I missing here ?
When you specify the generic name, you can also specify type information. Here, you want extends for each appropriate type. Something like
public interface IComponent<REQUEST extends IComponentRequest,
RESPONSE extends IComponentResponse> {
RESPONSE execute(REQUEST request);
}

Why can't Java infer the type of a lambda expression with a generic type parameter?

Given the following code:
abstract class Event {
}
class MyEvent extends Event {
}
interface EventSubscriber<T extends Event> {
void onMessage(T message);
Class<T> getMessageType();
}
interface MyEventSubscriber extends EventSubscriber<MyEvent> {
#Override
default Class<MyEvent> getMessageType() {
return MyEvent.class;
}
}
class SubscriberManager {
public void subscribe(EventSubscriber<? extends Event> subscriber) {
}
}
I would like to get access to the generic type parameter which an event subscriber holds via calling the getMessageType method.
I also would like to use the SubscriberManager by passing the lambda expressions to the subscribe method:
subscriberManager.subscribe((MyEvent event) -> {});
Unfortunately, the Java compiler can't infer the type of the lambda expression which is passed to the subscribe method, although it's pretty obvious to me that the type of the lambda could be deduced from the lambda's argument - MyEvent -> MyEventSubscriber. The Java compiler gives me the following error:
incompatible types: EventSubscriber is not a functional interface
multiple non-overriding abstract methods found in interface EventSubscriber
So I need to specify the type of the lambda expression or use the anonymous class in order to bypass this limitation:
MyEventSubscriber myEventSubscriber = (MyEvent event) -> {};
subscriberManager.subscribe(myEventSubscriber);
subscriberManager.subscribe(new MyEventSubscriber() {
#Override
public void onMessage(MyEvent message) {
}
});
I could add an overloaded method to the SubscriberManager class, remove the getMessageType method from the EventSubscriber interface (since we would know the actual type of the subscriber and therefore the message type it holds) and use the simple lambda expression I mentioned in the first code example, but it would make the whole code less 'polymorphic` I guess:
class SubscriberManager {
public void subscribe(EventSubscriber<? extends Event> subscriber) {
}
public void subscribe(MyEventSubscriber subscriber) {
}
}
The problem is that your EventSubscriber interface isn't a functional interface, as the error tells you: There are 2 methods to implement there. The fact that you've made an actual functional interface named MyEventSubscriber would mean that you want java to somehow intuit that this exists.
Java is not in the business of scouring the millions of classes in the classpath just to look and see if there's anything in that entire mess that may or may not work. I hope by putting it that way it's obvious why that is and why it'll never work that way.
Specifically: Because there's a lambda, java needs to target type it. To do this, java first checks the context surrounding the lambda: It checks the various methods named subscribe and notices there's only one, and it needs an argument of type EventSubscriber. It then target-types the lambda to this type, and immediately fails, as it is not a functional interface. There is no way for the compiler to figure it out it should be target-typing to MyEventSubscriber.
I did some toying around with using reflection to check the actual type, but that does not work; you'll have to find another way to tackle this problem.

Mockito: how to mock doAnswer for a generic method

I have a class that, in essence, looks like this:
class Checkpointer {
public <Input,Output> Output runFunction(Input input, Function<Input,Output> function) {
Output output;
// Sometimes run the function, sometimes return an Output from a cache
return output
}
}
I would like to mock this class using Mockito doAnswer:
Checkpointer checkpointer; // mocked via #Mock annotation
Mockito
.doAnswer(/* ??? */)
.when(checkpointer)
.runFunction(Mockito.any(), Mockito.any());
The function I want to mock needs to be generic. Can this be done?
For example, my first attempt produced the following. Not only did I resort to Object as the type arguments for Function, but the compiler was still unhappy with unchecked casting:
Mockito.doAnswer((invocation) ->
{
// compiler is not happy with this cast V
Function<Object,Object> function = (Function<Object,Object>)invocation.getArguments()[1];
return function.apply(invocation.getArgument(0));
}).when(checkpointer).runFunction(Mockito.any(), Mockito.any());
If this can't be done, I think can try writing my own mock class extending the first and use Mockito.spy.
The problem here is that you insist on using getArguments, which returns an Object[]
Since you know the index of the Function argument, you can use getArgument(index), as you're doing the line after that.
final Function<String, String> argument = invocation.getArgument(1);
Is this what you're looking for? Type inference for the getArgument generic type is working fine.
If not, can you provide a more elaborate example?

Programmatically assess relationship between type variables in class hierarchy

Suppose I have a Java class hierarchy defined as follow:
interface Bar<T> {}
class Foo<A,B> implements Bar<B> {}
How can I programmatically assess (using reflection) that the type parameter of Bar in Foo is the second of foo's parameters and not the first (B instead of A)?
I've tried using TypeVariable#getName() in order to compare the names, but when I apply getGenericInterfaces() to Foo<A,B> I get Bar<T> and not Bar<B>
Solution (thanks to #LouisWasserman): use Foo.class.getGeenricInterfaces()[0].getActualTypeParameters() returns the correct TypeVariable (B instead of T, in the previous example)
well using TypeVariable#getName() return the type as it appears in the source code in your case it's normal to get Bar<T>. TypeVariable Doc
Using reflection in generic Classes can't help, because of Type Erasure. Erasure of Generic Types
I've the same issue in some personal projects, I tried to change the design of my class, have a look at the example below:
Instead of this:
public class Mapper<T> {
public Mapper(){
}
}
I used this:
public class Mapper {
private Class<?> entityClazz;
public Mapper(Class<?> entity){
this.entityClazz = entity
//Here I've donne all reflection issues i want !
}
}
You can use Class#isAssignableFrom() Doc to test assignability between Class Objects.
I hope this helps, good luck !

Categories