Ambigous situation when using varargs - java-7

I have two methods:
addMsg(String summary, String msg, Object... params)
addMsg(String msg, Object... params)
Which one will be called when execute addMsg("str1", "str2", "str3") ?
Can I choose which one to be used?

Which one will be called when execute addMsg("str1", "str2", "str3") ?
The long version will be called:
public void addMsg(String summary, String msg, Object... params)
Can I choose which one to be used?
If you really can't change the method names to have an intention-revealing name or change the signature by changing the types (e.g. you are dealing with a legacy application), you can always invoke the short version by using reflection:
Method hiddenMethod = Arrays.stream(this.getClass().getDeclaredMethods())
.filter(method -> "addMsg".equals(method.getName()))
.filter(method -> method.getParameterTypes().length == 2)
.findFirst()
.orElseThrow(IllegalStateException::new);
Object[] params = { "message" , new String[]{"param1", "param2"}};
hiddenMethod.invoke(this,params);
But never do this if you can avoid this scenario.

I actually think this is a misuse of varargs.
What I suggest you to do is
addMsg(Integer type, Object... params)
You'd better differentiate the treatment to do using a different variable (integer, as I proposed).

Related

Spring Cloud Function - how to pass multiple parameters to a function call in Kotlin

In the documentation for Spring Cloud Function, the examples for Kotlin consist of function that takes a single parameter, e.g.
#Bean
open fun lower(): (String) -> String = { it.lowercase() }
which is called via a URL that has the single parameter on the end as so:
http://localhost/lower/UpperCaseParam
How can more than one parameter be passed ?
Is something like this supported ?
#Bean
open fun upper(): (String,String) -> String = { x,y -> x+y }
or if not multiple parameters, an object ?
#Bean
open fun upper(): (Pair<String,String>) -> String = { it.first+it.second }
Function by definition has only a single input/output. Even if we were to add support for BiFunction that would only satisfy cases where you have two inputs etc.
The best way to achieve what you want is to use Message Headers which you can pass as HTTP headers.
Then you can make your function signature to accept Function<Message<YourPOJOType>, ...> uppercase(); and then get payload (your main argument, such as request param) and headers from Message.
You can use BiFunction where second argument would be Map representing message headers and first argument payload. This way you can deal with your types and keep your function completely free from anything Spring. BiFunction<YourPOJOType, Map, ...>

Return an item by id

