2013-04-28 35 views
6

Dưới đây là một ví dụ:Có phải int.class.isInstance (Object) là mâu thuẫn không?

public boolean check(Class<?> clazz, Object o) 
{ 
    return clazz.isInstance(o); 
} 

check(int.class, 7); // returns false 

Kể từ isInstance chấp nhận một Object, nó sẽ không làm việc với int, vì int là một loại nguyên thủy và bị autoboxed để Integer. Vì vậy, có thể viết một phương pháp kiểm tra chung không? Hoặc tôi có nên đảm bảo rằng clazz thuộc loại Class<? extends Object>?

+4

Thay vì sử dụng các thẻ không có ý nghĩa như 'int',' types' hoặc thậm chí 'isintance', bạn nên gắn thẻ câu hỏi bằng ngôn ngữ bạn đang sử dụng. Điều đó sẽ thu hút nhiều người xem hơn và do đó làm tăng cơ hội để bạn nhận được câu trả lời thỏa mãn. –

+1

Sry, tôi hoàn toàn quên điều đó. ... Tôi đoán java đã trở nên tự nhiên với tôi: D – mike

+2

Bạn đã đọc [câu trả lời này] (http://stackoverflow.com/a/7083456/516433) chưa? – Lucas

Trả lời

6

Không phải tất cả các đối tượng Class đại diện cho các lớp/loại tham chiếu; cũng có Class đối tượng đại diện cho các loại nguyên thủy. Điều này rất hữu ích vì trong việc sử dụng sự phản chiếu với các trường và các phương thức, bạn thường cần phải xác định kiểu của chúng, và nó có thể là một kiểu nguyên thủy. Vì vậy, Class được sử dụng để đại diện cho tất cả các loại tiền như thế này.

Tuy nhiên, nhiều phương pháp của lớp Class không có ý nghĩa đối với các loại nguyên thủy. Ví dụ, đối tượng không thể là instanceof int. Do đó, phương thức tương tự .isInstance() sẽ luôn trả về false. Vì tham số của phương thức đó là loại Object, nó chỉ đơn giản là không thể từ một điểm ngôn ngữ của xem cho những gì bạn vượt qua trong đó để có một kiểu nguyên thủy.

Chắc chắn, trong Java 5 + khi bạn vượt qua một nguyên thủy với một tham số kiểu Object, nó phải trải qua autoboxing, nhưng thực tế là nó đã trải qua autoboxing nghĩa rằng những gì đã được thông qua thực sự là một tham chiếu đến một đối tượng. Các kiểu tham chiếu và kiểu nguyên thủy là khác biệt. Tham số là loại tham chiếu hoặc kiểu nguyên thủy. Vì vậy, bạn không thể viết một phương thức có thể lấy một "tham chiếu hoặc nguyên thủy".

Những gì bạn có thể yêu cầu, trong ví dụ của bạn, là để phát hiện rằng đối tượng đã được hộp tự động từ nguyên thủy và so sánh nó với kiểu nguyên thủy. Tuy nhiên, không thể phát hiện xem người gọi có tự động đóng hộp đó hay không, vì tính năng autoboxing là một hoạt động hoàn toàn người gọi xảy ra trước cuộc gọi.

Tuy nhiên, giả sử nó đã được tự động đóng hộp, bạn biết loại nó nên đi đến. Nếu bạn đang mong đợi một số int và được tự động chuyển và được chuyển đến phương thức của bạn, nó phải là một phiên bản của Integer.Vì vậy, những gì bạn có thể làm là, khi clazz đại diện cho một loại nguyên thủy, thay vào đó thực hiện kiểm tra trên lớp bao bọc của nó. Do đó, khi thấy rằng clazzint.class, hãy thay thế bằng Integer.class và sau đó thực hiện kiểm tra. Lưu ý rằng cách này vẫn không cho biết điều gì đã được truyền khi thông số o được tự động đóng hộp.

+0

Tôi đã làm một số nghiên cứu, có vẻ như không có phương pháp chung để có được lớp bao bọc của một kiểu nguyên thủy, hoặc một cách chung để có được trường TYPE của một lớp trình bao bọc. Tôi đoán tôi phải mã hóa bản đồ và thực hiện tra cứu. – mike

+1

@mike Nếu bạn tình cờ sử dụng ổi, các trình điều khiển lớp ['Primitives'] (http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/primitives/Primitives.html) những trường hợp sử dụng đó rồi. –

+0

Cảm ơn nhưng, các phương pháp ổi cũng dựa trên một bản đồ mã hóa cứng. Dù sao, câu trả lời tuyệt vời và ý kiến ​​ở đây, tôi đã học được rất nhiều! – mike

2

Không có lớp int trong Java. Lớp Integer của nó. 7 được chuyển đổi thành Integer.valueOf(7)int.class sẽ được chuyển đổi thành Integer.class theo JLS.

Nếu p là tên của một loại nguyên thủy, chúng ta hãy B là loại một biểu loại p sau khi chuyển đổi boxing. Sau đó, loại của p.classClass<B>.

Vì đối tượng lớp, trong khi int là loại nguyên thủy. Vì vậy, hầu hết các phương pháp của Class chẳng hạn như isInstance, isAssignableFrom v.v. hoạt động trên Đối tượng không hợp lệ trong ngữ cảnh int.class, do đó bạn thấy sự mâu thuẫn đó.

check(Integer.class, 7); 

nên cho kết quả mong đợi.

+0

Tôi sử dụng một hình thức của phương pháp kiểm tra trong bối cảnh của một setter chung chung, nơi tôi trích xuất các loại thông tin từ các thuộc tính để thiết lập và so sánh nó với kiểu tham số của setter. Vì vậy, tôi nên cấm các loại nguyên thủy cho các thuộc tính tôi muốn thiết lập? – mike

+0

Sẽ hữu ích khi hiển thị mã cho bộ đặt chung này. Nếu nó giống như ' void setSomething (T theThing)', bạn sẽ không thể sử dụng trực tiếp nguyên thủy trực tiếp anyway - chúng sẽ luôn được tự động hóa, vì các kiểu generic chỉ có thể là Objects, không bao giờ nguyên thủy. – BeeOnRope

+0

Bạn có thể xem mã trong câu hỏi khác mà tôi đã hỏi trên SO http://stackoverflow.com/questions/16225623/how-to-avoid-getters-setters-in-classes-with-many-instance-variables – mike

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