how to generalize a callable with params in java? - java

I have these two methods
private void saveBaseLineLatency(E2EResultShort e2EResultShort) {
LatencyHistogram latencyHistogram = getLatencyHistogram(e2EResultShort);
latencyDrillDownRepository.saveBaseLine(latencyHistogram);
saveLatencyTable(latencyHistogram);
}
private void saveFreshTestLatency(E2EResultShort e2EResultShort) {
System.out.println("log: before saveLatencyHistogram");
LatencyHistogram latencyHistogram = getLatencyHistogram(e2EResultShort);
latencyDrillDownRepository.save(latencyHistogram);
saveLatencyTable(latencyHistogram);
}
How can I refactor out their common code?
I thought to use Callable but its call() is parameterless.

Consumer is the interface you want. It's part of the new java.util.function package in Java 8, so this won't work if you're on an older version of Java. (The package also has a number of similar other interfaces, like a BiConsumer that takes two arguments, and interfaces for consuming various primitive types as well.)
So, your helper method would be something like:
private void doLatencyOperation (E2EResultShort newThing, Consumer<LatencyHistogram> consumer) {
LatencyHistogram lh = getLatencyHistogram(newThing);
consumer.accept(lh);
saveLatencyTable(lh);
}
and you could call it thusly
private void saveBaseLineLatency(E2EResultShort e2EResultShort) {
doLatencyOperation(e2EResultShort, (lh) -> latencyDrillDownRepository.saveBaseLine(lh));
}

