How can I implement a comparator to compare two numbers? - java

I have a class OffbyOne where I declare an interface as a comparator called compare where I'm supposed to take two integers and return True if the difference between two integers is 1, and false if not.
Here is my code so far:
public static class OffbyOne {
public interface Compare {
int x;
int y;
if ((x-y) == 1) {
return true;
} else if ((y-x)==1) {
return true;
}
return false
public boolean equalChars(char x, char y); {
if (Compare(x,y) == true) {
return true;
}
return false;
}
I'm struggling to understand how comparators work in Java and what do I have to do. If anyone can please help me with this and then provide explanations for how it is supposed to be done, it would be great for me.
Thank you.

Comparator already exists in java - java.util.Comparator. It is something completely different from what you describe: Java's own comparator is a thing that you give 2 objects, and the comparator tells you which of the two 'comes earlier' in a sorting. Such an oracle is all you need to efficiently sort stuff.
It's allowed, but a bad idea, to name types the same as core java types. You can make your own String, which is different from java's own String in all ways (your String does not in any way replace java's string), it's just a confusing name, is all. You're doing the same thing with Comparator here. Bad idea. I'd call it OffByOne or similar.
declare an interface as a comparator called compare where I'm supposed to take two integers and return True if the difference between two integers is 1, and false if not.
This makes no sense whatsoever. You must have misunderstood the assignment. An interface describes the what and does not describe the how, whereas what you just said is describing the how. That's just not what interfaces do - they don't get to define the how. They only define the what. You're describing an implementation, not an interface.
public interface Compare {
int x;
int y;
if ((x-y) == 1) {
You can't stick code in types like this. You can stick only methods, fields, constructors, and other types in there. You can stick code in a method and then stick the method in a type, if you want. In addition, given that it is an interface, you can't stick code in one at all - interfaces define what a class can do, not how it does it (there is the default mechanism. That's definitely not what this assignments wants you to do so, so it doesn't apply here).
This would be an interface:
public interface DifferenceOfOne<T> {
public boolean isDifferenceOfOne(T a, T B);
}
This says: There is such a thing as a 'DifferenceOfOne' implementation for any given type. Such a class would implement the method isDifferenceOfOne, which takes in 2 parameters, both of that given type, and which then returns a boolean.
You can then make an implementation for the Integer type:
class IntDiffOfOne implements DifferenceOfOne<Integer> {
public boolean isDifferenceOfOne(Integer a, Integer b) {
return (a - 1 == b || b - 1 == a);
}
}
DifferenceOfOne<Integer> intDiffOfOne = new IntDiffOfOne();
Or in more common, modern java syntax:
DifferenceOfOne<Integer> intDiffOfOne = (a, b) -> (a - 1 == b || b - 1 == a);
And someone else can write a DiffOfOne implementation that, I dunno, tells you if any 2 LocalDate instances differ by exactly 1 day, perhaps, that would be a DifferenceOfOne<LocalDate>.
If this all sounds confusing to you - go back to whomever gave you this assignment, as either the assignment makes no sense, or you misheard/misunderstood it.

Related

How to override Java's restrictions for objects

I am given an instance of the object class (String, int, double, or boolean) from a database. I need to write a method that can compare this object to something else (String, int, double, or boolean) using binary operators (e.g. <=, !=, >, etc.). I will only run this method if the two objects are of the same type. My method looks like
public boolean comparison(Object a, Object b, String operator) {
int result = a.compareTo(b);
String a2 = a.getClass().getName();
//followed by if/else if blocks to return true or false
//depending on operator and result
}
I have designed the if/else if blocks to ensure that no binary operator will be used for incompatible types (e.g. >= for a String object). The problem is that I get a "can't find symbol error" when I try to compile because the object class doesn't have a compareTo() method. If this was python, there wouldn't actually be any issue because I would never be putting anything into the comparison function that didn't have a compareTo() method. However, because of java's formatting I'm forced to declare the input as 'Object' because I can't say specifically what type of object I have to compare at a given moment.
Is there some way I could override Java's restrictions and force it to trust me that Object a will always have a compareTo() method? Because right now, it seems like I'm going to have to downcast the objects into Strings, ints, doubles, or booleans, and then write 4 different new comparison functions for each data type.
Since the compareTo method is declared in the java.lang.Comparable<T> interface, the usage of Bounded Type Parameters can constrain your a and b arguments in order to accept only objects which implement the interface itself.
You can check the operator parameter in order to affect the boolean result.
If you wish, the usage of an enum value helps to avoid string mismatching.
For brevity, the code below doesn't take in account null values.
enum Operator {
GREATER_OR_EQUALS,
LESS_OR_EQUALS
}
public <T extends Comparable<T>> boolean comparison(T a, T b, Operator operator) {
int test = a.compareTo(b);
switch(operator) {
case GREATER_OR_EQUALS:
return test >= 0;
default:
return test <= 0;
}
}
The Java way is to first use the instanceof operator to then cast to an appropriate class:
if (a instanceof String && b instanceof String) {
String aAsString = (String) a;
int comparisonResult = a.compareTo(b);
compareTo() gives you a negative result if a < b, 0 when a == b and a positive result if a > b. So alone that int result tells you enough to decide what your potential comparison operations should result in. The numeric types int/Integer, ... have similar methods.
Of course this only works if your assumptions are really correct and the object is really a String or Boolean. And please note that boolean and Boolean are two somehow different types!
Casting variables in Java
The top answer summarizes what I wanted to do. The code successfully compiled when I said
int result;
if (a instanceof Comparable && b instanceof Comparable) {
result = ((Comparable) a).compareTo((Comparable) b);
}
I haven't tested it, but fantaghirocco's solution also seems like it could work.

What is the best implementation of a state toggle in Java? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What is the best (in terms of flexibility) object-oriented implementation for an alternating state toggle in Java? The implementations I have listed are only what I have come up with and are not exhaustive.
Note: The answer to this question is not subjective. By the principles of object-oriented programming, the context of usage for this implementation should be irrelevant.
[Edit] The focus here is on the structure of the code. Obviously the actual functionality is so simple as to not even warrant the effort of a dedicated implementation.
public class ImpureToggle<T> implements Supplier<T> {
//false represents state a, true represents state b
private boolean state;
private final T a;
private final T b;
public ImpureToggle(T a, T b) {
this.a = a;
this.b = b;
}
// returns a different reference depending on internal state
#Override
public T get() {
return state ? b : a;
}
public void toggle() {
state = !state;
}
}
public class ConsumerToggle<T> implements Consumer<Consumer<T>> {
private final T a;
private final T b;
//false represents state a, true represents state b
private boolean state;
public ConsumerToggle(T a, T b) {
this.a = a;
this.b = b;
}
#Override
public void accept(Consumer<T> t) {
t.accept(state ? b : a);
}
public void toggle() {
state = !state;
}
}
public interface ImpureStaticToggle {
// reassigns parameter 'state'
static <T> void toggle(T state, T a, T b) {
state = state == a ? b : a;
}
}
public interface PureStaticToggle {
// returns a different reference depending exclusively on external input
static <T> T toggle(boolean state, T a, T b) {
//false represents state a, true represents state b
return state ? b : a;
}
}
/*
Just as an example of an unarguably bad implementation:
*/
public class MutableToggle<T> implements Supplier<T> {
private T state;
private final T a;
private final T b;
public MutableToggle(T a, T b) {
state = a;
this.a = a;
this.b = b;
}
// exposes a mutable reference, which could completely break the logic of this
// object and others
#Override
public T get() {
return state;
}
public void toggle() {
state = state == a ? b : a;
}
}
[Edit] ternary for inverting boolean (was done for consistency) replaced with logical complement operator as per #gargkshitiz.
By the principles of object-oriented programming, the context of usage for this implementation should be irrelevant.
Not sure what this means, and you seem firm on not giving context, but I'll try my best to give deeper insight into why I feel what you're doing doesn't make much sense.
Don't pass booleans as arguments1
broadly speaking if there is a parameter passed into a function that selects specific behaviour to be executed then further step-wise refinement is required; Breaking up this function in to smaller functions will produce more highly cohesive ones
The problem with a parameter passed in as you describe, is that the function is doing more than two things; it may or may not check the users access rights depending on the state of the Boolean parameter, then depending on that decision tree it will carry out a piece of functionality.
It would be better to separate the concerns of Access Control from the concerns of Task, Action or Command.
Take, for example, String#regionMatches. It has an overload for ignoring case.
public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {
if (!ignoreCase) {
return regionMatches(toffset, other, ooffset, len);
}
// Note: toffset, ooffset, or len might be near -1>>>1.
if ((ooffset < 0) || (toffset < 0)
|| (toffset > (long)length() - len)
|| (ooffset > (long)other.length() - len)) {
return false;
}
byte tv[] = value;
byte ov[] = other.value;
if (coder() == other.coder()) {
return isLatin1()
? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len)
: StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len);
}
return isLatin1()
? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len)
: StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len);
}
This is a clear example, from the standard library, of why you should avoid boolean parameters for your behaviors.
Notice how the boolean determines which implementation should be used: one which ignores casing, or one which doesn't.
This is a cheap trick typically used to make choosing an implementation less verbose:
for(int i = 0; i < 100; i++) {
boolean even = i % 2 == 0;
boolean matches = text.regionMatches(even, ...);
// use matches
}
However, at a glance, it's not clear exactly what that condition is determining. We're forced to open the documentation (or worse: the implementation).
Compare that to:
for(int i = 0; i < 100; i++) {
boolean even = i % 2 == 0;
boolean matches = false;
if(even)
matches = text.regionMatchesIgnoreCase(...);
else
matches = text.regionMatches(...);
// use matches
}
Or
for(int i = 0; i < 100; i++) {
boolean even = i % 2 == 0;
boolean matches = even ? text.regionMatchesIgnoreCase(...) : text.regionMatches(...);
// use matches
}
It's more verbose, but it's clearer as to what the condition is for: determining whether casing should be ignored.
regionMatchesIgnoreCase would be easier to comprehend at a glance, rather than needing to read the documentation to determine what the boolean represents.
Comprehension is important for avoiding time waste when fixing critical bugs. Assuming you want to blindly apply principles, this knocks out PureStaticToggle.
Don't use interfaces as utility classes1 (easy fix)
This seems to me to cut against the grain of interfaces. One would have to look around the API to determine that there are no classes that implement this interface, and that there are no producers or consumers of this interface
If you look at the new Java 8 APIs, you'll see that the final class idiom is still used despite the ability to add static methods on interfaces.
This would remove both interface alternatives. It can be easily worked around: You can ignore this principle, or use a regular class.
But, what would this utility type be for? What other methods would be in the utility type? 1 type per utility implementation seems excessive, bloats the namespace.
Using an interface doesn't make your code OOP. Interfaces in general are not an OOP concept. However, their initial/primary function (before static and private methods) were OOP. Java supports multiple paradigms, hence the exposure of static methods in interfaces.
Design by contract1
Software designers should define formal, precise and verifiable interface specifications for software components, which extend the ordinary definition of abstract data types with preconditions, postconditions and invariants.
Assuming you want sturdy interfaces for your implementations, you should expose contracts.
If you aren't familiar with contracts, they're a set of rules followed by both the client of the code & the code itself. If the code doesn't work based on what it states in the contract, it's considered to be bugged.
In Java, they're typically defined by JavaDocs. However, no matter how you choose to expose your contracts to users, the point here is that clients should know what that piece of code will and won't do, and code should define how the user should use the code.
How would your contract look for the types you've proposed?
Contracts are built based off requirements. From the code shown, the requirements aren't clear. In fact, the interface approaches
In terms of OOP, getters violate encapsulation1
It is not encapsulation and [using] Lombok [to generate getters & setters] is just making to work with procedural code less painful
And data structure is not an object
You should encapsulate state and implementation details so that object has full control on that. Logic will be focused inside object and will not be spread all over the codebase
Getters are procedural, not object oriented.
In OOP, objects communicate via behaviors. When you expose getters, you are exposing properties of the object.
The reason why OOP prefers hidding the properties of objects can vary, with some being obvious: Properties are eventually used in logic somewhere, and the logic/behavior which relies on that property won't be easily apparent if exposed.
Using a call-back to handle the logic of the property, especially how you're doing it in ConsumerToggle, is not much different from exposing a getter.
ImpureStaticToggle won't work as it is (easy fix)
Java is pass by value.
String s = "first";
toggle(s, "second", "third");
System.out.println(s); // prints "first"
The value of s will remain unchanged. It can be fixed with a return statement & assignment when calling the function:
<T> T toggle(T state, T a, T b) {
return state == a ? b : a;
}
T value = toggle(value, a, b);
However, this approach is still flawed for reasons mentioned in some of the sections above.
Last notes
ImpureStaticToggle and PureStaticToggle are different.
The former determines a return value based on the type of a reference
The latter determines a return value based on the result of any condition.
You can use PureStaticToggle to achieve what ImpureStaticToggle does. But, you cannot use ImpureStaticToggle to do what PureStaticToggle can do. They aren't completely interchangable, and those details should impact your choice.
What you are ultimately doing with the code you've shown is changing the implementation based on a condition. That's all that's going on here.
I hate to say it, but if your goal is to follow OOP principles by "tossing the book" at your code, then all your alternatives violate commonly practiced OOP principles.
Don't overcomplicate things. I don't see any benefit in encapsulating/hiding the use of a ternary. Use the ternary as is, when needed. Invest the time you would have invested in this design into something important.
Also, for your interfaces, toggle isn't the best name either, since the behavior isn't actually toggling anything - a better name would be chooseValue or determineValue, as that's what the method is actually doing.
Your first implementation (ImpureToggle) looks okay. Just change the toggle method to be:
state = !state
But having such a Toggler with a public toggle method looks like an overkill. Either use the whole class with proper access modifiers OR instead use a local method to limit the scope and the potential bugs.

Java double colon operator from compile time to byte code generation?

In this question the author uses the following example:
#Override
public final OptionalInt max() {
return reduce(Math::max); //this is the gotcha line
}
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Also how would one write the javadoc for something like this?
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Not quite :). Let's start by figuring out what the reduce operator actually does. The documentation explains that it performs a reduction on a sequence of numbers by applying an algorithm that is logically equivalent to the following:
public OptionalInt reduce(IntBinaryOperator op) {
boolean foundAny = false;
int result = 0;
for (int element : [this stream]) {
if (!foundAny) {
foundAny = true;
result = element;
}
else {
result = op.applyAsInt(result, element);
}
}
return foundAny ? OptionalInt.of(result)
: OptionalInt.empty();
}
Seems simple enough. If you can tell it how to take two numbers and 'reduce' or 'combine' them into one, then reduce knows how to extend that logic to reduce an entire sequence into a single number. It handles the edge cases and the aggregation for you. All it needs from you is a function that takes in two numbers and gives it one back. That function should conform to the functional interface IntBinaryOperator.
A functional interface is an interface that is meant to describe a single function. Specifically, it describes the argument types and the return type. The rest is largely superfluous. The signature for an IntBinaryOperator looks like this:
int applyAsInt(int left, int right);
You can provide a function that conforms to this specification in several ways. Prior to Java 8, you might have done something like this:
stream.reduce(
new IntBinaryOperator() {
public int applyAsInt(int a, int b) {
return b > a ? b : a;
}
}
);
Java 8 gives us a shorthand form for functional interfaces called lambda expressions. These are a bit more concise, and while they are conceptually similar to anonymous inner classes, they're not quite the same thing.
stream.reduce((a, b) -> b > a ? b : a);
Both functions above are equivalent: they take in two numbers and return the larger of the two. As it turns out, every standard programming library has a function that does exactly the same thing. In Java, that function is Math.max. So rather than writing this logic myself, I can delegate to Math.max:
stream.reduce((a, b) -> Math.max(a, b));
But wait! All reduce wants is a function that takes two numbers and returns one. Math.max does that, so do I even need to wrap it in a lambda? It turns out I don't; I can tell reduce to just call Math.max directly:
stream.reduce(Math::max);
This says "I know you want a function, so I'm show you by name where to find one that's already been written". The compiler knows that Math.max conforms to the (int, int) -> int specification we need, so it emits some bytecode telling the VM how to 'bootstrap' it once it's needed. When the JVM hits your call to reduce, it calls a special method that generates a wrapper class implementing IntBinaryOperator that delegates to Math.max in its implementation of applyAsInt. It only performs this 'bootstrapping' step once. Since calling Math.max doesn't rely on anything other than the two numbers that get passed in, it can cache that implementation and use it the next time you wind up on this code path.
Pre Java 8, this would have been written as:
public MyMathInteface {
OptionalInt max(Integer a, Integer b);
}
public static final MyMathInterface reducing = new MyMathInterface() {
#Override
public OptionalInt max(Integer a, Integer b) {
return OptionalInt.of(Math.max(a, b));
}
};
#Override
public final OptionalInt max() {
return reduce(reducing);
}
Then reduce would be defined as:
public static OptionalInt reduce(MyMathInteface toReduce) {
return toReduce.max(someValueA, someValueB);
}
So to answer your question, no arguments are passed to Math::max, because those values are retrieved by the reduce function. They could be constants or they could be retrieved from some other place.
In any case, the use of the max method in this way is called a method reference, that is where you do SomeObject::method. That :: operator creates a method reference. It returns a function, but does not call the function. The user (reduce) is responsible for calling the function.

How to typesafe check equality of booleans?

public class ComplexObject {
private boolean isA, isB;
}
//custom comparator
public boolean checkComplexObject(ComplexObject o1, ComplexObject o2) {
return o1.getIsA() == o2.getIsB();
}
Now when I change the data type in ComplexObject from boolean to String for example, the comparator will not break, nor will I notice that in future I would compare Strings instead of booleans and thus get different results.
Question: how could I compare the boolean properties typesafe, so that I get compilation error when I change the datatype of the fields?
One very simple thing you can do is put in a redundant cast:
return (boolean)o1.getIsA() == (boolean)o2.getIsB();
You can also define a method that only accepts boolean:
static boolean booleanEquals(boolean a, boolean b) {
return a == b;
}
Then call booleanEquals instead of using ==.
As a side note, this programming seems a bit overly defensive to me.
There are a few things you can do, but all of them will make your code less readable, and therefore I would advise against them.
For example :
return o1.getIsA() ^ o2.getIsB() == false;
or
return (o1.getIsA() && o2.getIsB()) || (!o1.getIsA() && !o2.getIsB());
You can use XOR for that:
return o1.getIsA() ^ o2.getIsB();
The better question is, why would you do that?
If you refactor (well, change heavily) your attributes from boolean to String you should always check the affected code. If you want code workarounds for a common practice (double checking), you're may introduce overly complicated code in your whole application.
If you're aware of that problem, why dont you put a comment directly on your affected class attributes, that it may be compared by ==. If you want or another dev wants to change it's type later on, they will be warned.

How to handle numbers in a generic fashion?

My question is eerily similar to "Writing a generic class to handle built-in types" including being inspired by the fact of working on a class to handle operations on matrices.
Although that question was asked using C# and pointed to an article on Generic Operators.
I don't get it. Java Number does not have an add method so you can have a method like:
public Number myAdd(Number a, Number b){
return a.add(b);
}
So how do you handle a case where you want to be able to handle multiple types of Numbers in Java?
The fundamental problem is with the Java type system which is very primitive.
Since there is no notion of a sealed set of types in Java (nor is it possible for Java to infer the types like Haskell does) there is no way to make make a general Number + Number -> Number without trickery.
For primitives (and those objects like Integer which can be automagically mapped to them) types promotion and the + operation is part of the language. (And this is actual part of the problem: what should Number a + Number b return where a and b are of different types?)
If you really want this behavior you'll have to find (or create) your own custom class that either uses reflection or a series (of checks and) casts and such. Even if you use generics (remember that generics are type-erased) casting will need to be done.
I imagine these problems are part of the reason why Number is as bland as it is.
How good do you want the result to be? If the answer is "good enough, mostly", then this should be sufficent:
public Number myAdd(Number a, Number b){
return a.doubleValue() + b.doubleValue();
}
But if you want something that, say, matches the promotion semantics of Java primitives, you're probably going to have to write it yourself. And then you'll have to figure out what the rules are for all combinations of "non-standard" Number implementations, including BigDecimal, BigInteger, AtomicDouble, AtomicLong, everything in org.apache.commons.lang.mutable, and any random implementation that somebody might decide to write next Tuesday.
It's not clear what the right thing to do is in most of these cases -- converting everything to BigDecimal, for instance, is not an option if one of the arguments is Apache Commons' Fraction.ONE_THIRD; and besides, doing the conversion in a general way presents the same problems as doing the addition in a general way. But having an add() method on Number would require every Number implementation to handle all these cases -- and that's probably why it isn't there.
I don't get it. Java Number does not
have an add method ...
Suppose that java.lang.Number did have an add method or methods, how would you define its signature? How would you define its semantics? How would you deal with "mixed mode" arithmetic?
While it is no doubt possible to answer these questions and design an API, the result is likely to be tricky to use correctly. In addition, it is most unusual for an application to need to perform "representation agnostic" arithmetic. Usually you want / need explicit control over the way that arithmetic is performed and conversions happen. (The Java primitive type promotion rules are already difficult enough for people to get their heads around!!)
All in all, I think that Sun have done us a good service by not trying to support arithmetic in the Number API.
One way of implementing a generic add method is to let the left hand argument infer the return type.
package mixins;
import java.math.BigDecimal;
public class Numbers {
public static boolean isZ(Number n) {
return n instanceof Integer || n instanceof Long || n instanceof Short || n instanceof Byte;
}
public static boolean isR(Number n) {
return n instanceof Double || n instanceof Float;
}
public static BigDecimal add(BigDecimal a, Number b) {
if (b instanceof BigDecimal) {
return a.add((BigDecimal) b);
} else if (isZ(b)) {
return a.add(new BigDecimal(b.longValue()));
} else if (isR(b)) {
return a.add(new BigDecimal(b.doubleValue()));
}
throw new IllegalArgumentException("No valid big decimal translation for " + b.getClass());
}
public static Integer add(Integer a, Number b) {
return a + b.intValue();
}
public static Long add(Long a, Number b) {
return a + b.longValue();
}
public static Float add(Float a, Number b) {
return a + b.floatValue();
}
public static Double add(Double a, Number b) {
return a + b.doubleValue();
}
}
If this is implemented as static methods, you can use static imports.
import static mixins.Numbers.*;
public class Example {
public static void main(String[] args) {
BigDecimal fortytwo = new BigDecimal(42);
BigDecimal fiftyfive = add(fortytwo, 13);
System.out.println(fiftyfive);
}
}
You cannot add any two numbers, for the reasons other pointed out, but you can add numbers of same type, and the result will also be that same type.
You can create generic arithmetics in Java, with something like this:
interface Arithmetics<T> {
T add(T val1, T val2);
}
class IntegerArithmetics implements Arithmetics<Integer> {
Integer add(Integer val1, Integer val2) { return val1 + val2; }
}
//similarly DoubleArithmetics, BigIntegerArithmetics, ...
Generic Java Math library does exactly that for you.
Actually, I've been working on a generic "real" number class (called 'Value') for a while now, but more as a design exercise than anything; and I can see why it hasn't been done sooner.
First off, you have to have to have some basic rules to work by - I chose to use Java FP (IEEE-754) rules - which means you have have to allow for results like 'infinity' and 'NaN', even if the type doesn't actually support them; and things like reciprocals have proved surprisingly tricky. But I'm getting there, and it's been a fun journey.
One thing that helped me was deciding early on that I needed to deal with "identity" values - specifically 0, 1, and -1, along with -0, +/-infinity and NaN as special cases; the reason being that (for example) multiplication by any of them usually doesn't need any calculation at all.
x * 1 = x, x * NaN = NaN, x * 0 = 0 (or NaN), and x * +/-infinity = +/-infinity; and there are similar rules for division, addition and subtraction, which means you can eliminate a lot of dross quickly and consistently.
And that leaves implementers to only have to deal with cases that do need calculation.
Of course, not all types will support all identities, but if you make them methods, you can just throw an exception when either an operand or a result is "unsupported".
Hope it helps anyone else interested in giving it a bash, but it's not as simple it looks. :-)
Personally, I use BigDecimals for almost everything (but that is mainly because I work with currency values). They handle all numeric values of any size. Because of that, in my opinion they are a generic value and could be used as such in your hypothetical example instead of the Number abstract class. Everything can be turned into a BigDecimal, why not use it?
public BigDecimal myAdd(BigDecimal a, BigDecimal b) {
return a.add(b);
}
EDIT: To address BigBrothers comment below, you could always use the doubleValue() method to create your own generic method. The only problem with this is that you may lose precision in some rare cases where someone IS passing in a BigDecimal and it is larger than a Double.maxValue
public Number myAdd(Number a, Number b) {
return new BigDecimal(a.doubleValue() + b.doubleValue());
}
A BigDecimal is a Number, so returning one is of no consequence.

Categories

Resources