2013-08-01 31 views
12

JVM quyết định phương thức quá tải nào cần gọi lúc biên dịch. Tôi có một ví dụ:Cách JVM tìm phương thức (tham số có đối sánh gần nhất) để gọi trong trường hợp quá tải hàm

public class MainClass{ 

    public static void go(Long n) {System.out.println("takes Long ");} 
    public static void go(Short n) {System.out.println("takes Short ");} 
    public static void go(int n) {System.out.println("takes int ");} 

    public static void main(String [] args) { 
    short y = 6; 
    long z = 7; 
    go(y); 
    go(z); 
    go((Short)y); 
    } 
} 

Theo hiểu biết của tôi, nó nên in như sau:

takes Short 
takes Long 
takes Short 

... nhưng sản lượng thực tế là:

takes int 
takes Long 
takes Short 

Tuy nhiên nếu tôi có ba chức năng sau:

public static void go(Integer n) {System.out.println("takes Integer");} 
public static void go(Long n) {System.out.println("takes Long ");} 
public static void go(Short n) {System.out.println("takes Short ");} 

... và gọi nó là sử dụng:

int a= 10; and go(i); //output : takes Integer. 

... tại sao lại có có sự khác biệt cho shortint?

+0

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.4 – kosa

+0

có thể trùng lặp http://stackoverflow.com/ q/6268157/2087187 – EProgrammerNotFound

Trả lời

18

Xem JLS Section 15.12.2, cho các quy tắc biên dịch sau để xác định phương pháp để gọi. Trình biên dịch luôn chọn phương pháp cụ thể nhất trong trường hợp các phương pháp của bạn bị quá tải:

Có thể có nhiều phương pháp như vậy. Bộ mô tả (chữ ký cộng với kiểu trả về) của phương thức cụ thể nhất là phương thức được sử dụng trong thời gian chạy để thực hiện phương thức gửi.

biên dịch đầu tiên cố gắng giải quyết các phương pháp mà không đấm bốc hay unboxing như trích dẫn ở đó:

Giai đoạn đầu (§15.12.2.2) thực hiện quá tải độ phân giải mà không cho phép đấm bốc hay unboxing chuyển đổi, hoặc sử dụng lời gọi phương thức arity biến. Nếu không có phương pháp áp dụng được tìm thấy trong giai đoạn này thì việc xử lý tiếp tục đến giai đoạn thứ hai.

Mỏ nhấn mạnh.

Vì vậy, trong 1 st mã của bạn, vì ngắn thể được sử dụng như là đối số cho tham số kiểu int .Trình biên dịch sẽ không sử dụng phương thức với tham số Short, vì điều đó đòi hỏi quyền anh. Mặc dù trong trường hợp của dài loại, vì nó không thể được sử dụng làm đối số cho loại int, nó sẽ được chuyển thành boxing Long. Ghi nhớ Mở rộng được ưu tiên hơn Quyền anh.

Trong 2 nd của bạn, không có cách nào khác ngoài boxing int đến Integer. Vì vậy, nó gọi phương thức với tham số Integer.

8

JVM không tìm thấy gì cả. Trình biên dịch có. Nó chọn cụ thể nhất phương pháp, theo các quy tắc trong JLS section 15.12.2.5:

Nếu có nhiều hơn một phương pháp thành viên vừa tiếp cận và áp dụng đối với một invocation phương pháp, nó là cần thiết để lựa chọn một để cung cấp các mô tả cho chạy thời gian gửi công văn. Ngôn ngữ lập trình Java sử dụng quy tắc mà phương pháp cụ thể nhất được chọn.

Trực giác không chính thức là một phương pháp cụ thể hơn phương pháp khác nếu bất kỳ lời gọi nào được xử lý bằng phương pháp đầu tiên có thể được truyền sang phương thức khác mà không có lỗi loại biên dịch.

... (quy tắc đầy đủ) ...

+2

+1 không chỉ tên và loại thông số là đối sánh chính xác mà còn phải là loại trả về. Nếu bạn gọi B và bạn thay đổi kiểu trả về của một phương thức trong B mà không biên dịch lại A, nó sẽ thất bại trong việc tìm ra phương thức khi chạy. –

1

Vì upcasting to int nằm trong phiên bản 1.0 của Java và auto-boxing đã được thêm vào phiên bản 5.0. Thay đổi hành vi sẽ vi phạm mã được viết cho phiên bản Java cũ hơn.

+0

Nó không phải là "upcasting" --- đó là một "mở rộng chuyển đổi". Nhưng nếu không một điểm tốt, +1. –

+1

@MarkoTopolnik. Vâng câu trả lời có vẻ như một bản sao dán của câu trả lời được chấp nhận từ các bản sao được đăng cho câu hỏi này. Vì vậy, lỗi là trong * Nguồn *. lol;) –

+0

@RohitJain Rất tiếc, cảm ơn vì đã kiểm tra điều đó! Và chúng ta biết đạo văn là gì ... –

0

Mở rộng xảy ra trước khi boxing (nếu có). Vì vậy, short sẽ trở thành int và gọi các phương thức đó.

Bên cạnh đó, không trực tiếp liên quan với những câu hỏi này, nhưng điểm thú vị: Bạn không có hộp và mở rộng ví dụ: short không thể trở thành Integer

0

Java trông cho trận đấu gần nhất đầu tiên. Nó cố gắng tìm ra sau:

  1. Kết hợp chính xác theo loại
  2. Matching một kiểu lớp siêu
  3. Chuyển đổi sang một loại nguyên thủy lớn
  4. Chuyển đổi sang một ô tô đóng hộp loại
  5. varargs
0

Video dưới đây giải thích rõ cách thức JVM chọn một phương thức trong số các phương thức đủ điều kiện khác nhau trong trường hợp quá tải phương thức.

https://www.youtube.com/watch?v=P4XtP1aeI3g

Các vấn đề liên quan