I'm taking a java course on lynda.com, and the course was explaining how to "cast" a variable if you want to shorten it.
WIDENING: Widening a variable is making it larger (e.g. int int1 = 4030; long long1 = int1;)
SHORTENING: Shortening a variable is making it smaller, and requires special syntax. (e.g. int int2 = 5024; short int3 = (short) int2;).
So, my question is, why would anyone want to do this? What's the advantage? If you know you'll need to widen a variable at some point, why don't you just start it as that variable? And why would you want to make your data type smaller if you're shortening? If you think that it could be used like this:
byte byte1 = 127;
byte1++;
if (byte1 > 127) {
short short1 = byte1;
}
(I know that this would give an error message, but you get the rough idea.)
You could do this, but why? It wouldn't save data, because it just adds more lines of code which would take up that data.
There are several reasons you might want to "shorten" a variable.
One is that an API or library you are working with requires data to be passed that is of a "shorter" type than the type you were using in your code.
Another is to save space. For example, if I only need to store a two digit number, using a long would be overkill as it would use much more system memory than is needed. This isn't something you normally need to worry too much about, but it could be an issue on certain systems or for very large projects.
There may be even more reasons; these are just a few examples.
You absolutely can't avoid this if you must pass a value received from a function that is out of your control into another function that is also out of your control:
package abc.def:
public class Foo {
public static long foo() { ... }
}
package xyz.qwerty:
public class Bar {
public static void bar(int n) { ... }
}
Your code:
import xyz.qwerty.Bar;
import abc.def.Foo;
...
Bar.bar((int)Foo.foo());
There may be intermediate variables temporarily holding the value received from Foo.foo() before it gets to Bar.bar() but that doesn't eliminate the inevitable need for converting from one type to another, which must happen somewhere in between.
Imagine you want to implement a min(...) method to calculate the minimum of two numbers. You could simply write:
public static double min(double lhs, double rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
and through auto-casting (or what you refer to as "widening"), you could call this method with all primitives in Java. The downside, however, is that the result would always be double and if you want to save it as an int, you would have to downcast the result:
int i1 = 0;
int i2 = 100;
int max = (int) max(i1, i2);
It would be nice if the method returned an int iff. both parameters are int, a long iff. one parapeter is long and the other parameter is long or int and so on. This would result in the following code1:
public static int min(int lhs, int rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
}
public static long min(long lhs, long rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
}
public static float min(float lhs, float rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
public static double min(double lhs, double rhs) {
if (lhs >= rhs) {
return (lhs);
}
// else if (rhs > lhs) {
return (rhs);
// }
}
Then you could write:
int i = 0;
long g = 1L;
float f = 2f;
double d = 3.0;
int intMax = max(i, i);
long longMax = max(i, g);
float floatMax = max(i, f);
double doubleMax = max(l, d);
Through the means of autocasting and method overloading, the most specific method will be called2,3.
1 You culd write those methods for byte, short and charas well. I would not recommend doing so since all arithemtic operations in Java return at least something of type int (e.g. byte + byte will return an int). This is due to the fact that the JVM does not know of the primitives boolean, char, byte and short, they are represented as int (see JLS §2.11.1).
2 The exact behaviour is specified in JLS, §15.12.2.5
3 This is actually the same mechanism used forjava.lang.Math's implementation of min(...), its implementation is slightly different.
Related
I wanted to make such class for calculating average value:
public static class AverageValue<T extends Number> {
T data = 0; //ERROR: incompatible types: int cannot be converted to T
int count = 0;
public AverageValue() {}
public AverageValue(T data) {
this.data = data;
count = 1;
}
public void add(T num) {
data+=num; //ERROR: bad operand types for binary operator '+'
count++;
}
public T average() {
return data/(T)count; //ERROR: incompatible types: int cannot be converted to T
}
}
I am not really getting why do we have interface Number if it doesn't abstract number. Because that's what interfaces do - abstract operations with data without holding the data themselves.
The above also makes it clear that you'll probably not be ever able to make your own number implementation (eg. number with unlimited size and precision for some really freaky experimental math programs).
I tried the same with Number instead of generic T with the very same results. Only difference is that Number x = 0 is actually valid.
Is there a way to trick java to compile this or do I have to be a "professional" java programmer and use doubles to calculate averages on byte arrays?
I am not really getting why do we have interface Number if it doesn't abstract number
interface Number does abstract the number for the purposes of storing and converting representations. It does not abstract the number for the purposes of making calculations, because the type of the result representation is not well defined.
The above also makes it clear that you'll probably not be ever able to make your own number implementation (eg. number with unlimited size and precision for some really freaky experimental math programs).
BigDecimal does it without any problem.
Number x = 0 is actually valid.
assigning Integer to Number is OK. Assigning Integer to something that extends Number (say, Double) is not OK. That's why there is a difference.
Is there a way to trick java to compile this or do I have to go full retard professional Java programmer and use doubles to calculate averages on byte arrays?
You need to specify the desired representation of the result when you compute the average. You could abstract it out yourself and supply the "averager" ingerface, but the information about the desired representation needs to get into the method in one way or the other:
interface AverageMaker<T extends Number> {
T initialResult();
T add(T a, Number b);
T divideByCount(T a, int b);
}
public static <T extends Number, R extends Number> R averageValue(Iterable<T> items, AverageMaker<R> maker) {
R res = maker.initialResult();
int count = 0;
for (T val : items) {
res = maker.add(res, val);
count++;
}
return maker.divideByCount(res, count);
}
Define several average makers, like this:
static final AverageMaker<Double> doubleAvg = new AverageMaker<Double>() {
public Double initialResult() { return 0.0; }
public Double add(Double a, Number b) { return a + b.doubleValue(); }
public Double divideByCount(Double a, int b) { return a/b; }
};
static final AverageMaker<Integer> intAvg = new AverageMaker<Integer>() {
public Integer initialResult() { return 0; }
public Integer add(Integer a, Number b) { return a + b.intValue(); }
public Integer divideByCount(Integer a, int b) { return a/b; }
};
Now you can use them in your code together with the averageValue method:
List<Integer> a = new ArrayList<Integer>();
a.add(4);
a.add(8);
a.add(91);
a.add(18);
double avgDouble = averageValue(a, doubleAvg);
int avgInt = averageValue(a, intAvg);
System.out.println(avgDouble); // Prints 30.25
System.out.println(avgInt); // Prints 30
Demo.
You could work with doubles in the class. Since the average of Integers is a Double, this should be correct.
public class AverageValue<T extends Number> {
double data = 0;
int count = 0;
public AverageValue() {
}
public AverageValue(T data) {
this.data = data.doubleValue();
count = 1;
}
public void add(T num) {
data += num.doubleValue();
count++;
}
public double average() {
return data / count;
}
}
This compiles. Usage:
AverageValue<Integer> avgInt = new AverageValue<>();
avgInt.add(1);
avgInt.add(2);
avgInt.add(3);
avgInt.add(4);
System.out.println(avgInt.average());
AverageValue<Double> avgDouble = new AverageValue<>();
avgDouble.add(1.1);
avgDouble.add(1.2);
avgDouble.add(1.3);
avgDouble.add(1.4);
System.out.println(avgDouble.average());
Output:
2.5
1.25
You are mixing up classes (Number) and primitive types (int). Operators like + or \ are not supported for numeric classes (+ is supported for strings, but that's a special case; and unlike e.g. C#, Java does not support custom operator overloading).
A "number with unlimited size and precision for some really freaky experimental math programs" is actually supported with the BigDecimal class, which shows that (and how) you can indeed have your own Number implementation.
ERROR: incompatible types: int cannot be converted to T
T data = (T)(Integer)0;
ERROR: bad operand types for binary operator '+'
ERROR: incompatible types: int cannot be converted to T
in java doesn't exist operator overload Why doesn't Java need Operator Overloading?
This is basically the same question as Implementing a C style bitfield in Java. But is there a way of doing this in a typed fashion without resorting to using a class? As an example, here is some 'C' code:
typedef struct
{
unsigned int x: 8;
unsigned int y: 8;
} point;
point getPoint()
{
point p;
p.x = 1;
p.y = 2;
return p;
}
"point" is nicely typed and the compiler passes it around as an int primitive type, which is very efficient. In java, one might use a class to contain the point and then write:
point getPoint()
{
return new point(1,2);
}
I am trying to improve a heavily recursive java game program that uses a class "point" (among other simple classes) and so the jvm is doing zillions of new operations and taking an enormous amount of time in garbage collection. Changing the class "point" into a packed int may or may not help, but its worth a shot. But I would like to have a nice type "point" to use in the program rather than just declaring "int" everywhere I use the point.
If you ask the same question, you're bound to get the same answer. No.
There is no way to do this is Java, except doing it manually. You could define a long value and shift/mask two ints in there. Or you could have an int and store two shorts in there. But setting/getting the values you will need to do some shifting and masking.
See this question/answer:
Packing two shorts into one int, dealing with negative and positive
In Java it is not usually the size of the object that clobbers you - it is more usually how long you keep hold of it. However - in some cases what you may be looking for is a mutable int.
/**
* Mutable integer.
*/
public class Mint {
private int i = 0;
public Mint () {
}
public Mint (int i) {
this.i = i;
}
/**
* #return the i
*/
public int get() {
return i;
}
/**
* #param i the i to set
*/
public int set(int i) {
this.i = i;
return i;
}
public int add ( int i ) {
this.i += i;
return i;
}
public int sub ( int i ) {
this.i -= i;
return i;
}
public int mul ( int i ) {
this.i *= i;
return i;
}
public int div ( int i ) {
this.i /= i;
return i;
}
public int mod ( int i ) {
this.i %= i;
return i;
}
#Override
public String toString () {
return Integer.toString(i);
}
}
Please be very careful about using mutables - there is a very good reason why making classes immutable is a good idea.
Added
On further reading of your question this may not be as effective for you as it is your Point objects that are clogging your system. Perhaps you should make your Point objects mutable instead.
jvm is doing zillions of new operations and taking an enormous amount of time in garbage collection.
How many distinct points are there? Perhaps it's worth making a cache of points and reusing them so you only create the few points you need and don't garbage collect at all.
Point should be a value object so as long as the x and y coords are the same it shouldn't matter which instance of Point is returned.
I want to compare to variables, both of type T extends Number. Now I want to know which of the two variables is greater than the other or equal. Unfortunately I don't know the exact type yet, I only know that it will be a subtype of java.lang.Number. How can I do that?
EDIT: I tried another workaround using TreeSets, which actually worked with natural ordering (of course it works, all subclasses of Number implement Comparable except for AtomicInteger and AtomicLong). Thus I'll lose duplicate values. When using Lists, Collection.sort() will not accept my list due to bound mismatchs. Very unsatisfactory.
This should work for all classes that extend Number, and are Comparable to themselves. By adding the & Comparable you allow to remove all the type checks and provides runtime type checks and error throwing for free when compared to Sarmun answer.
class NumberComparator<T extends Number & Comparable> implements Comparator<T> {
public int compare( T a, T b ) throws ClassCastException {
return a.compareTo( b );
}
}
A working (but brittle) solution is something like this:
class NumberComparator implements Comparator<Number> {
public int compare(Number a, Number b){
return new BigDecimal(a.toString()).compareTo(new BigDecimal(b.toString()));
}
}
It's still not great, though, since it counts on toString returning a value parsable by BigDecimal (which the standard Java Number classes do, but which the Number contract doesn't demand).
Edit, seven years later: As pointed out in the comments, there are (at least?) three special cases toString can produce that you need to take into regard:
Infinity, which is greater than everything, except itself to which it is equal
-Infinity, which is less than everything, except itself to which it is equal
NaN, which is extremely hairy/impossible to compare since all comparisons with NaN result in false, including checking equality with itself.
After having asked a similar question and studying the answers here, I came up with the following. I think it is more efficient and more robust than the solution given by gustafc:
public int compare(Number x, Number y) {
if (isSpecial(x) || isSpecial(y))
return Double.compare(x.doubleValue(), y.doubleValue());
else
return toBigDecimal(x).compareTo(toBigDecimal(y));
}
private static boolean isSpecial(Number x) {
var specialDouble = x instanceof Double d
&& (Double.isNaN(d) || Double.isInfinite(d));
var specialFloat = x instanceof Float f
&& (Float.isNaN(f) || Float.isInfinite(f));
return specialDouble || specialFloat;
}
private static BigDecimal toBigDecimal(Number number) {
if (number instanceof BigDecimal d)
return d;
if (number instanceof BigInteger i)
return new BigDecimal(i);
if (number instanceof Byte || number instanceof Short
|| number instanceof Integer || number instanceof Long)
return new BigDecimal(number.longValue());
if (number instanceof Float || number instanceof Double)
return new BigDecimal(number.doubleValue());
try {
return new BigDecimal(number.toString());
} catch(NumberFormatException e) {
throw new RuntimeException("The given number (\"" + number + "\" of class " + number.getClass().getName() + ") does not have a parsable string representation", e);
}
}
One solution that might work for you is to work not with T extends Number but with T extends Number & Comparable. This type means: "T can only be set to types that implements both the interfaces."
That allows you to write code that works with all comparable numbers. Statically typed and elegant.
This is the same solution that BennyBoy proposes, but it works with all kinds of methods, not only with comparator classes.
public static <T extends Number & Comparable<T>> void compfunc(T n1, T n2) {
if (n1.compareTo(n2) > 0) System.out.println("n1 is bigger");
}
public void test() {
compfunc(2, 1); // Works with Integer.
compfunc(2.0, 1.0); // And all other types that are subtypes of both Number and Comparable.
compfunc(2, 1.0); // Compilation error! Different types.
compfunc(new AtomicInteger(1), new AtomicInteger(2)); // Compilation error! Not subtype of Comparable
}
The most "generic" Java primitive number is double, so using simply
a.doubleValue() > b.doubleValue()
should be enough in most cases, but... there are subtle issues here when converting numbers to double. For example the following is possible with BigInteger:
BigInteger a = new BigInteger("9999999999999992");
BigInteger b = new BigInteger("9999999999999991");
System.out.println(a.doubleValue() > b.doubleValue());
System.out.println(a.doubleValue() == b.doubleValue());
results in:
false
true
Although I expect this to be very extreme case this is possible. And no - there is no generic 100% accurate way. Number interface have no method like exactValue() converting to some type able to represent number in perfect way without loosing any information.
Actually having such perfect numbers is impossible in general - for example representing number Pi is impossible using any arithmetic using finite space.
What about this one? Definitely not nice, but it deals with all necessary cases mentioned.
public class SimpleNumberComparator implements Comparator<Number>
{
#Override
public int compare(Number o1, Number o2)
{
if(o1 instanceof Short && o2 instanceof Short)
{
return ((Short) o1).compareTo((Short) o2);
}
else if(o1 instanceof Long && o2 instanceof Long)
{
return ((Long) o1).compareTo((Long) o2);
}
else if(o1 instanceof Integer && o2 instanceof Integer)
{
return ((Integer) o1).compareTo((Integer) o2);
}
else if(o1 instanceof Float && o2 instanceof Float)
{
return ((Float) o1).compareTo((Float) o2);
}
else if(o1 instanceof Double && o2 instanceof Double)
{
return ((Double) o1).compareTo((Double) o2);
}
else if(o1 instanceof Byte && o2 instanceof Byte)
{
return ((Byte) o1).compareTo((Byte) o2);
}
else if(o1 instanceof BigInteger && o2 instanceof BigInteger)
{
return ((BigInteger) o1).compareTo((BigInteger) o2);
}
else if(o1 instanceof BigDecimal && o2 instanceof BigDecimal)
{
return ((BigDecimal) o1).compareTo((BigDecimal) o2);
}
else
{
throw new RuntimeException("Ooopps!");
}
}
}
This should work for all classes that extend Number, and are Comparable to themselves.
class NumberComparator<T extends Number> implements Comparator<T> {
public int compare(T a, T b){
if (a instanceof Comparable)
if (a.getClass().equals(b.getClass()))
return ((Comparable<T>)a).compareTo(b);
throw new UnsupportedOperationException();
}
}
if(yourNumber instanceof Double) {
boolean greaterThanOtherNumber = yourNumber.doubleValue() > otherNumber.doubleValue();
// [...]
}
Note: The instanceof check isn't necessarily needed - depends on how exactly you want to compare them. You could of course simply always use .doubleValue(), as every Number should provide the methods listed here.
Edit: As stated in the comments, you will (always) have to check for BigDecimal and friends. But they provide a .compareTo() method:
if(yourNumber instanceof BigDecimal && otherNumber instanceof BigDecimal) {
boolean greaterThanOtherNumber = ((BigDecimal)yourNumber).compareTo((BigDecimal)otherNumber) > 0;
}
You can simply use Number's doubleValue() method to compare them; however you may find the results are not accurate enough for your needs.
Let's assume that you have some method like:
public <T extends Number> T max (T a, T b) {
...
//return maximum of a and b
}
If you know that there are only integers, longs and doubles can be passed as parameters then you can change method signature to:
public <T extends Number> T max(double a, double b) {
return (T)Math.max (a, b);
}
This will work for byte, short, integer, long and double.
If you presume that BigInteger's or BigDecimal's or mix of floats and doubles can be passed then you cannot create one common method to compare all these types of parameters.
If your Number instances are never Atomic (ie AtomicInteger) then you can do something like:
private Integer compare(Number n1, Number n2) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Class<? extends Number> n1Class = n1.getClass();
if (n1Class.isInstance(n2)) {
Method compareTo = n1Class.getMethod("compareTo", n1Class);
return (Integer) compareTo.invoke(n1, n2);
}
return -23;
}
This is since all non-Atomic Numbers implement Comparable
EDIT:
This is costly due to reflection: I know
EDIT 2:
This of course does not take of a case in which you want to compare decimals to ints or some such...
EDIT 3:
This assumes that there are no custom-defined descendants of Number that do not implement Comparable (thanks #DJClayworth)
In my use case, I was looking for a general Comparator that works with the autoboxed primitives (64 bit max precision), not arbitrary precision types like BigInteger and BigDecimal. Here's a first shot at it..
public class PrimitiveComparator implements Comparator<Number> {
#Override
public int compare(Number a, Number b) {
if (a == b)
return 0;
double aD = a.doubleValue();
double bD = b.doubleValue();
int comp = Double.compare(aD, bD);
if (comp == 0 && inLongBounds(aD))
comp = Long.compare(a.longValue(), b.longValue());
return comp;
}
private boolean inLongBounds(double value) {
return
Double.compare(value, Long.MAX_VALUE) <= 0 &&
Double.compare(value, Long.MIN_VALUE) >= 0;
}
}
The objective is to be able to compare mixed types (e.g. Floats against Longs). This should also work with those AtomicXxx types (or any hand rolled Number subclass that uses no more than 64 bits).
In this ordering, btw, Double.NaN > Double.POSITVE_INFINITY > { everything else }.
In C++, if you need to have 2 objects modified, you can pass by reference. How do you accomplish this in java? Assume the 2 objects are primitive types such as int.
You can't. Java doesn't support passing references to variables. Everything is passed by value.
Of course, when a reference to an object is passed by value, it'll point to the same object, but this is not calling by reference.
Wrap them in an object and then pass that object as a parameter to the method.
For example, the following C++ code:
bool divmod(double a, double b, double & dividend, double & remainder) {
if(b == 0) return false;
dividend = a / b;
remainder = a % b;
return true;
}
can be rewritten in Java as:
class DivRem {
double dividend;
double remainder;
}
boolean divmod(double a, double b, DivRem c) {
if(b == 0) return false;
c.dividend = a / b;
c.remainder = a % b;
return true;
}
Although more idiomatic style in Java would be to create and return this object from the method instead of accepting it as a parameter:
class DivRem {
double dividend;
double remainder;
}
DivRem divmod(double a, double b) {
if(b == 0) throw new ArithmeticException("Divide by zero");
DivRem c = new DivRem();
c.dividend = a / b;
c.remainder = a % b;
return c;
}
Java does not have pass by reference, but you can still mutate objects from those references (which themselves are passed by value).
java.util.Arrays.fill(int[] arr, int val) -- fills an int array with a given int value
java.util.Collections.swap(List<?> list, int i, int j) -- swaps two elements of a list
StringBuilder.ensureCapacity(int min) -- self-explanatory
As you can see, you can still modify objects (if they're not immutable); you just can't modify references or primitives by passing them to a function.
Of course, you can make them fields of an object and pass those objects around and set them to whatever you wish. But that is still not pass by reference.
Using generics you can create a pointer class which would make this at least somewhat less painful. You pass in the object, change it's value property and when the function exits your object will contain the new value.
MyPointerClass<int> PointerClass = new MyPointerClass<int>(5);
myFunction(PointerClass);
System.out.println(PointerClass.Value.toString());
// ...
void myFunction(myPointerClass<int> SomeValue)
{
SomeValue.Value = 10;
}
I am trying to convert these small math calls to Java from C# and just wanted to make sure that they operate the same way. I added one additional call as it is not supported in Java.
Here is code in C#
public override int CompareTo(object a)
{
EquationGenome Gene1 = this;
EquationGenome Gene2 = (EquationGenome)a;
return Math.Sign(Gene2.CurrentFitness - Gene1.CurrentFitness);
}
Java:
Notice the Math.Sign is not being called.
/**
* Compare to.
*/
public int compareTo(final Object a) {
final EquationGenome gene1 = this;
final EquationGenome gene2 = (EquationGenome) a;
return (int) ((-1.0) * (gene2.currentFitness - gene1.currentFitness));
}
And here is one to replicate C#'s 'next' with two int parameters in Java:
public static final int nextInt(final Random r, final int min, final int max) {
final int diff = max - min;
final int n = r.nextInt(diff);
return n + min;
}
Are these methods equivalent from C# to Java?
Why not just use Java's compareTo? This is assuming currentFitness is of type Integer and not the primitive type int. Otherwise you can just wrap it in Integer. This is not the most efficient method but it's more clear to me.
/**
* Compare to.
*/
public int compareTo(final Object a) {
final EquationGenome gene1 = this;
final EquationGenome gene2 = (EquationGenome) a;
return gene1.currentFitness.compareTo(gene2.currentFitness);
}
No, because Math.Sign in C# returns one of three values: -1 if the value is < 0, 0 if the value is equal to 0, and 1 if the value is greater than 0. It doesn't flip the sign by multiplying by -1 as you're doing in the Java code.
In C# the CompareTo function expects -1 to mean that the object on which it is called is less than the object being passed in. Since you're returning the sign of subtracting value 1 from value 2, this will be switched. I doubt this is what you want for your algorithm, given your Java code. Traditionally you would subtract value 2 from value 1 and use that sign.
If your Java version of EquationGenome implements the Comparable interface, you'll be able to take advantage of many Java APIs. This would alter your class to look like this:
final class EquationGenome
implements Comparable<EquationGenome>
{
...
public int compareTo(final EquationGenome gene2) ...
Then, what you are doing with the multiplication isn't clear. I assume the "natural order" is from most fit to least fit. Then I'd implement the comparison like this:
public int compareTo(final EquationGenome that) {
if (currentFitness == that.currentFitness) {
/* TODO: Add more tests if there are other properties that distinguish
* one EquationGenome from another (secondary sort keys). */
return 0;
} else
return (currentFitness > that.currentFitness) ? -1 : +1;
}
By convention, you should either implement the equals method to be "consistent" with your compareTo method, or clearly document your class to note the inconsistency. If you implement equals, you should also implement hashCode for consistency too.
public boolean equals(Object o) {
return o instanceof EquationGenome && compareTo((EquationGenome) o) == 0;
}
public int hashCode() {
return currentFitness;
}
The method for producing random numbers is alright, as long as you understand that max is excluded; the method generates random numbers from the half-open interval (min, max]. If you want to include max in the range, add one to diff.
I would write something like.
Note: You have be very careful using Comparator with mutable fields as this can have undesirable side effects.
public class EquationGenome implenents Comparable<EquationGenome> {
private final double currentFitness;
public EquationGenome(double currentFitness) {
this.currentFitness = currentFitness;
}
public int compareTo(EquationGenome eg) {
return Double.compareTo(currentFitness, eg.currentFitness);
}
}