3
 public class NewMain
 {
     public static void main(String[] args)
     {
         long num = 100;
         System.out.println(xMethod(5,1000000000000L));

     }

     public static int xMethod(int n, long x)
     {
         System.out.println("int, long");
         return n;
     }

     public static long xMethod(long n, long x)
     {
         System.out.println("long, long");
         return n;
     }

 }

To me, this looks very ambiguous.

A number within the range of an integer CAN be a long, which is demonstrated with the declaration of num.

And I was curious what would happen if I had two methods with two different parameters.

Apparently, when writing the parameters, the number MUST have an L at the end to indicate that it's a long, whereas when declaring num, that wasn't necessary. Why is this?

I first thought that if it was within the range of an int, it'll automatically think of it as an int and when it goes above that range, it'll be used as a long. However, with my second parameter, it won't pass unless I put the L. It says it's not within the range of an int.

Can someone give some clear rules to this?

John Doe
  • 43
  • 1
  • 5

5 Answers5

3

A numeric literal with no decimal point is always treated as int unless it has a suffix that specifies otherwise (such as L).

If it's outside the range of int, this is a compilation error.

when declaring num, that wasn't necessary

You can assign an int literal to a long variable, since there's no loss of information.

Eran
  • 387,369
  • 54
  • 702
  • 768
1

Quoting Java Language Specification:

3.10.1. Integer Literals

An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1).

The suffix L is preferred, because the letter l (ell) is often hard to distinguish from the digit 1 (one).

So, an integer number is an int unless ending with L. Since 1000000000000 is too large for a int, it must end with L, or you get a compile error ("The literal 1000000000000 of type int is out of range").

3.10.2. Floating-Point Literals

A floating-point literal is of type float if it is suffixed with an ASCII letter F or f; otherwise its type is double and it can optionally be suffixed with an ASCII letter D or d (§4.2.3).

So, an decimal number is a double unless ending with f.

5.1.2. Widening Primitive Conversion

  • int to long, float, or double

  • float to double

So, the compiler will silently widen (convert) int values to long, if needed.

In your case, the compiler prefers the first method, because it can be called without any conversions.

If the first method hadn't existed, the second method would be called, after an implicit conversion of the first parameter to long.

Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247
1

Few points come to my mind for your question,
1. A variable is declared long then there is no need to put L for variable value
2. If you are passing a hard coded numeric literal, you put L at the end to make it long otherwise all numeric values are treated as int ( if not properly suffixed )
3.You can pass an int in place of long parameter ( automatic widening will happen )
4. You can't pass a narrow type in place of wider type without explicit casting
5. Parameter conversion is either via explicit casting and automatic widening without considering numeric value magnitude.

For below code sample - "Inside INT LONG " will be printed due to automatic widening and in absence of private static void aMethod(int a , int b)

public class IntVsLons {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        int a =100;
        long b=200;

        aMethod(a,a);

        }

    /*
    private static void aMethod(int a , int b){
        System.out.println("Inside INT  INT  ");
    }
    */

    private static void aMethod(int a , long b){
        System.out.println("Inside INT  LONG ");
    }

    private static void aMethod(long a, long b ){
        System.out.println("Inside LONG LONG ");
    }

Hope it helps !!

Sabir Khan
  • 9,826
  • 7
  • 45
  • 98
0

Your concern is a valid one. Take a look at this scenario:

public static void methodX(long x, int y){

}
public static void methodX(int x, long y){

}

In this case, if you invoke the following, it will give you different results:

methodX(123, 123);    //Compilation error (reference to methodX is ambiguous)
methodX(123L, 123);   //Ok!
methodX(123, 123L);   //Ok!

The first invocation gives you error because by default without the suffix (you create an integer) which will be able to fit into both overloaded methods.


A bit of additional info

  • Without the suffix of l, the default whole number value will be an integer
  • Without the suffix of d, the default decimal value will be a double.
user3437460
  • 17,253
  • 15
  • 58
  • 106
0

An numerical literal without decimal point and without suffix, such as 42 or 100 is always of type int. To make it a long, you have to add a suffix: 42L or 100L.

If you call a method, the actual (compile-time) types of the arguments determine which overloaded method is called. If more than one overloaded method can be called with the given types, the most specific one will be taken. (For the exact rule, read Section 15.2 of the JLS.) So, in your case if the first argument is an int, the first method overload will be called, because int is more specific as long.

xMethod(1, 1)  --> xMethod(int n, long x) is called
xMethod(1L, 1) --> xMethod(long n, long x) is called
Hoopje
  • 12,677
  • 8
  • 34
  • 50