I've defined a Point class like this.
class Point<E,F> {E x; E y; ...}
so that i can give float, Integer ... [anyway its a number]
But when i want to manipulate its an error.
void getdistance(Point<Number, Number> pt) {
this.x-pt.x.floatValue(); //not a statement
this.y-pt.y.floatValue();
}
also i should not give string as type, so should i change it to Number?
or any other way to calculate distance from generic type?
But if i change the type to Number how can i specify different co-ordinate type [float or integer]?
how to infer type here?
this.y-pt.y.TypeValue?
how can we do if its integer or double?
when i pass
pt.getdistance(otherpt);
compiler shows error: create a method getdistance(Float,Integer). how to pass other point to that method?
Try and define your point like this: Point<E extends Number, F extends Number>.
That way the compiler can tell that E and F both are numbers.
However, you might even want to simplify that to Point<N extends Number> since most likely both coordinates should be of the same type (i.e. Double, Integer etc.) - mixing types seems quite odd to me.
The method would then have to be adjusted:
<X extends Number, Y extends Number> float getdistance(Point<X, Y> pt) {
float dx = this.x.floatValue() - pt.x.floatValue();
float dy = this.y.floatValue() - pt.y.floatValue();
return (whatever your distance calculation needs to look like);
}
Note that x and y might be null, thus you'd have to check for that.
Specifying X and Y here would allow you to pass a Point<Float, Integer> to a Point<Double, Long>'s member method. You could redefine E and F here, but that might be a source of confusion.
Edit:
I'll elaborate a bit on Mark Peters' comment:
Using floatValue() or even doubleValue() might result in a loss of precision, since even double would not be able to accurately represent each long value. Thus you might experience severe precision losses, especially with higher numbers.
Additionally, BigInteger and BigDecimal are numbers too and those have even higher precision.
In order to get maximum precision, you'd have to use BigDecimal in the calculation and when creating the initial values you'd have to check the types of the values and call the appropriate method:
for Byte, Short, Integer and Long you'd call BigDecimal.valueof( x.longValue() )
for Float and Double you'd call BigDecimal.valueof( x.doubleValue() )
BigDecimal could be used as is
BigInteger would be passed to the BigDecimal constructor
This would add quite a bit of complexity and in that case you might want to go with arshajii's suggestion of subclassing Point instead.
You can tell the types that they should extend Number with:
<T extends Number, T1 extends Number>
This way you'll be able to pass it Float etc
Related
I want to know why the result of this code:
Number x = 3;
System.out.println(x.intValue());
System.out.println(x.doubleValue());
generates
3
3.0
as Number is an abstract class in Java.
So when I need to use it - I could use it with some it's subclasses like Integer, Double ...etc. Now I want to know how exactly this part of code works:
Number x = 3;
when you do:
Number x = 3;
System.out.println(x.intValue());
System.out.println(x.doubleValue());
Following will happen:
Number x = 3;
this will declare x as int, and will be auto boxed to an object of the class Integer turning this: Number x = 3; into Number x = new Integer(3);
then here:
System.out.println(x.intValue());
intValue is implemented as:
public int intValue() {
return value;
}
System.out.println(x.doubleValue());
and doubleValue is implemented as:
public double doubleValue() {
return (double)value;
}
Auto Boxing.
So when you do
Number x = 3;
That gets compiled to
Number x = new Integer(3);
Number in java how it work without a subclass?
That is a wrong assumption. Number class have subclasses. If you look at the definition of Integer class.
Look at the definition of Integer class
public final class Integer
extends Number
It is a sublcass of Number so it gets compiled fine.
The key thing to understand here: the fact that you use Number on the left hand side of that assignment doesn't mean that the object referenced by x is in fact a direct instance of the Number class.
As others have outlined, auto-boxing kicks in here. One way to get to the true nature of things: by looking at the byte code:
0: iconst_3
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
...
1: is about calling Integer.valueOf(int) - the method that turns the int value 3 into an Integer object!
The other easy way to get to the point - by doing:
System.out.println(x.getClass());
and that of course prints Integer; not Number!
Autoboxing helping to compile the code.
Converting a primitive value (an int, for example) into an object of the corresponding wrapper class (Integer) is called autoboxing
So compiler convert this code Number x = 3; to the following at runtime :
Number x = Integer.valueOf(3);
Following is an example of boxing and unboxing:
public class Test {
public static void main(String args[]) {
Integer x = 5; // boxes int to an Integer object
x = x + 10; // unboxes the Integer to a int
System.out.println(x);
}
}
This will produce the following result:
15
When x is assigned an integer value, the compiler boxes the integer because x is integer object. Later, x is unboxed so that they can be added as an integer.
Java has a feature called AutoBoxing, what it does is automatically wrapping primitives with it's corresponding object wrapper class.
Number x=3;
System.out.println(x.getClass());
Just try this and you will see what actually has happened.
Also try
Number x=3.0;
System.out.println(x.getClass());
In first case java wraps 3 with an Integer.class and in the second time it wraps 3.0 with a Double.class.
In your case, since it is getting wrapped as an Integer, when you call doubleValue() method, it actually calls doubleValue() in Integer.class which has the following implementation.
public double doubleValue() {
return (double)value;
}
Please find the below hierarchy of Number DataType
Direct Known Subclasses:
AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short
java is not able to call any overload method as shown below :-
class LspTest{
public void add(int a, float b){
System.out.println("First add");
}
public void add(float a, int b){
System.out.println("second add");
}
public static void main(String [] a){
LspTest test = new LspTest();
test.add(1,1);
}
}
Please explain i am confused in this.
In your methods you are having parameters (int, float) and (float, int) but when calling the method you are passing both the int (1,1) values. The Java complier can auto type cast float to int whenever needed. But in this case compiler cannot decide auto type cast which int to float. Therefore it shows ambiguity.
You need to call it test.add(1f, 1); or test.add(1,1f); i.e. specify which value is int and which value is float.
P.S. To specify a value to be float you can write f with it.
When you initialise with literal values, in this case, compiler won't be able to infer the exact type. Therefore, it does not know which overload to call and returns the error that the reference to add is ambiguous. You can fix this by casting the arguments to the appropriate type, or even better, creating typed local variables initialised with 1 and passing the variables as parameters, like so:
int a = 1;
float b = 1;
LspTest test = new LspTest();
test.add(a,b);
There is an ambiguity here, and the Java compiler cannot figure out which method to call. Use test.add((float) 1, 1) or test.add(1, (float) 1) to explicitly tell which method you want.
This is the clear case of ambiguity which leads to a Compile Error.
Java compiler supports the type promotion. First of all, it'll checks for more specific data type if not match then it'll promote to next data type.
Java compiler will supports the type promotion in following order.
byte --> short --> int --> long --> float --> double
As your parameters (int,int) can be auto-promoted to float, java compiler can't decide in which one to invoke as both of your methods accepts the (1,1)
I encountered with a strange issue. I don't understand why this code doesn't work:
public static <Type1 extends Integer, Type2 extends Double >
Object addition(Type1 first, Type2 second)
{
return second * first;
}
The compiler claims Operator * cannot be applied to Type2,Type1. But that types extends Integer and Double which has + operator defined for them. So i really don't understand this
You are wrong. Neither Integer nor Double or any other objects extending Number class have "+" or any other operator definied.
The only reason why you are able to perform something like (Integer + Double) is autoboxing. And autoboxing is a kind of "hardcoded" feature which applies to a very small predefined set of classes, such as Integer, Double, etc.
Furthermore, Integer and all other Number subclasses are declared "final", therefore "Type extends Integer" has no meaning, since you cannot extend anything from Integer.
The simplest solution is to use double which can store every possible int values.
public static double addition(double first, double second)
{
return second + first;
}
I assume you wanted + for addition, not * for multiplication
you can run
double d1 = addition(1, 5.5);
double d2 = addition(10.1, 5);
double d3 = addition(1, 2);
double d4 = addition(10.1, 12.3455);
There is no point extending a final class. Your types are basically the types you gave.
Say we got 2 ordered collections of numbers. We want to compute the arithmetic difference element by element.
I think we need to use List of Number in order to model the idea of 'ordered collection of numbers'.
The problem is that the arithmetic difference (a banal '-' like in 3-2) is not defined for Number.
I can cast everything to Double, but I'd rather prefer a clean solution.
public static <E extends Number> List<E> listDifferenceElementByElement(List<E> minuend, List<E> subtrahend) throws Exception {
if (minuend.size() != subtrahend.size()) {
throw new Exception("Collections must have the same size"); //TODO: better exception handling
}
List<E> difference = new ArrayList<E>();
int i = 0;
for (E currMinuend : minuend) {
difference.add(currMinuend-subtrahend.get(i)); //error: The operator - is undefined for the argument type(s) E, E
i++;
}
return difference;
}
Any idea?
Since Number does not provide any subtract method, you can't do it simply. The alternatives I can think of are:
use the provided doubleValue() method, and return a double, but you could lose precision if the lists contain BigDecimal for example.
have one method per available Number subclass, but it could create a lot of duplicated code...
restrict the type to whatever makes sense (say double if precision does not matter too much or BigDecimal if it does), which is a subcase of (2).
Option 2 could be implemented like by replacing difference.add(currMinuend-subtrahend.get(i)); by difference.add(subtract(currMinuend, subtrahend.get(i)));
Then it's only a matter of writing 10 subtract methods:
private static int subtract(int a, int b) { return a - b; }
private static double subtract(double a, double b) { return a - b; }
private static BigDecimal subtract(BigDecimal a, BigDecimal b) { return a.subtract(b); }
etc.
This is nothing to do with generics, arrays, etc. Java doesn't allow operator overloading, so you cannot subtract 2 numbers with -, and the Number class doesn't define any methods for numeric operations. It can't because it might be operating on different subclasses (e.g. Integer.subtract(Double)) which would make defining the return type impossible.
You will need to use intrinsic types or BigDecimal (or similar) here, I think.
If you want to work with many arithmetic type, you can set your list as a generic list, then add the handler when you want to find the difference between them. The handler check if the type is instance of Double, Integer, or anything you want. Based on each type, you could compute the difference.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java : different double and Double in comparison
In a sample java program for one of my labs, I have two different methods taking Double and double parameters respectively.
How do I differentiate between them when passing arguments to them?
Double parameter can be null when double can't.
First off you need to understand the difference between the two types.
double is a primitive type whereas Double is an Object.
The code below shows an overloaded method, which I assume is similar to your lab code.
void doStuff(Double d){ System.out.println("Object call"); }
void doStuff(double d){ System.out.println("Primitive call"); }
There are several ways you can call these methods:
doStuff(100);
doStuff(200d);
doStuff(new Double(100));
These calls will result in:
"Primitive call"
"Primitive call"
"Object call"
- double is a primitive type, where as Double is a wrapper object.
- One of the most common use of Wrapper objects is with Collection .
Eg:
List<Double> d = new ArrayList<Double>();
- In Java 5 a mechanism called Autoboxing has been introduced to convert between the two directly.
Eg:
double d = 10.41;
Double wrapper = d;
Double is reference type and double is value type.
The Double class wraps a value of the primitive type double in an object. An object of type Double contains a single field whose type is double." link
As #Fess mentioned and because Double is reference type it can be null.
If you want you can explictly convert from Double to double with .doubleValue() method and viceverrsa with new Double(1.0).
Also as #millimoose said:
You should use X.valueOf() instead of new X(). The valueOf methods are allowed to cache the boxing types to reduce memory use. (Not sure this is done for Doubles but it's a good habit to get into.)"
// Method A
public static void foo(Double d) {...}
// Method B
public static void foo(double d) {...}
Evidently, if you pass a Double object then Method A will be called; i.e. if you had something like:
Double d = new Double(1.0);
Further, if you pass a double literal you will call Method B. What's interesting is if you have something like
double d = new Double(1.0);
In this case Method B will also be called, because the type of d is double; the Double object gets unboxed to a double. On the same note, if you had:
Double d = 1.0;
then Method A would be called, because the type of d would be Double (the double-literal gets autoboxed to a Double).
Double is a wrapper class while double is a primitive type like c/c++. As pointed out above, Double is mostly used in generics but also is useful anywhere there is a need for both numerical value and proper object encapsulation. In most cases the Double and double can be used interchangeably.
What you have is an example of method overloading. The good part is that the compiler and the JVM will select the correct method automatically based on the type of the arguments that is used when you call the method.