Java Casting in Method Overloading - java

I have the methods overloading such as:
public int sum1(int a, int b)
{
int c= a+b;
System.out.println("The method1");
return c;
}
public float sum1(int a, float b)
{
float c= a+b;
System.out.println("The method2");
return c;
}
public double sum1(float a, float b)
{
double c= (double) a+b;
System.out.println("The method3");
return c;
}
From the main method, suppose we have
double x=10.10f;
double y=10.20f;
the apparent type for x and y is double, but the actual type is float. when I call
System.out.println(" the output is :"+cc.sum1(x,y));
the error in the compile-time.
The method sum1(int, int) in the type Class is not applicable for the arguments double, double).
where it should go to sum1 (i.e. method3) by casting double to float

TL;DR version of this answer:
Variables of primitive types never have a different type at execution-time to their compile-time. (A double is always a double, never a float, etc.)
Overload resolution (picking which method signature is used) is performed using the compile-time types of expressions
Method implementation of the picked signature is performed using the execution-time type of the target of the method call
the apparent type for x and y is double, but the actual type is float
No, it's not. You've just got a conversion from the assigned float literals to double values. The actual values are double.
Primitives don't work like objects - there's no idea of an int value still being an int inside a double variable, for example.
It's simpler to take an example with integer types. Suppose we have:
byte b = 100;
int x = b;
The value of x is the 32-bit integer representing the value 100. It doesn't "know" that it was originally assigned from a byte value... there just happened to be a conversion from byte to int at the point of assignment.
Compare that with reference types:
String x = "hello";
Object y = x;
Here, the value of y really is a reference to a String object. That type information is preserved precisely because there's a whole object that can contain it, and because the value of the variable itself is only a reference. (The bits themselves don't need to change as part of the assignment - in a simple VM at least, they'll be the exact same bits in x and y, because they're referring to the same object.)
Even in that case, however, overload resolution occurs based on the compile-time type of the arguments, not their actual values at execution time. The only way that the execution-time type of a variable gets involved is with overriding based on the target of a method call. So if we have:
Foo f = new X();
Foo g = new Y();
Foo h = new Z();
f.someMethod(g, h);
... then the compiler will look for a method in Foo which has two Foo parameters (or Object or other superclasses/interfaces) - the actual types of the objects involved are irrelevant. At execution time, however, if that method has been overridden in X, then that override will be called due to the execution-time type of the object f's value refers to.

Casting double to float may cause loss of data, since it's a narrowing conversion, and is therefore not done automatically by the compiler. You'll have to cast the variables to float explicitly if you want it to take place.

No, the actual type of the variables is double. The type of the constants that you're assigning to that double variable, which get promoted on assignment, is float.

Try to add new function: public double sum1(double a, double b). It will solve your problem.
And also, this kind of casting will cause loss of data.

Floats are funny that way.. they always try to convert to doubles automatically. This code compiles, with floats at every turn.
public class wood {
public static void main(String[] args) {
float x = 10.1f;
float y = 10.2f;
System.out.println("Sum of x and y = " + sum1((float)x, (float)y));
}
public static float sum1(float x, float y) {
return (float)((float)x+(float)y);
}
}
edit; note that using a cast operator outside of parenthesis will cast after what is inside of the parenthesis has computed. So;
System.out.println((int)(50.5 + 50.7));
will print out 101.
Within java, some data conversions are automatic, and others require cast operators.. simply put, java will automatically make widening conversions, while you will have to use a cast operator for narrowing conversions.
The hierarchy of primitive data types is as follows:
byte //1 byte (-128 through 127)
short //2 bytes (over 32,000 give/take from 0)
int //4 bytes (over 2billion give/take from 0)
long //8 bytes (over 9 quintillion (10^18) give/take from 0)
float //4 bytes (holds 7 decimal places)
double //8 bytes (holds 15 decimal places)
java will not make narrowing conversions automatically, because then data is at risk of being lost. Both byte and short will become ints automatically.
short s = 5;
byte b = 5;
short sum = s + b; //this will cause an error!
s and b automatically make a widening conversion to an int, and an int cannot be assigned to a short without a cast operator.
short sum = (short)(s + b);
would be needed.

Related

integer division java returns a double? What is going on?

See screenshot:
What is going on there? i see that we're casting 23F to an int so in choice "II", we wind up doing 23/7 which should give us 3... at least so I thought. But why do we have 3.0? Why do we get a double?
Here is the context:
float x = myFunc(23F);
int myFunc(float x) { ... }
The right hand side of the expression is an int and you have correctly deduced that its value is 3.
When you assign an int value to a float variable, the integer will be converted to a float.
This is an example of a primitive widening conversion. It can happen in various contexts when you are going from a "smaller" primitive numeric type to a "larger" primitive numeric type. The int type is "smaller" than the float type. In general:
byte < short and char < int < long < float < double.
Why do we get a double?
See above. But it is a float not a double.
When you output a number in Java using println, a float and a double will look the same. The println method won't output a float with an F suffix. The F and D suffixes are only used in Java source code.
Because the function that return the result is assigned to z, and the type of z is float.