I got this piece of code, I am learning from tutorial. I want to return an element by url which looks like clients/1 instead of clients?id=1. How can I achieve this? Also, can the code below be made easier way?
#GetMapping
public Client getClient(#RequestParam int id) {
Optional<Client> first = clientList.stream().filter(element -> element.getId() == id).findFirst();
return first.get();
}
You may want to use #PathVariable as follows:
#Controller
#RequestMapping("/clients")
public class MyController {
#GetMapping("/{id}")
public Client getClient(#PathVariable int id) {
return clientList.stream().filter(element -> element.getId() == id).findFirst().orElseThrow();
}
Please note, the Optional can be unpacked with orElseThrow method. This will throw a NoSuchElementException in case there is no element found for the id.
Other solution would be to use orElse(new Client(...)) to return a default value if nothing is found.
get() is not really recommended to be used. From the JavaDoc of the get() method:
API Note:
The preferred alternative to this method is orElseThrow().
Even though get() may also throw a NoSuchElementException, similar to orElseThrow, usually the consensus is that get should not be used without isPresent, or should not be used at all. There several other methods to unpack the Optional without forcing you write an if.
The whole idea of the Optional is to overcome this by forcing you to think about the case when there is no value inside.

Pass optional objects as varags in parameter?

I want to pass multiple optional objects in function as varags ?
Optional<ab> ab = Optional.of(ab);
Optional<cd> cd = Optional.of(cd);
Optional<dc> dc = Optional.of(dc);
Optional<ba> ba = Optional.of(ba);
data(ab, cd, dc, ba);
data(Optional<Object>... objects){...}
I am getting error if i don this, any suggestion how can be proceed?
It isn’t related to varargs. You can’t pass an Optional<SomeSpecificType> where an Optional<Object> is expected. They are not compatible.
Assume just (without varargs):
static void data(Optional<Object> object) {
// …
}
Now if we try
Optional<String> ab = Optional.of("");
data(ab);
In my Eclipse I get this error message:
The method data(Optional<Object>) in the type MyClass is not
applicable for the arguments (Optional<String>)
Java generics are defined with this restriction. You also cannot pass, for example a List<String> where a List<Object> is expected.
You can overcome the limitation by declaring the method generic too:
static <T> void data(Optional<T> object) {
// …
}
Or just like this:
static void data(Optional<?> object) {
// …
}
With any of these two declarations the call above is OK.
BTW, #HadiJ is correct in the comment: Optional is meant for return values for from methods that may or may not be there. They have very few other good uses, and as parameters is not one of them. It seems to me that for your use case you should just pass the arguments that are there and leave out those that aren’t. The your data method may receive a longer or shorter argument array, but will just have to handle all elements of the array without caring about Optional. And passing String, Integer, LocalDate, etc, to a method declared void data(Object... objs) is straightforward and poses no problem.

Return method reference

I am playing around in Java 8. How can I return a method reference?
I am able to return a lambda but not the method reference.
My attempts:
public Supplier<?> forEachChild(){
return new ArrayList<?>::forEach;
}
OR
public Function<?> forEachChild(){
return new ArrayList<?>::forEach;
}
You have a small mis-understanding of how method-references work.
First of all, you cannot new a method-reference.
Then, let's reason through what you want to do. You want the method forEachChild to be able to return something that would accept a List and a Consumer. The List would be on which object to invoke forEach on, and the Consumer would be the action to perform on each element of the list. For that, you can use a BiConsumer: this represents an operation taking 2 parameters and returning no results: the first parameter is a list and the second parameter is a consumer.
As such, the following will work:
public <T> BiConsumer<List<T>, Consumer<? super T>> forEachChild() {
return List::forEach;
}
This type of method-reference is called "Reference to an instance method of an arbitrary object of a particular type". What happens is that the first parameter of type List<T> becomes the object on which forEach will be invoked, by giving it as parameter the Consumer.
Then you can use it like:
forEachChild().accept(Arrays.asList("1", "2"), System.out::println);
I would like to add some points.
You can't instantiate unbounded type instance.
List<?> list = new ArrayList<?>();
Second, as Tunaki mentioned, you can't make references to new MyObject::staticMethod when you make method references
The other thing is, forEach(Consumer<T> consumer) (Terminal operation for pipeline streams) doesn't return anything. It only eats whatever we feed it.
-Hope this may help :)

Is there any way to clean up the following generic method using any of the new C# 4 features?

I've just modified a method for handling my DDD commands (previously it had no return type):
public static CommandResult<TReturn> Execute<TCommand, TReturn>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
The method is fine, and does what I want it to do, however using it creates some fugly code:
CommandResult<Customer> result =
DomainCommands.Execute<CustomerCreateCommand, Customer>
(
new CustomerCreateCommand(message)
);
Before I added the Customer return type TReturn, it was nice and tidy and the method could infer the types from its usage. However that's no longer possible.
Is there any way using any new C# features that I could rewrite the above to make it tidier, i.e. using Func, Action, Expression, etc? I'm probably expecting the impossible, but I'm getting fed up of writing so much code to just call a single method that used to be very simple.
One option to reduce it slightly is to have a static generic type for the type parameter that can't be inferred, allowing you to have a generic method with just one type parameter that can be inferred:
public static class DomainCommands<TReturn>
{
public static CommandResult<TReturn> Execute<TCommand>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
}
Then:
var result = DomainCommands<Customer>.Execute(new CustomerCreateCommand(msg));
It's not much nicer, but it's slightly better. Of course, if the domain command type itself could be generic, that might help - so CustomerCreateCommand would implement IDomainCommand<Customer> for example. If you still needed a nongeneric IDomainCommand, you could make IDomainCommand<T> derive from IDomainCommand.

Resources