2010-07-22 30 views
8

Tôi có một chức năng mà tôi muốn cung cấp cho một khách hàng cho một mockup phần mềm mà chúng tôi đang chuẩn bị - và tôi muốn biết nếu nóTìm lớp Java mới trong thời gian chạy

  1. thể
  2. thông minh (aka không ngu ngốc)
  3. điều tốt nhất

tôi muốn khách hàng để có thể viết một lớp java mà thực hiện giao diện Computable tôi và dính vào nó trong một số thư mục định trước. Thư mục này sẽ chứa các tệp .java chứ không phải tệp .class. Sau đó, khi chạy, tôi muốn chương trình của tôi tìm kiếm thư mục đó và trích xuất tất cả các Computables từ thư mục đó và lưu chúng trong một bản đồ từ tên của Computable đến đối tượng Computable. Các Computable chỉ nên có một constructor mặc định và giao diện nó sẽ chỉ có một phương pháp gọi là compute mà ánh xạ một mảng của Object đến một Object.

+0

Bạn có muốn biên dịch tệp của người dùng trong thời gian chạy không? – jedierikb

+0

Liệu nó có phải là ngôn ngữ của chính nó hay một ngôn ngữ kịch bản khác có thể được chấp nhận không? – skaffman

+0

@jedierikb Nếu nó dễ dàng, đủ để biên dịch tại thời gian chạy đó sẽ là tốt. Tôi chỉ không muốn khách hàng phải lo lắng về việc kéo xung quanh các tệp lớp. – JnBrymn

Trả lời

9

Java Compiler API được giới thiệu trong Java SE 6 sẽ cung cấp cho bạn những gì bạn cần.

+0

Lưu ý rằng API này chỉ có sẵn trong JDK, không có trong JRE. Vì vậy, nếu bạn có ý định phân phối nó, enduser/client phải đã cài đặt JDK và điều này là khá phổ biến trong số các công chúng lớn. – BalusC

+0

Ouch! Cảm ơn @BalusC. – djna

+0

@BalusC 'x' ở cuối javax có ngụ ý điều này không? – JnBrymn

0
+0

Có vẻ đầy hứa hẹn, nhưng nó dường như xoay quanh hai giải pháp có thể. 1) Sử dụng API mà một số người đã xây dựng cho chính mình (tôi không muốn mạo hiểm chơi với khung của người khác trong thời gian ngắn tôi đã để lại.) Hoặc 2) Sử dụng sự phản chiếu để tìm ra các lớp đã nạp nào thực thi 'Computable'. Nhớ lại rằng các lớp của tôi sẽ không được tải ... chúng chỉ là các tệp .java. – JnBrymn

0

tôi nghĩ này sẽ đơn giản hơn nếu bạn cho phép khách hàng của bạn để gõ vào một lời tuyên bố mã sử dụng một cái gì đó giống như Groovy, đó là đủ Java-ish, và dễ dàng để thực hiện trong thời gian chạy từ một giá trị String.

+0

Groovy không phải là một siêu sao nghiêm ngặt? Nếu vậy tôi cho rằng bạn chỉ có thể nói với khách hàng của bạn rằng nó đang dùng Java và họ sẽ không còn khôn ngoan hơn nữa. –

+0

Ah, tôi sai rồi. Một tệp java gần như luôn luôn là mã groovy hợp lệ nhưng nó không phải là một superset nghiêm ngặt. –

1

Nếu quá trình biên dịch trong thời gian chạy sẽ trở nên dễ dàng.

Bạn có thể sử dụng javax.tools để thực hiện việc biên dịch nếu cần. Create dynamic applications with javax.tools cũng có thể hữu ích. Nó cũng có thể làm điều đó in memory.

Một lưu ý: sử dụng trình biên dịch tạo phụ thuộc vào JDK; chỉ riêng JRE là không đủ.

+0

Bạn có mã mẫu nào không? Tôi có giải quyết dòng lệnh từ Java để thực thi javac không? Làm thế nào để tôi nghĩ rằng suck trong tập tin lớp học và xây dựng các lớp học? – JnBrymn

+0

@John Berryman: Tôi đã thêm một liên kết ở trên. – trashgod

0

Thật dễ dàng để lặp qua danh sách tệp trong một thư mục. Ai đó đã đề cập rằng có thể gọi trình biên dịch Java từ Java (nếu bạn phân phối lại JDK, mà tôi nghĩ là một điểm mà pháp lý cần kiểm tra !!) Đó là phần lớn của trận chiến.

Bạn dường như có một mô hình cố định trong tâm trí của bạn, nơi chỉ các tệp thực hiện một giao diện nhất định được trích xuất từ ​​thư mục. Tôi nghĩ đây là nơi mà phương pháp của bạn cần đưa ra một chút. Cách hợp lý (IMO) để thực hiện việc này là biên dịch tất cả các tệp trong thư mục đó và sau đó với các lớp của chúng được lưu trữ ở đâu đó, bạn có thể tải và phản ánh chúng rồi xác định giao diện nào trong số đó "làm" giao diện và 't. Những thứ không cần thiết sẽ được nạp vào JVM của bạn, nhưng trừ khi nó vô tình lãng phí không gian, mã bạn không thực thi không thể gây hại cho chương trình của bạn.

Sau khi xác định cái nào làm điều có thể tính toán, bạn có thể lưu trữ các lớp đó (hoặc các phiên bản của chúng) trong Bộ sưu tập và làm bất cứ điều gì bạn thích với chúng. Bạn chỉ cần bỏ qua những cái khác.

3

Bạn có thể tìm thấy Google Reflections hữu ích để tìm các lớp triển khai/mở rộng một giao diện/siêu lớp nhất định trong đường dẫn lớp. Đó là sau đó đơn giản như

Reflections reflections = new Reflections("my.project.prefix"); 
Set<Class<? extends SomeClassOrInterface>> subTypes = reflections.getSubTypesOf(SomeClassOrInterface.class); 

Sau đó, để kiểm tra nếu nó thực sự có một constructor mặc định không-arg, chỉ cần kiểm tra đối với từng nếu Class#newInstance() không ném bất kỳ ngoại lệ.

+0

Vậy điều gì sẽ xảy ra nếu tệp .class không nằm trên đường dẫn hiện tại, nhưng trong một thư mục mà chúng ta chỉ biết về thời gian chạy? – JnBrymn

+1

Bạn có thể thêm đường dẫn vào đường dẫn lớp trong thời gian chạy bằng ['URLClassLoader'] (http://java.sun.com/javase/6/docs/api/java/net/URLClassLoader.html). – BalusC

0

Bạn có thể sử dụng BeanShell. Thư viện này nhỏ và không yêu cầu JDK. Nó được sử dụng trong một số IDE và máy chủ web. Phiên bản mới nhất dường như có hỗ trợ bạn cần tải các tệp .java từ đường dẫn lớp. (Vẫn còn trong phiên bản beta)

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