Why does this method return an output?

class Demo {
public void myMethod(int a, double b, char c) {
System.out.println("Version 1.");
}
public void myMethod(int a, double b, double c) {
System.out.println("Version 2.");
}
public void myMethod(int a, boolean b, double c) {
System.out.println("Version 3.");
}
public void myMethod(int a, boolean b, boolean c) {
System.out.println("Version 4.");
}
public static void main(String[] args) {
Demo obj = new Demo();
obj.myMethod(1, 100, 'b');
}
}
1 and 100 are both of type int and b is a type char so shouldn't the result be a compile error? i do not understand why it returns "version 1".
could someone please explain to me why?
thank you
The value 100 can be used as a double, it’s the widening primitive conversions:
byte to short, int, long, float, or double
short to int, long, float, or double
char to int, long, float, or double
int to long, float, or double
long to float or double
float to double
At runtime, your compiler converts the int 100 to type double because you left it no other choices (i.e. another overloaded method that accepts exactly int , int and char).
In other words, instead of throwing a RuntimeException, your compiler converts the int that takes less size to the type that takes more size which is in your case a double. That is automatically performed without loosing information.
That is called Widening Primitive Conversion or auto conversion or implicit conversion.
The scenario you described occurs for type conversions in java. The official java doc has already provided the 13 categories of conversions that are possible in java. Your one also falls on one of them, the widening primitive one.
You can easily understand the logic if you can understand this simple code:
int a = 12.80;
System.out.print(a);
12.80 is not an integer data type and if 12.80 is to be converted to an integer then the compiler has to cut out .80 from there which will lead you to possible lossy conversion compilation error.
Again, we may want to run another code:
double b = 12;
System.out.print(b);
If you think that the above code may give you a compilation error, then you are completely wrong. Because, the output here is 12.0. As no data loss occurs here, int can be easily converted to double.
So, you should now understand that not all the data types can be converted to another one. You may refer to the official java doc link provided above to know about all types of conversions.
Now, in your case, 100 is considered to compiler as 100.0 or something like that as there is no other overloaded method with integer data type.
Hope you understand now.

Java Ceil Weirdness

Why does this output 0 instead of 1?
System.out.println((int) (Math.ceil(1/2)));
While this one correct outputs 1
System.out.println((int) (Math.ceil((double) 1/ (double) 2)));
Shouldn't Math.ceil(double) automatically type cast the 1/2 to double?
Math.ceil does, indeed, cast the integer to a double. But it only does so after the integer operation has been performed. This is the order of operations:
int a = 1;
int b = 2;
int c = a / b; // now equals 0, because it's an integer operation.
double d = (double)c; // now it's a double - but equals 0.0.
double e = Math.ceil(d); // still 0.0.
You're thinking of 1/2 as a fraction, but it's not - it's an expression of two ints and an operator that has to be resolved before its value can be used in further expressions.
Explicit casting always require (datatype) to be mentioned. Here 1 and 2 represents itself as int and to cast from int to double explicit casting will be introduced. Whenever casting is preformed from lower to higher datatypes explicit casting should be imposed. See example below;
public class MainClass{
public static void main(String[] argv){
int a = 100;
long b = a; // Implicit cast, an int value always fits in a long
}
}
An explicit casts looks like this:
public class MainClass{
public static void main(String[] argv){
float a = 100.001f;
int b = (int)a; // Explicit cast, the float could lose info
}
}
Code Snippet: Source
The first thing which happens when that line is executed, is that the division 1/2 is resolved. This happens without any consideration for the method-call to Math.ceil it is embedded in.
The literals 1 and 2 are integers. When you perform a division with only integers as arguments, an integer division is performed, which always rounds down. So the term gets resolved to the int value 0. Math.ceil() only accepts type double, but that's not a problem because Java can perform the conversion automatically and turn the int 0 to a double 0.0.
To perform an explicit floating point division, have one or both of the parameters to the division be floating point literals:
System.out.println((int) (Math.ceil(1.0/2.0)));

regarding long and float