Create an abstract class and move all the common code there.
public abstract class MyClass{
public MyClass(E2EResultShort result, latencyDrillDownRepository){
this.result = result;
}
public void execute() {
LatencyHistogram latencyHistogram = getLatencyHistogram(e2EResultShort);
callMe(latencyHistogram, latencyDrillDownRepository);
saveLatencyTable(latencyHistogram);
}
public abstract void callMe(LatencyHistogram latencyHistogram, latencyDrillDownRepository);
}`
Now in your method, create concrete MyClass:
private void saveFreshTestLatency(E2EResultShort e2EResultShort) {
System.out.println("log: before saveLatencyHistogram");
MyClass myClass = new MyClass(e2EResultShort, latencyDrillDownRepository){
public void callMe(LatencyHistogram latencyHistogram, latencyDrillDownRepository){
latencyDrillDownRepository.save(latencyHistogram);
}
}
myClass.execute();
}

Related

Java - Overriding method which has generic type parameter and type casting it while invoking it

I have a utility class OldRemote which has been deprecated now, but still it will be used for a while till the new class NewRemote is stable. And both the utility classes has the same method names and parameters, But the return type pojo classes are different. Even return type pojo structure is same, but naming is different.
In simple, both the function return types are pojo's with different field names.
Is there any generic way to handle this below usecase ?
I have created a service interface which has the generic method contract of both old and new class.
public interface RemoteService {
//contract [ return type is object to receive all/any Pojo classes ]
Object turnOnTV();
static Service GetRemoteservice(boolean isOldRemote){
if(isOldRemote){
return new OldRemote();
}
return new NewRemote();
}
}
OldRemote Class
public class OldRemote implements RemoteService{
#Override
public OldPojo turnOnTV() {
OldPojo oldPojo = new OldPojo();
System.out.println("OldPojo");
return oldPojo;
}
}
NewRemote Class
public class NewRemote implements Service{
#Override
public NewPojo turnOnTV() {
NewPojo newPojo = new NewPojo();
System.out.println("NewPojo");
return newPojo;
}
}
Demo usage of above implementation.
public class DemoTvRemote {
public static void main(String[] args) {
RemoteService remoteService1 = RemoteService.GetRemoteservice(true);
OldPojo oldRemote = (OldPojo) remoteService1.turnOnTV();
RemoteService remoteService2 = RemoteService.GetRemoteservice(false);
NewPojo shr = (NewPojo) Service2.test();
}
}
This above code works fine. But the problem is I don't want to type cast in all the places where turnOnTV() is used in my entire code base. Even If I have to do that, I will have to write a condition to switch between OldPojo and NewPojo where ever the turnOnTV() is invoked.
Is there any way to solve this problem ?
You could create a base class or interface they both extend/implement.
public abstract class RemoteServiceBase<E> {
public abstract E turnOnTv();
}
public class NewRemoteService extends RemoteServiceBase<NewRemotePojo >{
public NewRemotePojo turnOnTv() {
return new NewRemotePojo();
}
}
public class OldRemoteService extends RemoteServiceBase<OldRemotePojo >{
public OldRemotePojo turnOnTv() {
return new OldRemotePojo();
}
}
This would still only work if you know the service type. Otherwise you work with the common generic type as one would expect.
We can deal with this with the following approach :
1) We can create a dummy POJO class in a common location with having the reference of both OldPojo and NewPojo as data members
public class CommonPojo {
OldPojo oldPojo;
NewPojo newPojo;
public void setOldPojo(OldPojo oldPojo){
this.oldPojo=oldPojo;
}
public void setNewPojo(NewPojo newPojo){
this.newPojo=newPojo;
}
public OldPojo getOldPojo(){
return oldPojo;
}
public NewPojo getNewPojo(){
return newPojo;
}
}
2)We can write a Utility method as follow which can give an object of commonpojo :
public class CommonRemote {
public static CommonPojo turnOnTv(Boolean isOldRemote){
CommonPojo commonPojo = new CommonPojo
if(isOldRemote){
OldPojo oldPojo =new OldPojo();
commonPojo.setOldPojo(oldPojo);
}else{
NewPojo newPojo =new NewPojo();
commonPojo.setNewPojo (newPojo);
}
}
}
3) Use this method as turnOnTv() as Follows :
public class DemoTvRemote {
public static void main(String[] args) {
CommonPojo remote1 = CommonRemote.turnOnTv(true);
OldPojo oldRemote = remote1.getOldPojo();
CommonPojo remote2 = CommonRemote.turnOnTv(false);
NewPojo newRemote = remote2.getNewPojo();
}
}
with this approach with little changes in code We can achieve your requirement without any typecasting.

Java generic wildcard usages

This is related to java generic wild card.
I have interface like this.
public interface Processer<P, X> {
void process(P parent, X result);
}
An implementation like this.
public class FirstProcesser implements Processer<User, String> {
#Override
public void process(User parent, String result) {
}
}
And I'm using processer as this.
public class Executor {
private Processer<?, String> processer;
private int i;
public void setProcesser(Processer<?, String> processer) {
this.processer = processer;
}
private String generateString() {
return "String " + i++;
}
public <P> void execute(P parent) {
processer.process(parent, generateString());
}
public static void main(String[] args) {
Executor executor = new Executor();
executor.setProcesser(new FirstProcesser());
User user = new User();
executor.execute(user);
}
}
But here
public <P> void execute(P parent) {
processer.process(parent, generateString());
}
it gives compile error Error:(18, 27) java: incompatible types: P cannot be converted to capture#1 of ?
I need to understand why this give an error. also solution.
The wildcard basically means "I don't care which type is used here". In your case, you definitely do care though: the first type parameter of your processor must be the same as the P type in the execute method.
With the current code, you could call execute(1), which would try to call the FirstProcesser with an integer as argument, which obviously makes no sense, hence why the compiler forbids it.
The easiest solution would be to make your Executor class generic, instead of only the execute method:
public class Executor<P> {
private Processer<P, String> processer;
private int i;
public void setProcesser(Processer<P, String> processer) {
this.processer = processer;
}
private String generateString() {
return "String " + i++;
}
public void execute(P parent) {
processer.process(parent, generateString());
}
public static void main(String[] args) {
Executor executor = new Executor<User>();
executor.setProcesser(new FirstProcesser());
User user = new User();
executor.execute(user);
}
}
Because processor can have first type argument of anything. You may have assigned a Process<Foo, String> to it, and of course compiler will complain as it can be something different from P in your execute().
You may want to make your Executor a generic class:
class Executor<T> {
private Processer<T, String> processer;
public void setProcesser(Processer<T, String> processer) {
this.processer = processer;
}
public void execute(T parent) {
processer.process(parent, generateString());
}
}
and your main will look like:
Executor<User> executor = new Executor<User>();
executor.setProcesser(new FirstProcesser());
User user = new User();
executor.execute(user);
In response to comments:
There is no proper solution with proper use of Generics here, because what you are doing is contradicting: On one hand you say you do not care about first type argument of Processor (hence private Processor<?, String> processor), but on the other hand you DO really care about it (your execute). Compiler is simply doing its work right as it is absolutely legal for you to assign a Processor<Foo,String> to it.
If you don't really care about generics and is willing to suffer from poor design, then don't use generics.
Just keep Processor a raw type in Executor and suppress all unchecked warning:
i.e.
class Executor {
private Processor processor;
#SuppressWarnings("unchecked")
public void setProcessor(Processor<?, String> processor) {
this.processor = processor;
}
// your generic method does not do any meaningful check.
// just pass an Object to it
#SuppressWarnings("unchecked")
public void execute(Object parent) {
processor.process(parent, "");
}
}
And if it is me, I will go one step further:
Provide an Executor that is properly designed (e.g. calling it TypedExecutor). All new code should use the new, properly designed TypedExecutor. Original Executor is kept for sake of backward compatibility, and delegate its work to TypedExecutor.
Hence look like:
class TypedExecutor<T> {
private Processor<T, String> processor;
public void setProcessor(Processor<T, String> processor) {
this.processor = processor;
}
public void execute(T parent) {
processor.process(parent, "");
}
}
#SuppressWarnings("unchecked")
class Executor {
private TypedExecutor executor = new TypedExecutor();
public void setProcessor(Processor<?, String> processor) {
this.executor.setProcessor(processor);
}
public void execute(Object parent) {
this.executor.execute(parent);
}
}

Java - Calling method from child of abstract class

Given the following abstract class:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
and the following child class:
public class VersionResponseV1 extends BaseVersionResponse<VersionVOV1>
{
protected String testFieldOne;
protected String testFieldTwo;
public String getTestFieldOne() {
return testFieldOne;
}
public void setTestFieldOne(String value) {
this.testFieldOne = value;
}
public String getTestFieldTwo() {
return testFieldTwo;
}
public void setTestFieldTwo(String value) {
this.testFieldTwo = value;
}
#Override
public void populate(VersionVOV1 versionVO) {
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
I desire to do something like this from a calling method:
public void getVersionInfo(String version) {
BaseVO versionVO = null;
BaseVersionResponse<? extends BaseVO> baseVersionResponse = null;
baseVersionResponse = createVersionResponse(version);
versionVO = createVersionVO(version);
baseVersionResponse.populate(versionVO);
}
where createVersionResponse(...) and createVersionVO(...) look like this:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) {
BaseVersionResponse<? extends BaseVO> specificVersionResponse = null;
if (version.equalsIgnoreCase("V1")) {
specificVersionResponse = new VersionResponseV1();
} else if (version.equalsIgnoreCase("V2"))
specificVersionResponse = new VersionResponseV2();
return specificVersionResponse;
}
public BaseVO createVersionVO(String version) {
BaseVO versionVO = null;
if (version.equalsIgnoreCase("V1")) {
versionVO = new VersionVOV1();
} else if (version.equalsIgnoreCase("V2"))
versionVO = new VersionVOV2();
return versionVO;
}
and VersionVOV1 looks like this:
public class VersionVOV1 extends BaseVO {
private String fieldOne = null;
private String fieldTwo = null;
private String fieldThree = null;
public String getFieldOne() {
return fieldOne;
}
public void setFieldOne(String fieldOne) {
this.fieldOne = fieldOne;
}
public String getFieldTwo() {
return fieldTwo;
}
public void setFieldTwo(String fieldTwo) {
this.fieldTwo = fieldTwo;
}
public String getFieldThree() {
return fieldThree;
}
public void setFieldThree(String fieldThree) {
this.fieldThree = fieldThree;
}
}
My problem arises when I try to compile this line of code:
baseVersionResponse.populate(versionVO);
in getVersionInfo(...). I'm getting a message that looks like this:
The method populate(capture#3-of ?) in the type BaseVersionResponse is not applicable for the arguments (BaseVO)
on the populate method above.
My thought was (which is apparently incorrect) that since the baseVersionResponse is, at this point in the code, actually a specific child instance, that the class would know exactly which populate method to call from that specific child class.
What am I doing wrong here? Is there a better way to do this if this isn't the correct approach?
Thank you for your time!
Ok, I took a better look at this today. The problem is that the wildcard, while the right way to go, precludes you from doing:
BaseVO versionVO = createVersionVO(version);
Because the populate call wants an extension of BaseVO, not an actual BaseVO, which doesn't qualify. That means you can't pass that versionVO variable directly.
So, to keep the type checking in place, which I think is good because you'll always want an implementation, leave pretty much everything as-is above, and change your BaseVersionResponse class to something like:
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
So, populate method now takes a BaseVO, and there's a new getVersion method to do some explicit casting for us. This should be ok since we know that the factory will always supply the right thing, but if another caller doesn't, an IllegalArgumentException is thrown.
Now, in your response class implementation, change the populate method accordingly:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
So, we've changed the populate method to take BaseVO, and the getVersion method does the casting for us. All the other type checks still apply, and we're good to go.
The casting makes it feel not as clean, but for the factory approach you're using, it's really the only way (I can think of) to keep the guarantees made by the type declarations and the code pattern in tact.
Hope that helps!
If you just take out the capture of type (the "<?>"), and leave it unchecked, it should work just fine. Even using type Object would have compiled.
But, given your specific example, what you probably want is the method:
public BaseVersionResponse<?> createVersionResponse(String version)
Changed to:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
Then, instead of using
BaseVersionResponse<?>
use
BaseVersionResponse<? extends BaseVO>
Since you know that the return type will be one of those things that implements the interface/class.

Generic static factory

I am getting a compilation error. I want my static method here to return a factory that creates and return Event<T> object. How can I fix this?
import com.lmax.disruptor.EventFactory;
public final class Event<T> {
private T event;
public T getEvent() {
return event;
}
public void setEvent(final T event) {
this.event = event;
}
public final static EventFactory<Event<T>> EVENT_FACTORY = new EventFactory<Event<T>>() {
public Event<T> newInstance() {
return new Event<T>();
}
};
}
Generic parameters of a class do not apply to static members.
The obvious solution is to use a method rather than a variable.
public static <U> EventFactory<Event<U>> factory() {
return new EventFactory<Event<U>>() {
public Event<U> newInstance() {
return new Event<U>();
}
};
}
The syntax is more concise in the current version of Java.
It is possible to use a the same instance of EventFactory stored in a static field, but that requires an unsafe cast.
You have:
public final class Event<T> {
...
public final static EventFactory<Event<T>> EVENT_FACTORY = ...
}
You cannot do this. T is a type that is associated with a specific instance of an Event<T>, and you cannot use it in a static context.
It's hard to give you good alternate options without knowing more about what exactly you are trying to do, as this is sort of an odd-looking factory implementation. I suppose you could do something like (put it in a method instead):
public final class Event<T> {
...
public static <U> EventFactory<Event<U>> createEventFactory () {
return new EventFactory<Event<U>>() {
public Event<U> newInstance() {
return new Event<U>();
}
};
};
}
And invoke it like:
EventFactory<Event<Integer>> factory = Event.<Integer>createEventFactory();
Or, if you don't want to be explicit (you don't really need to be, here):
EventFactory<Event<Integer>> factory = Event.createEventFactory();
Why don't you get rid of the whole static member of Event thing and either keep the factories separate, e.g.:
public final class GenericEventFactory<T> extends EventFactory<Event<T>> {
#Override public Event<T> newInstance() {
return new Event<T>();
}
}
And use, e.g., new GenericEventFactory<Integer>() where appropriate?

Creating a Class with specific methods in Java

I have 10 specific methods on my code, and I want to use them with a Class Object like this one:
void function(){
//do Something that I want
}
class PoseAction{
Pose pose;
void methodDesirable();
PoseAction(Pose ps, Method function()){
this.pose = ps;
this.methodDesirable() = function();
}
}
So when I create a new Object
PoseAction ps = new PoseAction(pose1, action1());
calling
ps.methodDesirable();
it will call action1() function.
It's possible to do this?
Thanks in advance!
Functions are not first class objects in java. That is, you can not directly assign them or pass them as method parameters. You need to use objects and interfaces:
interface Action {
void fire(Pose pose);
}
class PoseAction {
Action action;
Pose pose;
void methodDesirable() {
action.fire(pose)
}
PoseAction(Pose ps, Action a) {
pose = ps;
action = a;
}
}
And use it like:
PoseAction ps = new PoseAction(pose1, new Action() {
public void fire(Pose pose) {
action1(pose);
}
};
ps.methodDesirable();
No it's not possible in such way, Java doesn't support delegates. In java that can be done with interfaces:
interface Command {
void doCommand();
}
PoseAction pa = new PoseAction(new Pose(), new Command() {
#Override
public void doCommand() {
//method body
}
});
Here new Command() {...} is anonymous inner class that implements Command Interface

Categories

Resources