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.
Related
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.
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).
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 :)
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.
I'm using Ninject 1.0 and would like to be able to inject lazy initialisation delegates into constructors. So, given the generic delegate definition:
public delegate T LazyGet<T>();
I'd simply like to bind this to IKernel.Get() so that I can pass a lazy getter into constructors, e.g.
public class Foo
{
readonly LazyGet<Bar> getBar;
public Foo( LazyGet<Bar> getBar )
{
this.getBar = getBar;
}
}
However, I can't simply call Bind<LazyGet<T>>() because it's an open generic type. I need this to be an open generic so that I don't have to Bind all the different lazy gets to explicit types. In the above example, it should be possible to create a generic delegate dynamically that invokes IKernel.Get<T>().
How can this be achieved with Ninject 1.0?
Don't exactly understand the question, but could you use reflection? Something like:
// the type of T you want to use
Type bindType;
// the kernel you want to use
IKernel k;
// note - not compile tested
MethodInfo openGet = typeof(IKernel).GetMethod("Get`1");
MethodInfo constGet = openGet.MakeGenericMethod(bindType);
Type delegateType = typeof(LazyGet<>).MakeGenericType(bindType);
Delegate lazyGet = Delegate.CreateDelegate(delegateType, k, constGet);
Would using lazyGet allow you to do what you want? Note that you may have to call the Foo class by reflection as well, if bindType isn't known in the compile context.
I am fairly certain that the only way to do this (without some dirty reflection code) is to bind your delegate with type params. This will mean it needs to be done for each individual type you use. You could possibly use a BindingGenerator to do this in bulk, but it could get a bit ugly.
If there is a better solution (a clean one) I would love to hear it as I run into this problem from time to time.
From another similar question I answered:
public class Module : NinjectModule
{
public override void Load()
{
Bind(typeof(Lazy<>)).ToMethod(ctx =>
GetType()
.GetMethod("GetLazyProvider", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(ctx.GenericArguments[0])
.Invoke(this, new object[] { ctx.Kernel }));
}
protected Lazy<T> GetLazyProvider<T>(IKernel kernel)
{
return new Lazy<T>(() => kernel.Get<T>());
}
}