i was developing the below code
static String m(float i) {
return "float";
}
static String m(double i) {
return "double";
}
public static void main(String[] args) {
int a1 = 1;
long b1 = 2;
System.out.print(m(a1) + "," + m(b1));
}
Both results in output float, float , what the reason behind that please advise and how can I call double please advise thanks a lot.
Short answer: Java can automatically widen ints and longs to both floats and doubles, but Java will choose to widen to a float because it is smaller (in terms of memory footprint) than a double. You can call the double version of the method by explicitly casting the argument to a double:
System.out.print(m((double)a1) + "," + m((double)b1));
Long answer: Each primitive data type in Java has a size (measured in bytes), which determines how much information (or rather, what range of values) a given primitive can hold. The table below shows the sizes of some of Java's primitive data types:
byte 1 byte
short 2 bytes
char 2 bytes
int 4 bytes
float 4 bytes
long 8 bytes
double 8 bytes
Java will automatically "widen" values for you in certain situations, following some well-defined rules from the Java Language Specification. The following widening primitive conversions are performed by Java automatically:
byte to short, int, long, float, or double
short to int, long, float, or double
char to int, long, float, or double
int to long, float, or double
long to float or double
float to double
The other rules that are applicable to this situation are:
Widening does not lose information about the overall magnitude of the numeric value.
Widening from an integral type to another integral type does not lose any information at all; the numeric value is preserved exactly.
Widening an int or long value to a float, or of a long value to a double may result in a loss of precision.
For example, Java can safely widen an int to a long without changing the numeric value at all, because both are integral types and a long is larger than an int (see rule 2). Java can also widen an int to a float, but there might be a loss of precision. The sample code below demonstrates this loss of precision.
public static void foo(float f) {
System.out.println(f);
}
public static void main(String[] args) {
int a = 123;
int b = 1234567890;
foo(a);
foo(b);
}
The first call to foo(float) prints "123.0" as expected. The int value "123" is widened to the float value "123.0". The second call prints "1.23456794E9", which makes sense when you take rule 3 into account. The value "1234567940" is the same magnitude as but less precise than "1234567890".
The other piece of information that is key here: when multiple overloaded methods are present, Java determines which method to call by choosing the method with the smallest parameter type (in terms of memory footprint) such that the given argument is capable of being widen to the parameter type. In other words, the number you pass to the method must be capable of being widened to the parameter type of the method, and if multiple overloaded methods satisfy that requirement, Java will choose the method whose parameter type is of the smallest size.
In your case, you are passing an int and a long to one of two overloaded methods. Java will look at methods m(float) and m(double) to determine which method to call. An int can be widened to a float and a double, but a float (4 bytes) is smaller than a double (8 bytes), so Java will choose to call m(float). The same is true when you call the method with a long argument: float is chosen because it's the smallest data type that a long can be widened to.
If you want to call the double version, make it explicitly a double: m((double)a1)
Take a look at the JLS §8.4.9 - Method Overloading
Try
System.out.print(m(1f)+","+ m(2d));
why are you creating an int and long to test it? Well, what is actually happening is that both parameters are converted to float by default.
how can I call double?
Use a double variable
double d = 3.3;
m(d);

Method overloading in Java

import java.lang.Math;
class Squr
{
public static void main ()
{
Squr square = new Squr();
System.out.println ("square root of 10 : " + square.mysqrt(10));
System.out.println (" Square root of 10.4 : "+ square.mysqrt(10.4));
}
int mysqrt ( int x)
{
return Math.sqrt(x);
}
double mysqrt (double y)
{
return Math.sqrt(y);
}
}
When we compile it then it's giving error
possible loss of precision
found :double
required :int
I have written this program for calculating square root of int or double type values by method overloading concept.
How can I fix my error so I can find the square root of an int and a double?
I don't think this is anything to do with method overloading - it's actually quite simple.
Math.sqrt() returns a double, but in your first class method, you're trying to return this directly from a method that returns int. This would be a lossy conversion, and you'd need to perform it manually.
In particular - when you call mysqrt(5), which integer do you expect the answer to be? 2? 3? Some "warning, not a whole number" value like -1? I suspect that perhaps you meant to return double for both methods, and differ only in the type of the arguments.
My eclipse gives:
Type mismatch: cannot convert from double to int
Whatever the message is, you fix this by: return (int) Math.sqrt(x);
This has nothing to do with overloading though.
By the way, a square root of an integer can be double, so by having a return type int you are truncating possibly important information.
Hence I'd advise for simply using Math.sqrt(..) without making any additional methods. If you need the whole part, you can use Math.floor(..) or Math.round(..)
http://download.oracle.com/javase/6/docs/api/java/lang/Math.html#sqrt%28double%29
returns double. Casting in int will loose precision. Don't you think so?
JLS has something to say on conversions. See this http://java.sun.com/docs/books/jls/third_edition/html/conversions.html
The following 22 specific conversions on primitive types are called the narrowing primitive conversions:
* short to byte or char
* char to byte or short
* int to byte, short, or char
* long to byte, short, char, or int
* float to byte, short, char, int, or long
* double to byte, short, char, int, long, or float
Narrowing conversions may lose information about the overall magnitude of a numeric value and may also lose precision.

Categories

Resources