2011-08-21 30 views
49

Về cơ bản những gì tôi cần làm là nàyLàm thế nào để truy cập vào lớp Java bên trong tĩnh thông qua Clojure interop?

FileChannel.MapMode.READ_ONLY 

tôi đã cố gắng làm những điều hiển nhiên

(.. FileChannel MapMode READ_ONLY) 

nhưng mà kết thúc lên ném một ngoại lệ

java.lang.NoSuchFieldException: MapMode 

ngay cả những ký hiệu / quy định như đối với truy cập các trường tĩnh trong interop documentation cũng tạo ra cùng một ngoại lệ

(. (FileChannel/MapMode) READ_ONLY) 

Trả lời

75

Bạn truy cập vào các lớp bên trong với $

java.nio.channels.FileChannel$MapMode/READ_ONLY 
+27

Đừng quên rằng nếu bạn đang nhập FileChannel với chức năng 'import' hoặc bằng từ khóa': import', bạn cũng phải xác định rằng bạn đang nhập 'FileChannel $ MapMode' –

+1

Cảm ơn bạn @TerjeDahl. Tôi nghĩ bạn nên chỉnh sửa câu hỏi của bạn để bao gồm điều này, Hamza Yerlikaya. – Joe

11

Cú pháp (FileChannel/MapMode) là một việc đơn giản hóa và chỉ nhằm mục đích cho các lĩnh vực và phương pháp tĩnh (đối với các lĩnh vực, thậm chí bạn có thể bỏ qua các dấu ngoặc đơn)! Ngoài ra các hình thức ... là dành cho các trường/phương thức nhưng KHÔNG cho các lớp lồng nhau/bên trong!

Đối với JVM, một lớp bên trong Outer.Inner chỉ là một lớp có tên Outer$Inner (và trình biên dịch tạo một tệp Outer$Inner.class cho việc này). Trình biên dịch Java cho phép bạn tham khảo nó bằng Outer.Inner. Bạn cũng có thể định nghĩa một lớp không phải là bên trong có tên là Outer$Inner mà trình biên dịch cho phép bạn tham chiếu là Outer$Inner. Bạn không thể xác định cả hai cùng một lúc, vì cả hai đều có tên lớp là Outer$Inner (và .class tệp có tên Outer$Inner.class, vì vậy đây sẽ là tên lớp trùng lặp!)

Khi sử dụng phản ánh - ví dụ: với Class.forName() - (thường để giới thiệu một số năng động), bạn không thể bỏ qua tên gói của một lớp đã nhập và bạn phải sử dụng tên lớp thực với ký hiệu $ thay vì dấu chấm.

Có lẽ vì bản chất động, Clojure có cùng cách tiếp cận, vì vậy bạn cần sử dụng biểu mẫu my.package.Outer$Inner nếu lớp học ở my.package - ngay cả khi bạn đã nhập lớp ngoài! Để tránh tên gói, bạn rõ ràng có thể nhập các lớp bên trong my.package.Outer$Inner và sau đó đề cập đến nó như Outer$Inner (tên lớp thực sự của nó!) Nhưng bạn sẽ không giảm này để Inner bằng cách chỉ cần nhập nó:

Inner không có ý nghĩa để JVM, chỉ Java-Compiler cung cấp cho bạn lối tắt này từ ngữ cảnh biên dịch thời gian (không có sẵn cho JVM và các phương thức như Class.forName khi chạy!) ... OK, trong Clojure bạn có thể, dĩ nhiên, luôn định nghĩa: (def Inner Outer$Inner) ... hoặc (def Tom Outer$Inner) hoặc (def Harry Outer$Inner) hoặc bất cứ điều gì ... nếu bạn thích điều đó tốt hơn.

+0

điều này có lẽ là một lời giải thích tốt đẹp. cám ơn. – tutysara

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