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.
Related
This question already has an answer here:
Casting rules for primitive types in java
(1 answer)
Closed 5 years ago.
I don't understand why code snippet 1 works fine, but code snippet 2 gives compile time error incompatible types: java.lang.Long cannot be converted to int
Is related to priority of casting in java? I went through this thread on stackoverflow, but it didn't help.
Please explain in detail what happens behind the scenes in the both the snippets and why it doesn't give error in code snippet 1.
Code snippet 1:
package com.company;
public class Main
{
public static void main(String[] args)
{
double dbl = 10.25;
int i1 = (int)Math.round(dbl);
}
}
Code snippet 2:
package com.company;
public class Main
{
public static void main(String[] args)
{
double dbl = 10.25;
Long lng = Math.round(dbl);
int i2 = (int)lng;
}
}
Let's take a closer look at what happens. In snippet 1:
double dbl = 10.25;
int i1 = (int) Math.round(dbl);
You declare a double. The result after rounding is a long. Then comes a cast to int which is possible since both are primitive types, Java allows the cast. Then you store this inside int.
In snippet 2 however things change a bit:
double dbl = 10.25;
Long lng = Math.round(dbl);
int i2 = (int) lng;
You declare a double, round returns a long but you want to store it inside Long. So Java automatically transforms long into Long, this is called auto-boxing. Java can box all primitive types to their wrapper classes.
Last you try to cast Long to int but this is not possible since Long is an object now. It can however automatically unbox Long to long. From there you can go to int. Let's first take a look at those two variants:
int i2 = (long) lng; // Make unboxing explicit by casting
int i2 = lng.longValue() // Use unboxing method
However it won't compile either due to:
incompatible types: possible lossy conversion from long to int
So the conversion is possible but the compiler warns us that a long could possibly not fit into an int (lossy conversion), thus it prevents us from doing so.
We can however do the conversion by again making it explicit by casting:
int i2 = (int) lng.longValue() // The whole process completely explicit
Or if you have Java 8, use Math#toIntExact (documentation) which will throw an ArithmeticException if the long doesn't fit into the int:
int i2 = Math.toIntExact(lng.longValue());
Note that Java won't unbox your Long to long and then cast it to int automatically, you will need to make the unboxing explicit on your own, as shown.
It's simply one of the casting rules of the JVM, in this case probably to prevent unintentional programming errors.
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.
Why values of c are 2.0 and 2.5 although they have same data type
How is conversion taking place in a/b
public static void main(String[] args)
{
int a = 5,b=2;
float c;
c=a/b;
System.out.println(c);
c=(float)a/b;
System.out.println(c);
}
The answer lies in understanding that despite declaring c as float, integer division still takes place with a/b. Integer division in Java truncates any fractional part (so it can remain an int). Only then is it implicitly converted to a float upon assignment to c, and 2.0 is printed.
The cast to a float in (float)a/b changes a to 5.0f and forces floating point division before the result is assigned to c, so the correct result 2.5 is printed.
In the first statement, a/b is calculated. As both variables are integers, the result is an integer too: 2. In your second statement, a is first converted to a float and then divided by b. As one of the values is a float, the result is a float too: 2.5.
The first division is int / int --> int result.
the second is Float / int, --> Float results.
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);
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.