2013-07-15 93 views
11

Tôi đã theo dõi một lỗi ngày hôm nay, và tôi nhận thấy một cái gì đó kỳ lạ trong một trong các lớp học của chúng tôi. Tôi cắt càng nhiều mã càng tốt để đăng ở đây:Java phân biệt các phương thức này với cùng tên/chữ ký như thế nào?

class A { 
    static int obtainNumber() { return 42; } 
    static int obtainNumber() { return 3; } 
    static int obtainNumber() { return -1; } 
    static { 
     System.out.println(obtainNumber()); 
    } 
} 

Lớp này có 3 phương pháp có cùng tên và chữ ký chính xác. Lúc đầu, tôi nghĩ rằng đây là mã không hợp lệ, nhưng sau đó nhật thực sẽ làm nổi bật mã màu đỏ. Nó hoạt động:

javac A.java && java A 
42 
Exception in thread "main" java.lang.NoSuchMethodError: main 

Vì vậy, tôi nghĩ có thể Java sẽ chỉ sử dụng ứng dụng đầu tiên mà nó thấy. Tôi sắp xếp lại để kiểm tra:

class A { 
    static int obtainNumber() { return 3; } 
    static int obtainNumber() { return -1; } 
    static int obtainNumber() { return 42; } 
    static { 
     System.out.println(obtainNumber()); 
    } 
} 

Nope, cùng kết quả:

javac A.java && java A 
42 
Exception in thread "main" java.lang.NoSuchMethodError: main 

Tôi nghĩ có lẽ nó sử dụng một với 42 vì lớn nhất của nó. Để kiểm tra điều này, tôi đã lấy bản gốc và thay đổi giá trị trả về:

class A { 
    static int obtainNumber() { return 0; } 
    static int obtainNumber() { return 1; } 
    static int obtainNumber() { return 2; } 
    static { 
     System.out.println(obtainNumber()); 
    } 
} 

Nó vẫn biết sử dụng đầu tiên:

javac A.java && java A 
0 
Exception in thread "main" java.lang.NoSuchMethodError: main 

Và nếu tôi sắp xếp lại chúng một lần nữa:

class A { 
    static int obtainNumber() { return 1; } 
    static int obtainNumber() { return 0; } 
    static int obtainNumber() { return 2; } 
    static { 
     System.out.println(obtainNumber()); 
    } 
} 

Kết quả tương tự:

javac A.java && java A 
0 
Exception in thread "main" java.lang.NoSuchMethodError: main 

Tôi nghĩ Java là một ngôn ngữ dựa trên văn bản, điều mà tôi mong đợi làm cho điều này là không thể. Java theo dõi phương thức nào?

+1

Nếu bạn nhận thấy, hình ảnh được chụp là một cú pháp khác với cú pháp khác nhau từ những người khác. Có lẽ điều đó có thể gợi ý bạn dựa trên các ký tự ẩn hoặc ngữ pháp ẩn. – hexafraction

+1

Tại sao ai đó làm điều này? Nó giống như một trò ảo thuật chơi trên người lập trình viên – Shoe

+0

@Jim từ Batman The Dark Knight: * Một số người chỉ muốn xem thế giới cháy bỏng *. –

Trả lời

6

Ký tự ẩn. Các mã nguồn tương đương với

static int obtainNumber() { return 42; }

static int obtain\ufeffNumber() { return 3; }

static int obtain\ufeff\ufeffNumber() { return -1; }

Để tránh những loại vấn đề, các file nguồn của tôi là nghiêm US-ASCII. Tôi muốn chắc chắn rằng các nhân vật tôi thấy chính xác là các trình biên dịch nhân vật nhìn thấy.

+8

Làm cho tôi nghĩ rằng anh ấy đã cố tình ... –

+0

Chà tôi nghĩ lập trình viên cuối cùng hơi bực mình ... – Michael

8

Tôi chỉ sao chép/dán này trong IDE của tôi và mặc dù đó là một điều kỳ diệu, sau đó khi cố gắng để lưu các tập tin một thông báo lỗi xuất hiện thanh toán bù trừ vấn đề này:

Lưu không thể được hoàn thành. Hãy thử Tệp> Lưu dưới dạng ... nếu sự cố vẫn tiếp diễn.

Lý do: Một số ký tự không thể được ánh xạ bằng mã hóa vi phân "Cp1252". Hoặc thay đổi mã hóa hoặc xóa các ký tự không được mã hóa caracter "Cp1252" hỗ trợ.

Vì vậy, những phương pháp này không có cùng tên, chỉ cần sử dụng các ký tự trông giống nhau.

Thông tin thêm liên quan đến mã hóa ký tự trên các tập tin nguồn Java:

+0

@downvoter ít nhất là giải thích lý do của bạn để downvote. –

1

My gốc bình luận:

Nếu bạn thông báo, trên e được thực hiện là một với cú pháp khác nhau hiliting từ những người khác.Có lẽ điều đó có thể gợi ý bạn dựa trên các ký tự ẩn hoặc ngữ pháp ẩn.

Tôi đã dán điều này vào Eclipse và nhận thấy thêm một chút ký tự. Tôi đã ném tập tin đã lưu của tôi (trong CP1252) vào một trình soạn thảo hex, và tìm thấy một dấu thứ tự byte.

Khi tôi nhìn, CP1252 không có dấu thứ tự byte, nhưng các ký tự nằm trong CP1252. Một ký tự unicode đi lạc có thể đã nhập.

Khi tôi nhìn kỹ hơn, một phương pháp khác có dấu thứ tự byte khác theo thứ tự byte khác.

Làm thế nào chúng xuất hiện, chúng tôi sẽ không bao giờ biết. Tuy nhiên, chúng tôi biết rằng trình biên dịch đang lấy số mà không cần dấu thứ tự byte.

Bạn nên kiểm tra dự án để tìm sự cố mã hóa, đặc biệt nếu nó đã được khôi phục từ các loại hệ thống khác hoặc phương tiện lưu trữ cũ hơn có thể bị lỗi hoặc đã tiếp xúc với thiết bị cũ.

Chúng tôi thực sự cần xử lý hành vi FGITW này thông qua meta đôi khi ngay bây giờ.