Technical reason for no default parameters in Java - java

I've been looking around to try to find what the reasoning is behind not including default parameters for functions in Java.
I'm aware that it's possible to simulate the behavior, either with varargs or else by creating several overloaded functions that accept fewer parameters, and call the real function that takes all parameters. However, neither of these options match the clarity and ease-of-use of, e.g. C++'s syntax.
Does anyone know if there's a solid technical reason that would make something like
void myFunc(int a=1, int b=2) {...}
undesirable or undo-able in a new version of Java?

It was not in the initial version of Java because they decided they did not need it, probably to keep things simple.
Adding it now would be tricky, because it needs to be done in a backwards-compatible fashion. Adding varargs, autoboxing and generics in Java5 was a major undertaking, and it could only be done with limited functionality (such as type erasure) and at the cost of increased complexity (the new method resolution rules make for good exam trick questions).
Your best shot would be with a non-Java language on the JVM. Maybe one of them already has this.

I am not aware of a technical reason, apart from it being complicated which values are being omitted and which ones are not.
For example, in your sample, if only one integer was passed through then is it a or b that should be defaulted? Most probably a but it does add that level of ambiguity.
A simple solution would be to
void myFunc(Integer a, Integer b) {
if (a == null) a = 1;
if (b == null) b = 2;
}
Yes it is more long winded, and yes it hides the defaulting within the code, rather than the method signature (which could then be shown in JavaDoc), but it does enforce the consistency.

I agree that optional arguments would add huge clarity and save the huge work of defining loads of overloaded methods (called telescoping), which do nothing than call each other. However, the enabler for this neat feature is passing arguments by name.
Named association is self-documenting. In contrast, positional argument association is concise but it makes you to refer the definition of method all the time to check which argument is expected in nth position at every invocation. This is ridiculous and motivates us to search for solutions like Builder pattern. The Builder actually solves both problems at once because named association is a synonym for optional arguments. But Builder is useful only for user. API designer still must waste space/time to create the Builder class. Pattern bigots might disagree but it is an overkill to create a Builder class for every method with named/optional arguments. Language design should obviate this stupid pattern. But, I do not know how compatible they are with the variable argument list.

To Avoid Ambiguity. Java Support Method Override.
We assume the code below:
public int add(int a) {
// do something
}
public int add(int a, int b = 0) {
// do something
}
When we call add(12), Can you tell me which function is invoked?

Related

Why Kotlin doesn't have explicit typing?

