开发者

Can one function of java return two types in different condition?

public String[] getValue(String keyName) {

    ArrayList arraylist = (ArrayList) value.get(getKey(keyName));

    String[] valueArray = new String[arraylist.size()];

    for (int i = 0; i < valueArray.length; i++)
        valueArray[i] = arraylist.get(i).toString();

    return valueArray;
}

I want to modify this function to make it easier to use. If the return String array contains only one element.I want it to be returned in S开发者_运维知识库tring(not String array) type.

How can I do this in Java?


Well, you can declare that the method returns Object instead of String[]... but that makes it harder to use, not easier.

  • You can't declare that a method can return type X or type Y, unless either X or Y is a supertype of the other (in which case other subtypes could be returned, too)
  • You can't declare two methods which differ only in return type

Think about what the calling code would look like, and I think you'll see why it's actually simpler to be consistent.

Of course, you could always create your own OneOrMany interface which wrapped up common operations, and could have either a single element or many... but again, I can't see the benefit. (I can see the benefit in returning a List<String> or an Iterable<String> rather than an array though.)

EDIT: Having seen your comment on Dilum's answer, in a situation where the caller has an expectation of a single element, I would either create helper methods which allowed that to be expressed for collections or simply have two methods:

public Collection<String> getValues()
{
    ...
}

public String getSingleValue()
{
    // Throws an exception if there's more than one
}

The latter could either go via the former method, or potentially be optimized for the case of expecting (and validating) a single result.

That way it's very clear in the calling code what you're expecting and why, and having that expectation validated.

I probably wouldn't have introduced a new interface, as that would mean I'd either have to wrap existing collection classes or subclass them (argh). In C# it's easy, as you can just use the Single() extension method (along with SingleOrDefault, FirstOrDefault etc)...


No.

How would you be able to use the return value if it were possible? What type would you assign it to?

XXX foo = getValue(keyName);
^^^
What goes here?


A project I worked on had to deal with something similar. There were some map-like objects. Each key had zero or more values. But there were some keys where we knew there was exactly one value. Others had at most one. Others had zero or more.

We addressed this by introducing an extension to Collection:

public class CardinalityException extends RuntimeException {
  ...
}

public interface Values<T> extends Collection<T> {

  /**
   * @return the equivalent of iterator().next() if size() == 1
   * @throws CardinalityException if collection is empty 
   *         or contains more than one element.
   */
  T unique() throws CardinalityException;

  /**
   * @return one element from the collection, or null if empty
   */
  T one();
}

So essentially, we always returned a Values<T>. If the caller knew there was just one value, it would simply use unique() or one() depending on whether no value was valid.

For cases where the number of values were not important, we just kept values in the wrapped form.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