Related
In Kotlin, I wanted to write a function, but I see the new way of writing it with "val" property using get(). What's the difference between the below two.
1) fun sample(): String {
return "text"
}
2) val sample: String
get() = "text"
As noted in the comments, there are is no major difference between the two snippets. I can only point you at some minor differences:
Snippet #1 will be recognised as a declared function whereas Snippet #2 will be a declared property. This might make a difference should reflection-based logic be applied.
Snippet #2 could never accept an argument and could never return a response of type different than the declared val. This is due to the nature of the get() abstraction. Snippet #1 could easily be extended to accept an input argument.
Snippet #2 might have IDE complaining about a backing field being generated for the property that has no impact on the property's get().
Generally speaking, Snippet #2 could and probably should be reduced to val sample: String = "text". get() declaration is redundant.
I am trying to learn a java-based program, but I am pretty new to java. I am quite confusing on the following two lines of java code. I think my confusion comes from the concepts including “class” and “cast”, but just do not know how to analyze.
For this one
XValidatingObjectCorpus<Classified<CharSequence>> corpus
= new XValidatingObjectCorpus<Classified<CharSequence>>(numFolds);
What is <Classified<CharSequence>> used for in terms of Java programming? How to understand its relationships with XValidatingObjectCorpusand corpus
For the second one
LogisticRegressionClassifier<CharSequence> classifier
= LogisticRegressionClassifier.<CharSequence>train(para1, para2, para3)
How to understand the right side of LogisticRegressionClassifier.<CharSequence>train? What is the difference between LogisticRegressionClassifier.<CharSequence>train and LogisticRegressionClassifier<CharSequence> classifier
?
These are called generics. They tell Java to make an instance of the outer class - either XValidatingObjectCorpus or LogisticRegressionClassifier - using the type of the inner object.
Normally, these are used for lists and arrays, such as ArrayList or HashMap.
What is the relationship between XValidatingObjectCorpus and corpus?
corpus is just a name given to the new XValidatingObjectCorpus object that you make with that statement (hence the = new... part).
What does LogisticRegressionClassifier.<CharSequence>train mean?
I have no idea, really. I suggest looking at the API for that (I think this is the right class).
What is the difference between LogisticRegressionClassifier.<CharSequence>train and LogisticRegressionClassifier<CharSequence> classifier?
You can't really compare these two. The one on the left of the = is the object identifier, and the one on the right is the allocator (probably the wrong word, but it is what it does, kind of).
Together, the two define an instance of LogisticRegressionClassifier, saying to create that type of object, call it classifier, and then give it the value returned by the train() method. Again, look at the API to understand it more.
By the way, these look like wretched examples to be learning Java with. Start with something simple, or at least an easier part of the code. It looks like someone had way too much fun with long names (the API has even longer names). Seriously though, I only just got to fully understanding this, and Java was my main language for quite a while (It gets really confusing when you try and do simple things). Anyways, good luck!
public class Sample<T> { // T implies Generic implementation, T can be substituted with any object.
static <T> Sample<T> train(int par1, int par2, int par3){
return new Sample<T>(); // you are calling the Generic method to return Sample object which works with a particular type of generic object, may it be an Integer or a CharSequence. --> see the main method.
}
public static void main(String ... a)
{
int par1 = 0, par2 = 0, par3 = 1;
// Here you are returning Sample object which works with a sequence of characters.
Sample<CharSequence> sample = Sample.<CharSequence>train(par1, par2, par3);
// Here you are returning Sample object which works with Integer values.
Sample<CharSequence> sample1 = Sample.<Integer>train(par1, par2, par3);
}
}
<Classified<CharSequence>> is a generic parameter.
LogisticRegressionClassifier<CharSequence> is a generic type.
LogisticRegresstionClassifier.<CharSequence>train is a generic method.
Java Generics Tutorial
I'm doing a bit of playing about to learn a framework I'm contributing to, and an interesting question came up. EDIT: I'm doing some basic filters in the Okapi Framework, as described in this guide, note that the filter must return different event types to be useful, and that resources must be used by reference (as the same resource may be used in other filters later). Here's the code I'm working with:
while (filter.hasNext()) {
Event event = filter.next();
if (event.isTextUnit()) {
TextUnit tu = (TextUnit)event.getResource();
if (tu.isTranslatable()) {
//do something with it
}
}
}
Note the cast of the resource to a TextUnit object on line 4. This works, I know it's a TextUnit because events that are isTextUnit() will always have a TextUnit resource. However, an alternative would be to add an asTextUnit() method to the IResource interface that returns the event as a TextUnit (as well as equivalent methods for each common resource type), so that the line would become:
TextUnit tu = event.getResource().asTextUnit;
Another approach might be providing a static casting method in TextUnit itself, along the lines of:
TextUnit tu = TextUnit.fromResource(event.getResource());
My question is: what are some arguments for doing it one way or the other? Are there performance differences?
The main advantage I can think of with asTextUnit() (or .fromResource) is that more appropriate exceptions could be thrown if someone tries to get a resource as the wrong type (i.e. with a message like "Cannot get this RawDocument type resource as a TextUnit - use asRawDocument()" or "The resource is not a TextUnit").
The main disadvantages I can think of with .asTextUnit() is that each resource type would then have to implement all the methods (most of which will just throw an exception), and if another major resource type is added there would be some refactoring to add the new method to every resource type (although there's no reason the .asSomething() methods would have to be defined for every possible type, the less common resources could just be cast, although this would lead to inconsistency of approach). This wouldn't be a problem with .fromResource() since it's just one method per type, and could be added or not per type depending on preference.
If the aim is to test an object's type and cast it, then I don't see any value in creating / using custom isXyz and asXyz methods. You just end up with a bunch of extra methods that make little difference to code readability.
Re: your point about appropriate exception messages, I would say that it is most likely not worth it. It is reasonable to assume that not having a TextUnit when a TextUnit is expected is symptom of a bug somewhere. IMO, it is not worthwhile trying to provide "user friendly" diagnostics for bugs. The person that the information is aimed at is a Java programmer, and for that person the default message and stacktrace for a regular ClassCastException (and the source code) provides all of the information required. (Translating it into pretty language adds no real value.)
On the flip-side, the performance differences between the two forms are not likely to be significant. But consider this:
if (x instanceof Y) {
((Y) x).someYMethod();
}
versus
if (x.isY()) {
x.asY().someYMethod();
}
boolean isY(X x) { return x instanceof Y; }
Y asY(X x) { return (Y) x; }
The optimizer might be able to do a better job of the first compared with the second.
It might not inline the method calls in the second case, especially if it is changed to use instanceof and throw a custom exception.
It is less likely to figure out that only one type test is really required in the second case. (It might not in the first case either ... but it is more likely to.)
But either way, the performance difference is going to be small.
Summary, the fancy methods are not really worth the effort, though they don't do any real harm.
Now if the isXyz or asXyz methods were testing the state of the object (not just the object's Java type), or if the asXyz was returning a wrapper, then the answers would be different ...
You could also just go
if (event instanceof TextUnit) {
// ...
}
and save yourself the trouble.
To answer your question regarding whether to go asTextUnit() vs. TextUnit.fromResource, the performance difference would depend upon how you actually implement these methods.
In the case of the static converter you would have a to create and return a new object of type TextUnit. However, in the case of the member function you could simply return this casted or you could create an return a new object - depends upon your use case.
Either ways, seems like instanceof is probably the cleanest way here.
What if your filter were extended - or wrapped - to return only text unit events? In fact, what if it returned only the resources of text unit events? Then your loop would be much simpler. I would think the clean way to do this would be a second filter, which simply returned just the text unit events, followed by, let's say, an Extractor, which returned the properly cast resource.
If you have a common base class, you can have a single asXMethod there for every derived class, and needn't refactor all derived classes:
abstract class Base {
A asA () { throw new InstantiationException ("not an A"); }
B asB () { throw new InstantiationException ("not an B"); }
C asC () { throw new InstantiationException ("not an C"); }
// much more ...
}
class A extends Base {
A asA () { /* hard work */ return new A (); }
// no asB, asC requiered
}
class B extends Base {
B asB () { /* hard work */ return new B (); }
// no asA, asC required
}
// and so on.
looks pretty clever. For a new Class N, just add a new Method to Base, and all derived classes get it. Just N needs to implement asN.
But it smells.
Why should a B have a method asA if it will always fail? That's not a good design. Exceptions in the generator are cheap, if they aren't triggered. Only thrown exceptions might be costly.
Yes, there are differences. Creating new immutable elements is better then casting. Pass all serializable data (non transient or computable data) to a Builder and build appropriate class.
I am not able to understand the point of Option[T] class in Scala. I mean, I am not able to see any advanages of None over null.
For example, consider the code:
object Main{
class Person(name: String, var age: int){
def display = println(name+" "+age)
}
def getPerson1: Person = {
// returns a Person instance or null
}
def getPerson2: Option[Person] = {
// returns either Some[Person] or None
}
def main(argv: Array[String]): Unit = {
val p = getPerson1
if (p!=null) p.display
getPerson2 match{
case Some(person) => person.display
case None => /* Do nothing */
}
}
}
Now suppose, the method getPerson1 returns null, then the call made to display on first line of main is bound to fail with NPE. Similarly if getPerson2 returns None, the display call will again fail with some similar error.
If so, then why does Scala complicate things by introducing a new value wrapper (Option[T]) instead of following a simple approach used in Java?
UPDATE:
I have edited my code as per #Mitch's suggestion. I am still not able to see any particular advantage of Option[T]. I have to test for the exceptional null or None in both cases. :(
If I have understood correctly from #Michael's reply, is the only advantage of Option[T] is that it explicitly tells the programmer that this method could return None? Is this the only reason behind this design choice?
You'll get the point of Option better if you force yourself to never, ever, use get. That's because get is the equivalent of "ok, send me back to null-land".
So, take that example of yours. How would you call display without using get? Here are some alternatives:
getPerson2 foreach (_.display)
for (person <- getPerson2) person.display
getPerson2 match {
case Some(person) => person.display
case _ =>
}
getPerson2.getOrElse(Person("Unknown", 0)).display
None of this alternatives will let you call display on something that does not exist.
As for why get exists, Scala doesn't tell you how your code should be written. It may gently prod you, but if you want to fall back to no safety net, it's your choice.
You nailed it here:
is the only advantage of Option[T] is
that it explicitly tells the
programmer that this method could
return None?
Except for the "only". But let me restate that in another way: the main advantage of Option[T] over T is type safety. It ensures you won't be sending a T method to an object that may not exist, as the compiler won't let you.
You said you have to test for nullability in both cases, but if you forget -- or don't know -- you have to check for null, will the compiler tell you? Or will your users?
Of course, because of its interoperability with Java, Scala allows nulls just as Java does. So if you use Java libraries, if you use badly written Scala libraries, or if you use badly written personal Scala libraries, you'll still have to deal with null pointers.
Other two important advantages of Option I can think of are:
Documentation: a method type signature will tell you whether an object is always returned or not.
Monadic composability.
The latter one takes much longer to fully appreciate, and it's not well suited to simple examples, as it only shows its strength on complex code. So, I'll give an example below, but I'm well aware it will hardly mean anything except for the people who get it already.
for {
person <- getUsers
email <- person.getEmail // Assuming getEmail returns Option[String]
} yield (person, email)
Compare:
val p = getPerson1 // a potentially null Person
val favouriteColour = if (p == null) p.favouriteColour else null
with:
val p = getPerson2 // an Option[Person]
val favouriteColour = p.map(_.favouriteColour)
The monadic property bind, which appears in Scala as the map function, allows us to chain operations on objects without worrying about whether they are 'null' or not.
Take this simple example a little further. Say we wanted to find all the favourite colours of a list of people.
// list of (potentially null) Persons
for (person <- listOfPeople) yield if (person == null) null else person.favouriteColour
// list of Options[Person]
listOfPeople.map(_.map(_.favouriteColour))
listOfPeople.flatMap(_.map(_.favouriteColour)) // discards all None's
Or perhaps we would like to find the name of a person's father's mother's sister:
// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister
// with options
val fathersMothersSister = getPerson2.flatMap(_.father).flatMap(_.mother).flatMap(_.sister)
I hope this sheds some light on how options can make life a little easier.
The difference is subtle. Keep in mind to be truly a function it must return a value - null is not really considered to be a "normal return value" in that sense, more a bottom type/nothing.
But, in a practical sense, when you call a function that optionally returns something, you would do:
getPerson2 match {
case Some(person) => //handle a person
case None => //handle nothing
}
Granted, you can do something similar with null - but this makes the semantics of calling getPerson2 obvious by virtue of the fact it returns Option[Person] (a nice practical thing, other than relying on someone reading the doc and getting an NPE because they don't read the doc).
I will try and dig up a functional programmer who can give a stricter answer than I can.
For me options are really interesting when handled with for comprehension syntax. Taking synesso preceding example:
// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister
// with options
val fathersMothersSister = for {
father <- person.father
mother <- father.mother
sister <- mother.sister
} yield sister
If any of the assignation are None, the fathersMothersSister will be None but no NullPointerException will be raised. You can then safely pass fathersMothersSisterto a function taking Option parameters without worrying. so you don't check for null and you don't care of exceptions. Compare this to the java version presented in synesso example.
You have pretty powerful composition capabilities with Option:
def getURL : Option[URL]
def getDefaultURL : Option[URL]
val (host,port) = (getURL orElse getDefaultURL).map( url => (url.getHost,url.getPort) ).getOrElse( throw new IllegalStateException("No URL defined") )
Maybe someone else pointed this out, but I didn't see it:
One advantage of pattern-matching with Option[T] vs. null checking is that Option is a sealed class, so the Scala compiler will issue a warning if you neglect to code either the Some or the None case. There is a compiler flag to the compiler that will turn warnings into errors. So it's possible to prevent the failure to handle the "doesn't exist" case at compile time rather than at runtime. This is an enormous advantage over the use of the null value.
It's not there to help avoid a null check, it's there to force a null check. The point becomes clear when your class has 10 fields, two of which could be null. And your system has 50 other similar classes. In the Java world, you try to prevent NPEs on those fields using some combination of mental horesepower, naming convention, or maybe even annotations. And every Java dev fails at this to a significant degree. The Option class not only makes "nullable" values visually clear to any developers trying to understand the code, but allows the compiler to enforce this previously unspoken contract.
[ copied from this comment by Daniel Spiewak ]
If the only way to use Option were
to pattern match in order to get
values out, then yes, I agree that it
doesn’t improve at all over null.
However, you’re missing a *huge* class
of its functionality. The only
compelling reason to use Option is
if you’re using its higher-order
utility functions. Effectively, you
need to be using its monadic nature.
For example (assuming a certain amount
of API trimming):
val row: Option[Row] = database fetchRowById 42
val key: Option[String] = row flatMap { _ get “port_key” }
val value: Option[MyType] = key flatMap (myMap get)
val result: MyType = value getOrElse defaultValue
There, wasn’t that nifty? We can
actually do a lot better if we use
for-comprehensions:
val value = for {
row <- database fetchRowById 42
key <- row get "port_key"
value <- myMap get key
} yield value
val result = value getOrElse defaultValue
You’ll notice that we are *never*
checking explicitly for null, None or
any of its ilk. The whole point of
Option is to avoid any of that
checking. You just string computations
along and move down the line until you
*really* need to get a value out. At
that point, you can decide whether or
not you want to do explicit checking
(which you should never have to do),
provide a default value, throw an
exception, etc.
I never, ever do any explicit matching
against Option, and I know a lot of
other Scala developers who are in the
same boat. David Pollak mentioned to
me just the other day that he uses
such explicit matching on Option (or
Box, in the case of Lift) as a sign
that the developer who wrote the code
doesn’t fully understand the language
and its standard library.
I don’t mean to be a troll hammer, but
you really need to look at how
language features are *actually* used
in practice before you bash them as
useless. I absolutely agree that
Option is quite uncompelling as *you*
used it, but you’re not using it the
way it was designed.
One point that nobody else here seems to have raised is that while you can have a null reference, there is a distinction introduced by Option.
That is you can have Option[Option[A]], which would be inhabited by None, Some(None) and Some(Some(a)) where a is one of the usual inhabitants of A. This means that if you have some kind of container, and want to be able to store null pointers in it, and get them out, you need to pass back some extra boolean value to know if you actually got a value out. Warts like this abound in the java containers APIs and some lock-free variants can't even provide them.
null is a one-off construction, it doesn't compose with itself, it is only available for reference types, and it forces you to reason in a non-total fashion.
For instance, when you check
if (x == null) ...
else x.foo()
you have to carry around in your head throughout the else branch that x != null and that this has already been checked. However, when using something like option
x match {
case None => ...
case Some(y) => y.foo
}
you know y is not Noneby construction -- and you'd know it wasn't null either, if it weren't for Hoare's billion dollar mistake.
Option[T] is a monad, which is really useful when you using high-order functions to manipulate values.
I'll suggest you read articles listed below, they are really good articles that show you why Option[T] is useful and how can it be used in functional way.
Martians vs Monads: Null Considered Harmful
Monads are Elephants Part 1
Adding on to Randall's teaser of an answer, understanding why the potential absence of a value is represented by Option requires understanding what Option shares with many other types in Scala—specifically, types modeling monads. If one represents the absence of a value with null, that absence-presence distinction can't participate in the contracts shared by the other monadic types.
If you don't know what monads are, or if you don't notice how they're represented in Scala's library, you won't see what Option plays along with, and you can't see what you're missing out on. There are many benefits to using Option instead of null that would be noteworthy even in the absence of any monad concept (I discuss some of them in the "Cost of Option / Some vs null" scala-user mailing list thread here), but talking about it isolation is kind of like talking about a particular linked list implementation's iterator type, wondering why it's necessary, all the while missing out on the more general container/iterator/algorithm interface. There's a broader interface at work here too, and Option provides a presence-and-absence model of that interface.
I think the key is found in Synesso's answer: Option is not primarily useful as a cumbersome alias for null, but as a full-fledged object that can then help you out with your logic.
The problem with null is that it is the lack of an object. It has no methods that might help you deal with it (though as a language designer you can add increasingly long lists of features to your language that emulate an object if you really feel like it).
One thing Option can do, as you've demonstrated, is to emulate null; you then have to test for the extraordinary value "None" instead of the extraordinary value "null". If you forget, in either case, bad things will happen. Option does make it less likely to happen by accident, since you have to type "get" (which should remind you that it might be null, er, I mean None), but this is a small benefit in exchange for an extra wrapper object.
Where Option really starts to show its power is helping you deal with the concept of I-wanted-something-but-I-don't-actually-have-one.
Let's consider some things you might want to do with things that might be null.
Maybe you want to set a default value if you have a null. Let's compare Java and Scala:
String s = (input==null) ? "(undefined)" : input;
val s = input getOrElse "(undefined)"
In place of a somewhat cumbersome ?: construct we have a method that deals with the idea of "use a default value if I'm null". This cleans up your code a little bit.
Maybe you want to create a new object only if you have a real value. Compare:
File f = (filename==null) ? null : new File(filename);
val f = filename map (new File(_))
Scala is slightly shorter and again avoids sources of error. Then consider the cumulative benefit when you need to chain things together as shown in the examples by Synesso, Daniel, and paradigmatic.
It isn't a vast improvement, but if you add everything up, it's well worth it everywhere save very high-performance code (where you want to avoid even the tiny overhead of creating the Some(x) wrapper object).
The match usage isn't really that helpful on its own except as a device to alert you about the null/None case. When it is really helpful is when you start chaining it, e.g., if you have a list of options:
val a = List(Some("Hi"),None,Some("Bye"));
a match {
case List(Some(x),_*) => println("We started with " + x)
case _ => println("Nothing to start with.")
}
Now you get to fold the None cases and the List-is-empty cases all together in one handy statement that pulls out exactly the value you want.
Null return values are only present for compatibility with Java. You should not use them otherwise.
It is really a programming style question. Using Functional Java, or by writing your own helper methods, you could have your Option functionality but not abandon the Java language:
http://functionaljava.org/examples/#Option.bind
Just because Scala includes it by default doesn't make it special. Most aspects of functional languages are available in that library and it can coexist nicely with other Java code. Just as you can choose to program Scala with nulls you can choose to program Java without them.
Admitting in advance that it is a glib answer, Option is a monad.
Actually I share the doubt with you. About Option it really bothers me that 1) there is a performance overhead, as there is a lor of "Some" wrappers created everywehre. 2) I have to use a lot of Some and Option in my code.
So to see advantages and disadvantages of this language design decision we should take into consideration alternatives. As Java just ignores the problem of nullability, it's not an alternative. The actual alternative provides Fantom programming language. There are nullable and non-nullable types there and ?. ?: operators instead of Scala's map/flatMap/getOrElse. I see the following bullets in the comparison:
Option's advantage:
simpler language - no additional language constructs required
uniform with other monadic types
Nullable's advantage:
shorter syntax in typical cases
better performance (as you don't need to create new Option objects and lambdas for map, flatMap)
So there is no obvious winner here. And one more note. There is no principal syntactic advantage for using Option. You can define something like:
def nullableMap[T](value: T, f: T => T) = if (value == null) null else f(value)
Or use some implicit conversions to get pritty syntax with dots.
The real advantage of having explicit option types is that you are able to not use them in 98% of all places, and thus statically preclude null exceptions. (And in the other 2% the type system reminds you to check properly when you actually access them.)
Another situation where Option works, is in situations where types are not able to have a null value. It is not possible to store null in an Int, Float, Double, etc. value, but with an Option you can use the None.
In Java, you would need to use the boxed versions (Integer, ...) of those types.
Since arguments sent to a method in Java point to the original data structures in the caller method, did its designers intend for them to used for returning multiple values, as is the norm in other languages like C ?
Or is this a hazardous misuse of Java's general property that variables are pointers ?
A long time ago I had a conversation with Ken Arnold (one time member of the Java team), this would have been at the first Java One conference probably, so 1996. He said that they were thinking of adding multiple return values so you could write something like:
x, y = foo();
The recommended way of doing it back then, and now, is to make a class that has multiple data members and return that instead.
Based on that, and other comments made by people who worked on Java, I would say the intent is/was that you return an instance of a class rather than modify the arguments that were passed in.
This is common practice (as is the desire by C programmers to modify the arguments... eventually they see the Java way of doing it usually. Just think of it as returning a struct. :-)
(Edit based on the following comment)
I am reading a file and generating two
arrays, of type String and int from
it, picking one element for both from
each line. I want to return both of
them to any function which calls it
which a file to split this way.
I think, if I am understanding you correctly, tht I would probably do soemthing like this:
// could go with the Pair idea from another post, but I personally don't like that way
class Line
{
// would use appropriate names
private final int intVal;
private final String stringVal;
public Line(final int iVal, final String sVal)
{
intVal = iVal;
stringVal = sVal;
}
public int getIntVal()
{
return (intVal);
}
public String getStringVal()
{
return (stringVal);
}
// equals/hashCode/etc... as appropriate
}
and then have your method like this:
public void foo(final File file, final List<Line> lines)
{
// add to the List.
}
and then call it like this:
{
final List<Line> lines;
lines = new ArrayList<Line>();
foo(file, lines);
}
In my opinion, if we're talking about a public method, you should create a separate class representing a return value. When you have a separate class:
it serves as an abstraction (i.e. a Point class instead of array of two longs)
each field has a name
can be made immutable
makes evolution of API much easier (i.e. what about returning 3 instead of 2 values, changing type of some field etc.)
I would always opt for returning a new instance, instead of actually modifying a value passed in. It seems much clearer to me and favors immutability.
On the other hand, if it is an internal method, I guess any of the following might be used:
an array (new Object[] { "str", longValue })
a list (Arrays.asList(...) returns immutable list)
pair/tuple class, such as this
static inner class, with public fields
Still, I would prefer the last option, equipped with a suitable constructor. That is especially true if you find yourself returning the same tuple from more than one place.
I do wish there was a Pair<E,F> class in JDK, mostly for this reason. There is Map<K,V>.Entry, but creating an instance was always a big pain.
Now I use com.google.common.collect.Maps.immutableEntry when I need a Pair
See this RFE launched back in 1999:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4222792
I don't think the intention was to ever allow it in the Java language, if you need to return multiple values you need to encapsulate them in an object.
Using languages like Scala however you can return tuples, see:
http://www.artima.com/scalazine/articles/steps.html
You can also use Generics in Java to return a pair of objects, but that's about it AFAIK.
EDIT: Tuples
Just to add some more on this. I've previously implemented a Pair in projects because of the lack within the JDK. Link to my implementation is here:
http://pbin.oogly.co.uk/listings/viewlistingdetail/5003504425055b47d857490ff73ab9
Note, there isn't a hashcode or equals on this, which should probably be added.
I also came across this whilst doing some research into this questions which provides tuple functionality:
http://javatuple.com/
It allows you to create Pair including other types of tuples.
You cannot truly return multiple values, but you can pass objects into a method and have the method mutate those values. That is perfectly legal. Note that you cannot pass an object in and have the object itself become a different object. That is:
private void myFunc(Object a) {
a = new Object();
}
will result in temporarily and locally changing the value of a, but this will not change the value of the caller, for example, from:
Object test = new Object();
myFunc(test);
After myFunc returns, you will have the old Object and not the new one.
Legal (and often discouraged) is something like this:
private void changeDate(final Date date) {
date.setTime(1234567890L);
}
I picked Date for a reason. This is a class that people widely agree should never have been mutable. The the method above will change the internal value of any Date object that you pass to it. This kind of code is legal when it is very clear that the method will mutate or configure or modify what is being passed in.
NOTE: Generally, it's said that a method should do one these things:
Return void and mutate its incoming objects (like Collections.sort()), or
Return some computation and don't mutate incoming objects at all (like Collections.min()), or
Return a "view" of the incoming object but do not modify the incoming object (like Collections.checkedList() or Collections.singleton())
Mutate one incoming object and return it (Collections doesn't have an example, but StringBuilder.append() is a good example).
Methods that mutate incoming objects and return a separate return value are often doing too many things.
There are certainly methods that modify an object passed in as a parameter (see java.io.Reader.read(byte[] buffer) as an example, but I have not seen parameters used as an alternative for a return value, especially with multiple parameters. It may technically work, but it is nonstandard.
It's not generally considered terribly good practice, but there are very occasional cases in the JDK where this is done. Look at the 'biasRet' parameter of View.getNextVisualPositionFrom() and related methods, for example: it's actually a one-dimensional array that gets filled with an "extra return value".
So why do this? Well, just to save you having to create an extra class definition for the "occasional extra return value". It's messy, inelegant, bad design, non-object-oriented, blah blah. And we've all done it from time to time...
Generally what Eddie said, but I'd add one more:
Mutate one of the incoming objects, and return a status code. This should generally only be used for arguments that are explicitly buffers, like Reader.read(char[] cbuf).
I had a Result object that cascades through a series of validating void methods as a method parameter. Each of these validating void methods would mutate the result parameter object to add the result of the validation.
But this is impossible to test because now I cannot stub the void method to return a stub value for the validation in the Result object.
So, from a testing perspective it appears that one should favor returning a object instead of mutating a method parameter.