I am curious about this, why would kotlin designers think this would be a good idea to drop explicit typing in Kotlin ?
To me, explicit typing is not a "pain" to write in Java (or any other strongly typed language) : all IDE can assist me to automaticaly type my variable.
It adds great understanding of the code (that's why I don't like weakly-typed languages, I have no idea what kind of variables I'm dealing with).
Also, and this is my main issue with that, it makes the code more bug-prone.
Example :
Java : Easily identified as a String, all good
String myPrice = someRepository.getPrice(); // Returns a String
myTextView.setText(myPrice);
Java : Easily identified as an int, code smell with setText()
int myPrice = someRepository.getPrice(); // Returns an int, code smell !!
myTextView.setText(String.valueOf(myPrice)); // Problem avoided
Kotlin : ????
val myPrice = someRepository.getPrice(); // What does it return ?
myTextView.setText(myPrice); // Possible hidden bug with setText(#StringRes int) instead of setText(String) !!
No explicit typing in Kotlin is the biggest drawback in Kotlin imo. I try to understand this design choice.
I'm not really looking for "patches" to fix the example / avoid the presented code smell, I try to understand the main reason behind the removal of explicit typing. It has to be more than "less typing / easier to read". It only removes a couple of characters (one still have to write val / var), and explicit typing in Kotlin adds some caracters anyway...
Static typing without explicit typing is, to me, the worst case scenario to deal with hidden bugs / spaghetti bugs : if one class (let's say "Repository") changes it return type (from String to int for example). With explicit typing, compilation would fail at the class calling "Repository". Without explicit typing, compilation may not fail and the wrong type of variable may "travel" through classes and change the behavior of the classes because of its type. This is dangerous and undetected.
The fix is easy ; explicitly type the variable. But this is Kotlin we're speaking, a language made for code golfers : people won't explicitely type their variables, as it takes even more time to do so in kotlin than turtle-java. Yikes!
First of all: Kotlin has static typing. The compiler knows exactly which type goes or comes where. And you are always free to write that down, like
fun sum(a: Int, b: Int): Int {
val c: Int = 1
The point is: you can write a lot of code that simply relies on the fact that anything you do is statically typed, and type checked, too!
Do you really need to know whether you are adding two doubles or two ints or two longs, when all you "care" to look at is a + b?
In the end, this is about balancing different requirements. Leaving out the type can be helpful: less code that needs to be read and understood by human readers.
Of course: if you write code so that people constantly turn to their IDE for the IDE to tell them the actual, inferred type of something, then you turned a helpful feature into a problem!
The real answer here is: it depends. I have been in many code reviews where C++ people discussed the use of the auto keyword. There were a lot of situations, where using auto did make the code much easier to read and understand, because you could focus on "what happens with the variable", instead of looking 1 minute at its declaration, trying to understand its type. But there were also occasional examples where auto achieved the exact opposite, and a "fully typed" declaration was easier to follow.
And given the comment by the OP: you should know what you are doing in the first place. Meaning: when you write code, you don't just invoke "any" method that you find on some object. You call a method because you have to. You better know what it does, and what it returns to you. I agree, when someone is in a rush, you quickly var-assign and then pass that thing along, that might lead to errors. But for each situation where var helps with creating a bug, there might be 10 incidents where it helps writing easier to read code. As said: life is about balancing.
Finally: languages shouldn't add features for no reason. And the Kotlin people are carefully balancing features they add. They didn't add type inference because C++ has it. They added it because they carefully researched other languages and found it to be useful to be part of the language. Any language feature can be misused. It is always up to the programmer to write code that is easy to read and understand. And when your methods have unclear signatures, so "reading" their names alone doesn't tell you what is gong on, then blame that on the method name, not on type inference!
To quote Java's Local-Variable Type Inference JEP:
In a call chain like:
int maxWeight = blocks.stream()
.filter(b -> b.getColor() == BLUE)
.mapToInt(Block::getWeight)
.max();
no one is bothered (or even notices) that the intermediate types Stream<Block> and IntStream, as well as the type of the lambda formal b, do not appear explicitly in the source code.
Are you bothered about it?
if one class (let's say "Repository") changes it return type (from String to int for example). With explicit typing, compilation would fail at the class calling "Repository".
If you have overloads like setText in your example, then
Repository repository = ...;
myTextView.setText(repository.getFormerlyStringNowInt());
won't fail without type inference either. To make it fail, your code standard has to require every operation's result to be assigned to a local variable, as in
Stream<Block> stream1 = blocks.stream();
Predicate<Block> pred = b -> {
Color c = b.getColor();
return c == BLUE;
};
Stream<Block> stream2 = stream1.filter(pred);
ToIntFunction<Block> getWeight = Block::getWeight;
IntStream stream3 = stream2.mapToInt(getWeight);
int maxWeight = stream3.max();
And at this point you make bugs easier just from decreased readability and the chance to accidentally use the wrong variable.
Finally, Kotlin wasn't created in a vacuum: the designers could see that when C# introduced local type inference in 2007, it didn't lead to significant problems. Or they could look at Scala, which had it since the beginning in 2004; it had (and has) plenty of user complaints, but local type inference isn't one of them.

Passing Optional arguments to Java methods [duplicate]

I've read on many Web sites Optional should be used as a return type only, and not used in method arguments. I'm struggling to find a logical reason why. For example I have a piece of logic which has 2 optional parameters. Therefore I think it would make sense to write my method signature like this (solution 1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2) {
// my logic
}
Many web pages specify Optional should not be used as method arguments. With this in mind, I could use the following method signature and add a clear Javadoc comment to specify that the arguments may be null, hoping future maintainers will read the Javadoc and therefore always carry out null checks prior to using the arguments (solution 2):
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Alternatively I could replace my method with four public methods to provide a nicer interface and make it more obvious p1 and p2 are optional (solution 3):
public int calculateSomething() {
calculateSomething(null, null);
}
public int calculateSomething(String p1) {
calculateSomething(p1, null);
}
public int calculateSomething(BigDecimal p2) {
calculateSomething(null, p2);
}
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Now I try writing the code of the class which invokes this piece of logic for each approach. I first retrieve the two input parameters from another object which returns Optionals and then, I invoke calculateSomething. Therefore, if solution 1 is used the calling code would look like this:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
if solution 2 is used, the calling code would look like this:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
if solution 3 is applied, I could use the code above or I could use the following (but it's significantly more code):
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
if (p2.isPresent()) {
result = myObject.calculateSomething(p1, p2);
} else {
result = myObject.calculateSomething(p1);
}
} else {
if (p2.isPresent()) {
result = myObject.calculateSomething(p2);
} else {
result = myObject.calculateSomething();
}
}
So my question is: Why is it considered bad practice to use Optionals as method arguments (see solution 1)? It looks like the most readable solution to me and makes it most obvious that the parameters could be empty/null to future maintainers. (I'm aware the designers of Optional intended it to only be used as a return type, but I can't find any logical reasons not to use it in this scenario).
Oh, those coding styles are to be taken with a bit of salt.
(+) Passing an Optional result to another method, without any semantic analysis; leaving that to the method, is quite alright.
(-) Using Optional parameters causing conditional logic inside the methods is literally contra-productive.
(-) Needing to pack an argument in an Optional, is suboptimal for the compiler, and does an unnecessary wrapping.
(-) In comparison to nullable parameters Optional is more costly.
(-) The risk of someone passing the Optional as null in actual parameters.
In general: Optional unifies two states, which have to be unraveled. Hence better suited for result than input, for the complexity of the data flow.
The best post I've seen on the topic was written by Daniel Olszewski:
Although it might be tempting to consider Optional for not mandatory method parameters, such a solution pale in comparison with other possible alternatives. To illustrate the problem, examine the following constructor declaration:
public SystemMessage(String title, String content, Optional<Attachment> attachment) {
// assigning field values
}
At first glance it may look as a right design decision. After all, we
explicitly marked the attachment parameter as optional. However, as
for calling the constructor, client code can become a little bit
clumsy.
SystemMessage withoutAttachment = new SystemMessage("title", "content", Optional.empty());
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", Optional.ofNullable(attachment));
Instead of providing clarity, the factory methods of the Optional
class only distract the reader. Note there’s only one optional
parameter, but imagine having two or three. Uncle Bob definitely
wouldn’t be proud of such code 😉
When a method can accept optional parameters, it’s preferable to adopt the well-proven approach and design such case using method
overloading. In the example of the SystemMessage class, declaring
two separate constructors are superior to using Optional.
public SystemMessage(String title, String content) {
this(title, content, null);
}
public SystemMessage(String title, String content, Attachment attachment) {
// assigning field values
}
That change makes client code much simpler and easier to read.
SystemMessage withoutAttachment = new SystemMessage("title", "content");
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", attachment);
There are almost no good reasons for not using Optional as parameters. The arguments against this rely on arguments from authority (see Brian Goetz - his argument is we can't enforce non null optionals) or that the Optional arguments may be null (essentially the same argument). Of course, any reference in Java can be null, we need to encourage rules being enforced by the compiler, not programmers memory (which is problematic and does not scale).
Functional programming languages encourage Optional parameters. One of the best ways of using this is to have multiple optional parameters and using liftM2 to use a function assuming the parameters are not empty and returning an optional (see http://www.functionaljava.org/javadoc/4.4/functionaljava/fj/data/Option.html#liftM2-fj.F-). Java 8 has unfortunately implemented a very limited library supporting optional.
As Java programmers we should only be using null to interact with legacy libraries.
Let's make something perfectly clear: in other languages, there is no general recommendation against the use of a Maybe type as a field type, a constructor parameter type, a method parameter type, or a function parameter type.
So if you "shouldn't" use Optional as a parameter type in Java, the reason is specific to Optional, to Java, or to both.
Reasoning that might apply to other Maybe types, or other languages, is probably not valid here.
Per Brian Goetz,
[W]e did have a clear
intention when adding [Optional], and it was not to be a general
purpose Maybe type, as much as many people would have liked us to do
so. Our intention was to provide a limited mechanism for library
method return types where there needed to be a clear way to represent
"no result", and using null for such was overwhelmingly likely to
cause errors.
For example, you probably should never use it for something that
returns an array of results, or a list of results; instead return an
empty array or list. You should almost never use it as a field of
something or a method parameter.
So the answer is specific to Optional: it isn't "a general purpose Maybe type"; as such, it is limited, and it may be limited in ways that limit its usefulness as a field type or a parameter type.
That said, in practice, I've rarely found using Optional as a field type or a parameter type to be an issue. If Optional, despite its limitations, works as a parameter type or a field type for your use case, use it.
The pattern with Optional is for one to avoid returning null. It's still perfectly possible to pass in null to a method.
While these aren't really official yet, you can use JSR-308 style annotations to indicate whether or not you accept null values into the function. Note that you'd have to have the right tooling to actually identify it, and it'd provide more of a static check than an enforceable runtime policy, but it would help.
public int calculateSomething(#NotNull final String p1, #NotNull final String p2) {}
This advice is a variant of the "be as unspecific as possible regarding inputs and as specific as possible regarding outputs" rule of thumb.
Usually if you have a method that takes a plain non-null value, you can map it over the Optional, so the plain version is strictly more unspecific regarding inputs. However there are a bunch of possible reasons why you would want to require an Optional argument nonetheless:
you want your function to be used in conjunction with another API that returns an Optional
Your function should return something other than an empty Optional if the given value is empty
You think Optional is so awesome that whoever uses your API should be required to learn about it ;-)
Check out the JavaDoc in JDK10, https://docs.oracle.com/javase/10/docs/api/java/util/Optional.html, an API note is added:
API Note:
Optional is primarily intended for use as a method return type where there is a clear need to represent "no result," and where using null is likely to cause errors.
Maybe I will provoke a bunch of down-votes and negative comments, but... I cannot stand.
Disclaimer: what I write below is not really an answer to the original question, but rather my thoughts on the topic. And the only source for it is my thoughts and my experience (with Java and other languages).
First let's check, why would anyone like to use Optional at all?
For me the reason is simple: unlike other languages java does not have built-in capability to define variable (or type) as nullable or not. All "object"-variables are nullable and all primitive-types are not. For the sake of simplicity let't not consider primitive types in further discussion, so I will claim simply that all variables are nullable.
Why would one need to declare variables as nullable/non-nullable? Well, the reason for me is: explicit is always better, than implicit. Besides having explicit decoration (e.g. annotation or type) could help static analyzer (or compiler) to catch some null-pointer related issues.
Many people argue in the comments above, that functions do not need to have nullable arguments. Instead overloads should be used. But such statement is only good in a school-book. In real life there are different situations. Consider class, which represents settings of some system, or personal data of some user, or in fact any composite data-structure, which contains lots of fields - many of those with repeated types, and some of the fields are mandatory while others are optional. In such cases inheritance/constructor overloads do not really help.
Random example: Let's say, we need to collect data about people. But some people don't want to provide all the data. And of course this is POD, so basically type with value-semantics, so I want it to be more or less immutable (no setters).
class PersonalData {
private final String name; // mandatory
private final int age; // mandatory
private final Address homeAddress; // optional
private final PhoneNumber phoneNumber; // optional. Dedicated class to handle constraints
private final BigDecimal income; // optional.
// ... further fields
// How many constructor- (or factory-) overloads do we need to handle all cases
// without nullable arguments? If I am not mistaken, 8. And what if we have more optional
// fields?
// ...
}
So, IMO discussion above shows, that even though mostly we can survive without nullable arguments, but sometimes it is not really feasible.
Now we come to the problem: if some of the arguments are nullable and others are not, how do we know, which one?
Approach 1: All arguments are nullable (according to java standrd, except primitive types). So we check all of them.
Result: code explodes with checks, which are mostly unneeded, because as we discussed above almost all of the time we can go ahead with nullable variables, and only in some rare cases "nullables" are needed.
Approach 2: Use documentation and/or comments to describe, which arguments/fields are nullable and which not.
Result: It does not really work. People are lazy to write and read the docs. Besides lately the trend is, that we should avoid writing documentation in favor of making the code itself self-describing. Besides all the reasoning about modifying the code and forgeting to modify the documentation is still valid.
Approach 3: #Nullable #NonNull etc... I personally find them to be nice. But there are certain disadvantages : (e.g. they are only respected by external tools, not the compiler), the worst of which is that they are not standard, which means, that 1. I would need to add external dependency to my project to benefit from them, and 2. The way they are treated by different systems are not uniform. As far as I know, they were voted out of official Java standard (and I don't know if there are any plans to try again).
Approach 4: Optional<>. The disadvantages are already mentioned in other comments, the worst of which is (IMO) performance penalty. Also it adds a bit of boilerplate, even thoough I personally find, use of Optional.empty() and Optional.of() to be not so bad. The advantages are obvious:
It is part of the Java standard.
It makes obvious to the reader of the code (or to the user of API), that these arguments may be null. Moreover, it forces both: user of the API and developer of the method to aknolage this fact by explicitly wrapping/unwrapping the values (which is not the case, when annotations like #Nullable etc. are used).
So in my point, there is no black-and-white in regard of any methodology including this one. I personally ended up with the following guidelines and conventions (which are still not strict rules):
Inside my own code all the variables must be not-null (but probably Optional<>).
If I have a method with one or two optional arguments I try to redesign it using overloads, inheritance etc.
If I cannot find the solution in reasonable time, I start thinking, if the performance is critical (i.e. if there are millions of the objects to be processed). Usually it is not the case.
If not, I use Optional as argument types and/or field types.
There are still grey areas, where these conventions do not work:
We need high performance (e.g. processing of huge amounts of data, so that total execution time is very large, or situations when throughput is critical). In this cases performance penalty introduced by Optional may be really unwanted.
We are on the boundary of the code, which we write ourselves, e.g.: we read from the DB, Rest Endpoint, parse file etc.
Or we just use some external libraries, which do not follow our conventions, so again, we should be careful...
By the way, the last two cases can also be the source of need in the optional fields/arguments. I.e. when the structure of the data is not developed by ourselves, but is imposed by some external interfaces, db-schemas etc...
At the end, I think, that one should think about the problem, which is being solved, and try to find the appropriate tools. If Optional<> is appropriate, then I see no reason not to use it.
Edit: Approach 5: I used this one recently, when I could not use Optional. The idea is simply to use naming convention for method arguments and class variables. I used "maybe"-prefix, so that if e.g. "url" argument is nullable, then it becomes maybeUrl. The advantage is that it slightly improves understandability of the intent (and does not have disadvantages of other approaches, like external dependencies or performance penalty). But there are also drawbacks, like: there is no tooling to support this convention (your IDE will not show you any warning, if you access "maybe"-variable without first checking it). Another problem is that it only helps, when applied consistently by all people working on the project.
This seems a bit silly to me, but the only reason I can think of is that object arguments in method parameters already are optional in a way - they can be null. Therefore forcing someone to take an existing object and wrap it in an optional is sort of pointless.
That being said, chaining methods together that take/return optionals is a reasonable thing to do, e.g. Maybe monad.
Accepting Optional as parameters causes unnecessary wrapping at caller level.
For example in the case of:
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {}
Suppose you have two not-null strings (ie. returned from some other method):
String p1 = "p1";
String p2 = "p2";
You're forced to wrap them in Optional even if you know they are not Empty.
This get even worse when you have to compose with other "mappable" structures, ie. Eithers:
Either<Error, String> value = compute().right().map((s) -> calculateSomething(
< here you have to wrap the parameter in a Optional even if you know it's a
string >));
ref:
methods shouldn't expect Option as parameters, this is almost always a
code smell that indicated a leakage of control flow from the caller to
the callee, it should be responsibility of the caller to check the
content of an Option
ref. https://github.com/teamdigitale/digital-citizenship-functions/pull/148#discussion_r170862749
My take is that Optional should be a Monad and these are not conceivable in Java.
In functional programming you deal with pure and higher order functions that take and compose their arguments only based on their "business domain type". Composing functions that feed on, or whose computation should be reported to, the real-world (so called side effects) requires the application of functions that take care of automatically unpacking the values out of the monads representing the outside world (State, Configuration, Futures, Maybe, Either, Writer, etc...); this is called lifting. You can think of it as a kind of separation of concerns.
Mixing these two levels of abstraction doesn't facilitate legibility so you're better off just avoiding it.
Another reason to be carefully when pass an Optional as parameter is that a method should do one thing... If you pass an Optional param you could favor do more than one thing, it could be similar to pass a boolean param.
public void method(Optional<MyClass> param) {
if(param.isPresent()) {
//do something
} else {
//do some other
}
}
So, if you would permit the pun, Oracle issued an oracle:
Thou shalt not use Optional but for function return values.
I love it how most of the answers so far are going along with the narrative of Oracle's oracle, which is re-iterated unquestioned all over the interwebz, in the "many Web sites" mentioned in the question. This is very typical of stack overflow: if something is allegedly supposed to be a certain way, and you ask why it is supposed to be that way, almost everyone will offer reasons why; almost nobody will question whether it should in fact be that way.
So, here is a dissenting opinion:
You can use Optional to completely eliminate null from your code base.
I have done it in a 100k-lines-of-code project. It worked.
If you decide to go along this path, then you will need to be thorough, so you will have a lot of work to do. The example mentioned in the accepted answer with Optional.ofNulable() should never occur, because if you are thorough, then you should never have anything returning null, and therefore no need for Optional.ofNullable(). In that 100k-lines-of-code project that I mentioned above, I have only used Optional.ofNullable() a couple of times when receiving results from external methods that I have no control over.
Also, if you decide to go along this path, your solution will not be the most performant solution possible, because you will be allocating lots of optionals. However:
That's nothing but a runtime performance overhead disadvantage.
That's not a severe disadvantage.
That's Java's problem, not your problem.
Let me explain that last part.
Java does not offer explicit nullability of reference types as C# does (since version 8.0) so it is inferior in this regard. (I said "in this regard"; in other regards, Java is better; but that's off-topic right now.)
The only proper alternative to explicit nullability of reference types is the Optional type.
(And it is arguably even slightly better, because with Optional you can indicate optional-of-optional, if you must, whereas with explicit nullability you cannot have ReferenceType??, or at least you cannot in C# as it is currently implemented.)
Optional does not have to add overhead, it only does so in Java. That's because Java also does not support true value types, as C# and Scala do. In this regard, Java is severely inferior to those languages. (Again, I said "in this regard"; in other regards, Java is better; but that's off-topic right now.) If Java did support true value types, then Optional would have been implemented as a single machine word, which would mean that the runtime overhead of using it would be zero.
So, the question that it boils down to is: do you want perfect clarity and type safety in your code, or do you prefer maximum performance? I believe that for high-level languages, (of which Java certainly aims to be one,) this question was settled a long time ago.
I think that is because you usually write your functions to manipulate data, and then lift it to Optional using map and similar functions. This adds the default Optional behavior to it.
Of course, there might be cases, when it is necessary to write your own auxilary function that works on Optional.
I believe the reson of being is you have to first check whether or not Optional is null itself and then try to evaluate value it wraps. Too many unnecessary validations.
I know that this question is more about opinion rather than hard facts. But I recently moved from being a .net developer to a java one, so I have only recently joined the Optional party. Also, I'd prefer to state this as a comment, but since my point level does not allow me to comment, I am forced to put this as an answer instead.
What I have been doing, which has served me well as a rule of thumb. Is to use Optionals for return types, and only use Optionals as parameters, if I require both the value of the Optional, and weather or not the Optional had a value within the method.
If I only care about the value, I check isPresent before calling the method, if I have some kind of logging or different logic within the method that depends on if the value exists, then I will happily pass in the Optional.
Using Optional as parameters might be useful in some use cases which involves protobufs or setting fields in a configuration object.
public void setParameters(Optional<A> op1, Optional<B> op2) {
ProtoRequest.Builder builder = ProtoRequest.newBuilder();
op1.ifPresent(builder::setOp1);
op2.ifPresent(builder::setOp2);
...
}
I think in such cases it might be useful to have optional as parameters. API receiving the proto request would handle the different fields.
If a function is not doing additional computations on these parameters then using Optional might be simpler.
public void setParameters(A op1, B op2) {
ProtoRequest.Builder builder = ProtoRequest.newBuilder();
if (op1 != null) {
builder.setOp1(op1);
}
if (op2 != null) {
builder.setOp2(op2);
}
...
}
Optionals aren't designed for this purpose, as explained nicely by Brian Goetz.
You can always use #Nullable to denote that a method argument can be null. Using an optional does not really enable you to write your method logic more neatly.
One more approach, what you can do is
// get your optionals first
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
// bind values to a function
Supplier<Integer> calculatedValueSupplier = () -> { // your logic here using both optional as state}
Once you have built a function(supplier in this case) you will be able to pass this around as any other variable and would be able to call it using
calculatedValueSupplier.apply();
The idea here being whether you have got optional value or not will be internal detail of your function and will not be in parameter. Thinking functions when thinking about optional as parameter is actually very useful technique that I have found.
As to your question whether you should actually do it or not is based on your preference, but as others said it makes your API ugly to say the least.
At first, I also preferred to pass Optionals as parameter, but if you switch from an API-Designer perspective to a API-User perspective, you see the disadvantages.
For your example, where each parameter is optional, I would suggest to change the calculation method into an own class like follows:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
MyCalculator mc = new MyCalculator();
p1.map(mc::setP1);
p2.map(mc::setP2);
int result = mc.calculate();
This is because we have different requirements to an API user and an API developer.
A developer is responsible for providing a precise specification and a correct implementation. Therefore if the developer is already aware that an argument is optional the implementation must deal with it correctly, whether it being a null or an Optional. The API should be as simple as possible to the user, and null is the simplest.
On the other hand, the result is passed from the API developer to the user. However the specification is complete and verbose, there is still a chance that the user is either unaware of it or just lazy to deal with it. In this case, the Optional result forces the user to write some extra code to deal with a possible empty result.
First of all, if you're using method 3, you can replace those last 14 lines of code with this:
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
The four variations you wrote are convenience methods. You should only use them when they're more convenient. That's also the best approach. That way, the API is very clear which members are necessary and which aren't. If you don't want to write four methods, you can clarify things by how you name your parameters:
public int calculateSomething(String p1OrNull, BigDecimal p2OrNull)
This way, it's clear that null values are allowed.
Your use of p1.orElse(null) illustrates how verbose our code gets when using Optional, which is part of why I avoid it. Optional was written for functional programming. Streams need it. Your methods should probably never return Optional unless it's necessary to use them in functional programming. There are methods, like Optional.flatMap() method, that requires a reference to a function that returns Optional. Here's its signature:
public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)
So that's usually the only good reason for writing a method that returns Optional. But even there, it can be avoided. You can pass a getter that doesn't return Optional to a method like flatMap(), by wrapping it in a another method that converts the function to the right type. The wrapper method looks like this:
public static <T, U> Function<? super T, Optional<U>> optFun(Function<T, U> function) {
return t -> Optional.ofNullable(function.apply(t));
}
So suppose you have a getter like this: String getName()
You can't pass it to flatMap like this:
opt.flatMap(Widget::getName) // Won't work!
But you can pass it like this:
opt.flatMap(optFun(Widget::getName)) // Works great!
Outside of functional programming, Optionals should be avoided.
Brian Goetz said it best when he said this:
The reason Optional was added to Java is because this:
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
is cleaner than this:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
Irrespective of Java 8, Use old school method overloading technique to bring clarity and flexibility, suppose you have following method with two args
public void doSomething(arg1,arg2);
in case you want to add additional optional parameter then overload the method
public void doSomething(arg1,arg2,arg3) {
Result result = doSomething(arg1,arg2);
// do additional working
}
A good example were Optional as arguments would be nice is JPA Repositories. Id love to do something like findByNameAndSurname(Optional,Optional). That way, if the Optional is empty, no WHERE param=y is performed

Why should Java 8's Optional not be used in arguments

I've read on many Web sites Optional should be used as a return type only, and not used in method arguments. I'm struggling to find a logical reason why. For example I have a piece of logic which has 2 optional parameters. Therefore I think it would make sense to write my method signature like this (solution 1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2) {
// my logic
}
Many web pages specify Optional should not be used as method arguments. With this in mind, I could use the following method signature and add a clear Javadoc comment to specify that the arguments may be null, hoping future maintainers will read the Javadoc and therefore always carry out null checks prior to using the arguments (solution 2):
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Alternatively I could replace my method with four public methods to provide a nicer interface and make it more obvious p1 and p2 are optional (solution 3):
public int calculateSomething() {
calculateSomething(null, null);
}
public int calculateSomething(String p1) {
calculateSomething(p1, null);
}
public int calculateSomething(BigDecimal p2) {
calculateSomething(null, p2);
}
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Now I try writing the code of the class which invokes this piece of logic for each approach. I first retrieve the two input parameters from another object which returns Optionals and then, I invoke calculateSomething. Therefore, if solution 1 is used the calling code would look like this:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
if solution 2 is used, the calling code would look like this:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
if solution 3 is applied, I could use the code above or I could use the following (but it's significantly more code):
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
if (p2.isPresent()) {
result = myObject.calculateSomething(p1, p2);
} else {
result = myObject.calculateSomething(p1);
}
} else {
if (p2.isPresent()) {
result = myObject.calculateSomething(p2);
} else {
result = myObject.calculateSomething();
}
}
So my question is: Why is it considered bad practice to use Optionals as method arguments (see solution 1)? It looks like the most readable solution to me and makes it most obvious that the parameters could be empty/null to future maintainers. (I'm aware the designers of Optional intended it to only be used as a return type, but I can't find any logical reasons not to use it in this scenario).
Oh, those coding styles are to be taken with a bit of salt.
(+) Passing an Optional result to another method, without any semantic analysis; leaving that to the method, is quite alright.
(-) Using Optional parameters causing conditional logic inside the methods is literally contra-productive.
(-) Needing to pack an argument in an Optional, is suboptimal for the compiler, and does an unnecessary wrapping.
(-) In comparison to nullable parameters Optional is more costly.
(-) The risk of someone passing the Optional as null in actual parameters.
In general: Optional unifies two states, which have to be unraveled. Hence better suited for result than input, for the complexity of the data flow.
The best post I've seen on the topic was written by Daniel Olszewski:
Although it might be tempting to consider Optional for not mandatory method parameters, such a solution pale in comparison with other possible alternatives. To illustrate the problem, examine the following constructor declaration:
public SystemMessage(String title, String content, Optional<Attachment> attachment) {
// assigning field values
}
At first glance it may look as a right design decision. After all, we
explicitly marked the attachment parameter as optional. However, as
for calling the constructor, client code can become a little bit
clumsy.
SystemMessage withoutAttachment = new SystemMessage("title", "content", Optional.empty());
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", Optional.ofNullable(attachment));
Instead of providing clarity, the factory methods of the Optional
class only distract the reader. Note there’s only one optional
parameter, but imagine having two or three. Uncle Bob definitely
wouldn’t be proud of such code 😉
When a method can accept optional parameters, it’s preferable to adopt the well-proven approach and design such case using method
overloading. In the example of the SystemMessage class, declaring
two separate constructors are superior to using Optional.
public SystemMessage(String title, String content) {
this(title, content, null);
}
public SystemMessage(String title, String content, Attachment attachment) {
// assigning field values
}
That change makes client code much simpler and easier to read.
SystemMessage withoutAttachment = new SystemMessage("title", "content");
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", attachment);
There are almost no good reasons for not using Optional as parameters. The arguments against this rely on arguments from authority (see Brian Goetz - his argument is we can't enforce non null optionals) or that the Optional arguments may be null (essentially the same argument). Of course, any reference in Java can be null, we need to encourage rules being enforced by the compiler, not programmers memory (which is problematic and does not scale).
Functional programming languages encourage Optional parameters. One of the best ways of using this is to have multiple optional parameters and using liftM2 to use a function assuming the parameters are not empty and returning an optional (see http://www.functionaljava.org/javadoc/4.4/functionaljava/fj/data/Option.html#liftM2-fj.F-). Java 8 has unfortunately implemented a very limited library supporting optional.
As Java programmers we should only be using null to interact with legacy libraries.
Let's make something perfectly clear: in other languages, there is no general recommendation against the use of a Maybe type as a field type, a constructor parameter type, a method parameter type, or a function parameter type.
So if you "shouldn't" use Optional as a parameter type in Java, the reason is specific to Optional, to Java, or to both.
Reasoning that might apply to other Maybe types, or other languages, is probably not valid here.
Per Brian Goetz,
[W]e did have a clear
intention when adding [Optional], and it was not to be a general
purpose Maybe type, as much as many people would have liked us to do
so. Our intention was to provide a limited mechanism for library
method return types where there needed to be a clear way to represent
"no result", and using null for such was overwhelmingly likely to
cause errors.
For example, you probably should never use it for something that
returns an array of results, or a list of results; instead return an
empty array or list. You should almost never use it as a field of
something or a method parameter.
So the answer is specific to Optional: it isn't "a general purpose Maybe type"; as such, it is limited, and it may be limited in ways that limit its usefulness as a field type or a parameter type.
That said, in practice, I've rarely found using Optional as a field type or a parameter type to be an issue. If Optional, despite its limitations, works as a parameter type or a field type for your use case, use it.
The pattern with Optional is for one to avoid returning null. It's still perfectly possible to pass in null to a method.
While these aren't really official yet, you can use JSR-308 style annotations to indicate whether or not you accept null values into the function. Note that you'd have to have the right tooling to actually identify it, and it'd provide more of a static check than an enforceable runtime policy, but it would help.
public int calculateSomething(#NotNull final String p1, #NotNull final String p2) {}
This advice is a variant of the "be as unspecific as possible regarding inputs and as specific as possible regarding outputs" rule of thumb.
Usually if you have a method that takes a plain non-null value, you can map it over the Optional, so the plain version is strictly more unspecific regarding inputs. However there are a bunch of possible reasons why you would want to require an Optional argument nonetheless:
you want your function to be used in conjunction with another API that returns an Optional
Your function should return something other than an empty Optional if the given value is empty
You think Optional is so awesome that whoever uses your API should be required to learn about it ;-)
Check out the JavaDoc in JDK10, https://docs.oracle.com/javase/10/docs/api/java/util/Optional.html, an API note is added:
API Note:
Optional is primarily intended for use as a method return type where there is a clear need to represent "no result," and where using null is likely to cause errors.
Maybe I will provoke a bunch of down-votes and negative comments, but... I cannot stand.
Disclaimer: what I write below is not really an answer to the original question, but rather my thoughts on the topic. And the only source for it is my thoughts and my experience (with Java and other languages).
First let's check, why would anyone like to use Optional at all?
For me the reason is simple: unlike other languages java does not have built-in capability to define variable (or type) as nullable or not. All "object"-variables are nullable and all primitive-types are not. For the sake of simplicity let't not consider primitive types in further discussion, so I will claim simply that all variables are nullable.
Why would one need to declare variables as nullable/non-nullable? Well, the reason for me is: explicit is always better, than implicit. Besides having explicit decoration (e.g. annotation or type) could help static analyzer (or compiler) to catch some null-pointer related issues.
Many people argue in the comments above, that functions do not need to have nullable arguments. Instead overloads should be used. But such statement is only good in a school-book. In real life there are different situations. Consider class, which represents settings of some system, or personal data of some user, or in fact any composite data-structure, which contains lots of fields - many of those with repeated types, and some of the fields are mandatory while others are optional. In such cases inheritance/constructor overloads do not really help.
Random example: Let's say, we need to collect data about people. But some people don't want to provide all the data. And of course this is POD, so basically type with value-semantics, so I want it to be more or less immutable (no setters).
class PersonalData {
private final String name; // mandatory
private final int age; // mandatory
private final Address homeAddress; // optional
private final PhoneNumber phoneNumber; // optional. Dedicated class to handle constraints
private final BigDecimal income; // optional.
// ... further fields
// How many constructor- (or factory-) overloads do we need to handle all cases
// without nullable arguments? If I am not mistaken, 8. And what if we have more optional
// fields?
// ...
}
So, IMO discussion above shows, that even though mostly we can survive without nullable arguments, but sometimes it is not really feasible.
Now we come to the problem: if some of the arguments are nullable and others are not, how do we know, which one?
Approach 1: All arguments are nullable (according to java standrd, except primitive types). So we check all of them.
Result: code explodes with checks, which are mostly unneeded, because as we discussed above almost all of the time we can go ahead with nullable variables, and only in some rare cases "nullables" are needed.
Approach 2: Use documentation and/or comments to describe, which arguments/fields are nullable and which not.
Result: It does not really work. People are lazy to write and read the docs. Besides lately the trend is, that we should avoid writing documentation in favor of making the code itself self-describing. Besides all the reasoning about modifying the code and forgeting to modify the documentation is still valid.
Approach 3: #Nullable #NonNull etc... I personally find them to be nice. But there are certain disadvantages : (e.g. they are only respected by external tools, not the compiler), the worst of which is that they are not standard, which means, that 1. I would need to add external dependency to my project to benefit from them, and 2. The way they are treated by different systems are not uniform. As far as I know, they were voted out of official Java standard (and I don't know if there are any plans to try again).
Approach 4: Optional<>. The disadvantages are already mentioned in other comments, the worst of which is (IMO) performance penalty. Also it adds a bit of boilerplate, even thoough I personally find, use of Optional.empty() and Optional.of() to be not so bad. The advantages are obvious:
It is part of the Java standard.
It makes obvious to the reader of the code (or to the user of API), that these arguments may be null. Moreover, it forces both: user of the API and developer of the method to aknolage this fact by explicitly wrapping/unwrapping the values (which is not the case, when annotations like #Nullable etc. are used).
So in my point, there is no black-and-white in regard of any methodology including this one. I personally ended up with the following guidelines and conventions (which are still not strict rules):
Inside my own code all the variables must be not-null (but probably Optional<>).
If I have a method with one or two optional arguments I try to redesign it using overloads, inheritance etc.
If I cannot find the solution in reasonable time, I start thinking, if the performance is critical (i.e. if there are millions of the objects to be processed). Usually it is not the case.
If not, I use Optional as argument types and/or field types.
There are still grey areas, where these conventions do not work:
We need high performance (e.g. processing of huge amounts of data, so that total execution time is very large, or situations when throughput is critical). In this cases performance penalty introduced by Optional may be really unwanted.
We are on the boundary of the code, which we write ourselves, e.g.: we read from the DB, Rest Endpoint, parse file etc.
Or we just use some external libraries, which do not follow our conventions, so again, we should be careful...
By the way, the last two cases can also be the source of need in the optional fields/arguments. I.e. when the structure of the data is not developed by ourselves, but is imposed by some external interfaces, db-schemas etc...
At the end, I think, that one should think about the problem, which is being solved, and try to find the appropriate tools. If Optional<> is appropriate, then I see no reason not to use it.
Edit: Approach 5: I used this one recently, when I could not use Optional. The idea is simply to use naming convention for method arguments and class variables. I used "maybe"-prefix, so that if e.g. "url" argument is nullable, then it becomes maybeUrl. The advantage is that it slightly improves understandability of the intent (and does not have disadvantages of other approaches, like external dependencies or performance penalty). But there are also drawbacks, like: there is no tooling to support this convention (your IDE will not show you any warning, if you access "maybe"-variable without first checking it). Another problem is that it only helps, when applied consistently by all people working on the project.
This seems a bit silly to me, but the only reason I can think of is that object arguments in method parameters already are optional in a way - they can be null. Therefore forcing someone to take an existing object and wrap it in an optional is sort of pointless.
That being said, chaining methods together that take/return optionals is a reasonable thing to do, e.g. Maybe monad.
Accepting Optional as parameters causes unnecessary wrapping at caller level.
For example in the case of:
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {}
Suppose you have two not-null strings (ie. returned from some other method):
String p1 = "p1";
String p2 = "p2";
You're forced to wrap them in Optional even if you know they are not Empty.
This get even worse when you have to compose with other "mappable" structures, ie. Eithers:
Either<Error, String> value = compute().right().map((s) -> calculateSomething(
< here you have to wrap the parameter in a Optional even if you know it's a
string >));
ref:
methods shouldn't expect Option as parameters, this is almost always a
code smell that indicated a leakage of control flow from the caller to
the callee, it should be responsibility of the caller to check the
content of an Option
ref. https://github.com/teamdigitale/digital-citizenship-functions/pull/148#discussion_r170862749
My take is that Optional should be a Monad and these are not conceivable in Java.
In functional programming you deal with pure and higher order functions that take and compose their arguments only based on their "business domain type". Composing functions that feed on, or whose computation should be reported to, the real-world (so called side effects) requires the application of functions that take care of automatically unpacking the values out of the monads representing the outside world (State, Configuration, Futures, Maybe, Either, Writer, etc...); this is called lifting. You can think of it as a kind of separation of concerns.
Mixing these two levels of abstraction doesn't facilitate legibility so you're better off just avoiding it.
Another reason to be carefully when pass an Optional as parameter is that a method should do one thing... If you pass an Optional param you could favor do more than one thing, it could be similar to pass a boolean param.
public void method(Optional<MyClass> param) {
if(param.isPresent()) {
//do something
} else {
//do some other
}
}
So, if you would permit the pun, Oracle issued an oracle:
Thou shalt not use Optional but for function return values.
I love it how most of the answers so far are going along with the narrative of Oracle's oracle, which is re-iterated unquestioned all over the interwebz, in the "many Web sites" mentioned in the question. This is very typical of stack overflow: if something is allegedly supposed to be a certain way, and you ask why it is supposed to be that way, almost everyone will offer reasons why; almost nobody will question whether it should in fact be that way.
So, here is a dissenting opinion:
You can use Optional to completely eliminate null from your code base.
I have done it in a 100k-lines-of-code project. It worked.
If you decide to go along this path, then you will need to be thorough, so you will have a lot of work to do. The example mentioned in the accepted answer with Optional.ofNulable() should never occur, because if you are thorough, then you should never have anything returning null, and therefore no need for Optional.ofNullable(). In that 100k-lines-of-code project that I mentioned above, I have only used Optional.ofNullable() a couple of times when receiving results from external methods that I have no control over.
Also, if you decide to go along this path, your solution will not be the most performant solution possible, because you will be allocating lots of optionals. However:
That's nothing but a runtime performance overhead disadvantage.
That's not a severe disadvantage.
That's Java's problem, not your problem.
Let me explain that last part.
Java does not offer explicit nullability of reference types as C# does (since version 8.0) so it is inferior in this regard. (I said "in this regard"; in other regards, Java is better; but that's off-topic right now.)
The only proper alternative to explicit nullability of reference types is the Optional type.
(And it is arguably even slightly better, because with Optional you can indicate optional-of-optional, if you must, whereas with explicit nullability you cannot have ReferenceType??, or at least you cannot in C# as it is currently implemented.)
Optional does not have to add overhead, it only does so in Java. That's because Java also does not support true value types, as C# and Scala do. In this regard, Java is severely inferior to those languages. (Again, I said "in this regard"; in other regards, Java is better; but that's off-topic right now.) If Java did support true value types, then Optional would have been implemented as a single machine word, which would mean that the runtime overhead of using it would be zero.
So, the question that it boils down to is: do you want perfect clarity and type safety in your code, or do you prefer maximum performance? I believe that for high-level languages, (of which Java certainly aims to be one,) this question was settled a long time ago.
I think that is because you usually write your functions to manipulate data, and then lift it to Optional using map and similar functions. This adds the default Optional behavior to it.
Of course, there might be cases, when it is necessary to write your own auxilary function that works on Optional.
I believe the reson of being is you have to first check whether or not Optional is null itself and then try to evaluate value it wraps. Too many unnecessary validations.
I know that this question is more about opinion rather than hard facts. But I recently moved from being a .net developer to a java one, so I have only recently joined the Optional party. Also, I'd prefer to state this as a comment, but since my point level does not allow me to comment, I am forced to put this as an answer instead.
What I have been doing, which has served me well as a rule of thumb. Is to use Optionals for return types, and only use Optionals as parameters, if I require both the value of the Optional, and weather or not the Optional had a value within the method.
If I only care about the value, I check isPresent before calling the method, if I have some kind of logging or different logic within the method that depends on if the value exists, then I will happily pass in the Optional.
Using Optional as parameters might be useful in some use cases which involves protobufs or setting fields in a configuration object.
public void setParameters(Optional<A> op1, Optional<B> op2) {
ProtoRequest.Builder builder = ProtoRequest.newBuilder();
op1.ifPresent(builder::setOp1);
op2.ifPresent(builder::setOp2);
...
}
I think in such cases it might be useful to have optional as parameters. API receiving the proto request would handle the different fields.
If a function is not doing additional computations on these parameters then using Optional might be simpler.
public void setParameters(A op1, B op2) {
ProtoRequest.Builder builder = ProtoRequest.newBuilder();
if (op1 != null) {
builder.setOp1(op1);
}
if (op2 != null) {
builder.setOp2(op2);
}
...
}
Optionals aren't designed for this purpose, as explained nicely by Brian Goetz.
You can always use #Nullable to denote that a method argument can be null. Using an optional does not really enable you to write your method logic more neatly.
One more approach, what you can do is
// get your optionals first
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
// bind values to a function
Supplier<Integer> calculatedValueSupplier = () -> { // your logic here using both optional as state}
Once you have built a function(supplier in this case) you will be able to pass this around as any other variable and would be able to call it using
calculatedValueSupplier.apply();
The idea here being whether you have got optional value or not will be internal detail of your function and will not be in parameter. Thinking functions when thinking about optional as parameter is actually very useful technique that I have found.
As to your question whether you should actually do it or not is based on your preference, but as others said it makes your API ugly to say the least.
At first, I also preferred to pass Optionals as parameter, but if you switch from an API-Designer perspective to a API-User perspective, you see the disadvantages.
For your example, where each parameter is optional, I would suggest to change the calculation method into an own class like follows:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
MyCalculator mc = new MyCalculator();
p1.map(mc::setP1);
p2.map(mc::setP2);
int result = mc.calculate();
This is because we have different requirements to an API user and an API developer.
A developer is responsible for providing a precise specification and a correct implementation. Therefore if the developer is already aware that an argument is optional the implementation must deal with it correctly, whether it being a null or an Optional. The API should be as simple as possible to the user, and null is the simplest.
On the other hand, the result is passed from the API developer to the user. However the specification is complete and verbose, there is still a chance that the user is either unaware of it or just lazy to deal with it. In this case, the Optional result forces the user to write some extra code to deal with a possible empty result.
First of all, if you're using method 3, you can replace those last 14 lines of code with this:
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
The four variations you wrote are convenience methods. You should only use them when they're more convenient. That's also the best approach. That way, the API is very clear which members are necessary and which aren't. If you don't want to write four methods, you can clarify things by how you name your parameters:
public int calculateSomething(String p1OrNull, BigDecimal p2OrNull)
This way, it's clear that null values are allowed.
Your use of p1.orElse(null) illustrates how verbose our code gets when using Optional, which is part of why I avoid it. Optional was written for functional programming. Streams need it. Your methods should probably never return Optional unless it's necessary to use them in functional programming. There are methods, like Optional.flatMap() method, that requires a reference to a function that returns Optional. Here's its signature:
public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)
So that's usually the only good reason for writing a method that returns Optional. But even there, it can be avoided. You can pass a getter that doesn't return Optional to a method like flatMap(), by wrapping it in a another method that converts the function to the right type. The wrapper method looks like this:
public static <T, U> Function<? super T, Optional<U>> optFun(Function<T, U> function) {
return t -> Optional.ofNullable(function.apply(t));
}
So suppose you have a getter like this: String getName()
You can't pass it to flatMap like this:
opt.flatMap(Widget::getName) // Won't work!
But you can pass it like this:
opt.flatMap(optFun(Widget::getName)) // Works great!
Outside of functional programming, Optionals should be avoided.
Brian Goetz said it best when he said this:
The reason Optional was added to Java is because this:
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
is cleaner than this:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
Irrespective of Java 8, Use old school method overloading technique to bring clarity and flexibility, suppose you have following method with two args
public void doSomething(arg1,arg2);
in case you want to add additional optional parameter then overload the method
public void doSomething(arg1,arg2,arg3) {
Result result = doSomething(arg1,arg2);
// do additional working
}
A good example were Optional as arguments would be nice is JPA Repositories. Id love to do something like findByNameAndSurname(Optional,Optional). That way, if the Optional is empty, no WHERE param=y is performed

java shortcuts to Pojos?

I am wondering a stupid question but well, I love to learn :)
Say I got the following code :
public String method(<T> a)
{
String dataA = a.getB().getC().getD();
}
At what point it becomes interesting to define a map which cache our requests and holds this :
Map<<T>, String> m;
m.put(a, dataA);
and then of course,
[SNIP the usual tests of nullity and adding the object if it is missing and so forth plus the refreshing issues]
return m.get(a);
Let me stress that the successive gets are NOT costy (no things such as DB calls, or JNDI lookups).
It's just that it's clearer if we define a dictionnary rather than read the whole string of "gets".
I consider that making a get call is NEARLY "free" in CPU time. Again, I suppose that retrieving the data from an hashmap is NOT exactly free but nearly (at least, in my case, it is :) ).
My question is really in terms of readibility, not performance.
Thanks !
To increase readability (and decrease dependencies), you should define an accessor in A, such as
public String getDataA() {
return getB().getC().getD();
}
Then your calling code becomes
String dataA = a.getDataA();
You may say that you would need too many such shortcut methods in A, cluttering its interface. That is actually a sign of a class design issue. Either A has grown too big and complex (in which case it may be better to partition it into more than one class), or the code needing all these far away pieces of data actually belongs to somewhere else - say into B or C - rather than to A's client.
A couple of things to consider:
Apache Beanutils has a lot of utilities for this sort of thing: http://commons.apache.org/beanutils/
java.util.properties, if the values are all strings
If you really want to access things like this you can also look at using groovy instead. All lookups on maps in groovy can be done with '.' notation and it also supports a "safe" accessor which will check for nulls.
MVEL is another option:
String d = (String) MVEL.eval("b.?c.?d", a);
I will say that data dictionaries lead to typesafety issues. There's no guarantee that everyone puts the right types in the right data elements, or even defines all the required elements.
Also, when using an expression language as above, there's also typesafety issues, as there's no compile time check on the actual expression to make sure that a) it makes sense, and b) it returns the right type.

Design to emulate Visitor without its drawbacks

I'm looking for a clean design to emulate Visitor functionality without the many drawbacks it has.
In Java, the traditional implementations (as the described in GoF) resort to double dispatch to get rid of if-elses. To solve this, I've seen some implementations that use reflection to avoid modifications on the "Visitable" classes, but these rely on hardcoded strings when looking for method names. Although quite useful, I still think that they are not clean design.
Is it possible to emulate the same idea using data structures and/or good OO-design? It doesn't have to be a pattern, just I'm looking for examples where a similar problem is solved (e.g.: using a Map<Class<T>,SomeFunctionObject>).
UPDATE Something like this:
public abstract class BaseVisitor<T> {
private final TypesafeHeterogeneusMap map;
protected BaseVisitor(){
map = inflateFunctions();
}
public <E extends T> void process(E element){
if(element == null){
throw new NullPointerException();
}
boolean processed = false;
#SuppressWarnings("unchecked")
Class<? super T> sc = (Class<? super T>) element.getClass();
while(true){
if(sc != null){
FunctionObject<? super T> fo2 = map.get(sc);
if(fo2 != null){
fo2.process(element);
processed = true;
break;
}
sc = sc.getSuperclass();
} else {
break;
}
}
if(!processed) System.out.println("Unknown type: " + element.getClass().getName());
}
abstract TypesafeHeterogeneusMap inflateFunctions();
}
Actually is a mix of Template pattern and Command pattern, I think. Feel free to post your suggestions on how to enhance it.
You could just make all your Visitor implementations extend a base class, which provides a default implementation for every type of Visitable:
public interface AnimalVisitor {
void visitHorse(Horse horse);
void visitDog(Dog dog);
}
public class BaseAnimalVisitor implements AnimalVisitor {
public void visitHorse(Horse horse) {
// do nothing by default
}
public void visitDog(Dog dog) {
// do nothing by default
}
}
Then, when a new class Cat is introduced, you add the visitCat(Cat cat) method to the interface and the base class, and all the visitors are left unchanged and still compile. If they don't want to ignore cats, then you override the visitCat method.
Although it's not the answer you're looking for: Consider using a higher-level, less verbose language than Java. You will find that things like the Visitor pattern start to seem irrelevant. Of course, if you want to define logic for traversing a data structure in one place, and define what to do with the elements of the data structure (based on their types) somewhere else, and make it possible to mix-and-match traversal/processing strategies, you can do that. But you can do it using just a small amount of straightforward code, nothing that you would think of calling a "pattern".
I came from a C/Java programming background and started learning various dynamic languages a few years ago. It was mind-blowing to realize how much you can do in a few lines of code.
For example, if I was to emulate the Visitor pattern in Ruby:
module Enumerable
def accept_visitor(visitor)
each do |elem|
method = "visit#{elem.class}".to_sym
elem.send(method,elem) if elem.respond_to? method
end
end
end
To explain: in Ruby, an Enumerable represents anything which can be iterated over. In those 8 lines of code, I have made every kind of object which can be iterated over accept Visitors. Whether I plan to have 5, 10, or 100 different classes accept Visitors, those 8 lines are all that are needed.
Here's a sample Visitor:
class CatCounter
attr_reader :count
def initialize; #count = 0; end
def visitCat; #count += 1; end
end
Note that the Visitor doesn't have to define methods for all the different types of Visitables. Each Visitor just has to define methods for the types of Visitables it is interested in; it can ignore the rest. (Which means you don't have to modify a bunch of existing code if you add a new type of Visitable.) And any Visitor can interoperate with any object which accepts Visitors.
Just in those few lines of code, all the problems you mentioned with the Visitor pattern have been overcome.
Don't get me wrong; Java is a great language for some things. But you need to choose the right tool for the job. The fact that you are fighting so much to overcome the limitations of your tool might indicate that in this case, a different tool is called for.
#MisterSmith, since you have to use Java, and presumably you do have good reasons for using Visitor, I am going to propose another possible solution.
Let's separate our minds from the way Visitor is usually implemented and go back to the reason why people use Visitors in the first place. Although I mentioned it already in my other answer, the point of Visitor is to make it possible to mix-and-match traversal and processing logic.
"Traversal logic" could mean logic for traversing different types of data structures, or traversing the same data structure in a different order. Or it could even include traversal strategies which apply certain filters to the elements returned, etc.
Implicit in Visitor is the idea that the processing we apply to each element is going to depend on its class. If what we do to each element doesn't depend on its class, there is no reason to use Visitor. Unless we want to do a "switch" on element class, we need to use virtual method calls to do this (which is why the usual Java implementation uses double dispatch).
I propose that we can split the Visitor pattern into 3 rather than 2 parts:
An Iterator object which implements a certain traversal
An object which implements the strategy of "deciding what to do with an element based on its class" (the part which normally requires double dispatch). Using reflection, we can make a general-purpose class which does this. A simple implementation would use a Map, or you could make something which generates bytecode dynamically (I forget the platform method in Java which lets you load raw bytecodes as a new Class, but there is one). OR! OR, you could use a dynamic, JVM-hosted language like JRuby or Clojure to write #2, compile to bytecode, and use the resulting .class file. (This file would probably use the invokedynamic bytecode, which as far as I know, is not accessible from Java -- the Java compiler never emits it. If this has changed, please edit this post.)
The Visitors themselves. In this implementation, Visitors won't have to subclass from a common superclass, nor will they have to implement methods for elements they're not interested in.
Keeping the traversal in a general-purpose Iterator allows you to do other things with it (not just accepting Visitors).
There are a couple ways the 3 pieces could be tied together; I'm thinking #2 will wrap #3 (taking it as a constructor argument). #2 will provide a public method which takes an Iterator as an argument, and applies the Visitor to it.
The interesting part is #2. I may edit this post later to add a sample implementation; right now I have some other things to do. If someone else comes up with an implementation, please add it here.

Categories