2008-12-13 29 views
10

Tôi hiện đang làm việc với ngôn ngữ lập trình, diễn giải, chuyên ngành được triển khai trong Java. Là một phần rất nhỏ của ngôn ngữ, tôi muốn thêm khả năng thực hiện cuộc gọi vào Java. Trước khi tôi đi sâu vào tất cả các sự phản chiếu dữ dội, tôi đã tự hỏi liệu có ai biết một thư viện chung để làm phần "phụ trợ" trong việc gọi mã Java một cách phản xạ hay không.Có thư viện "phụ trợ" chung để phản ánh Java không

Tức là, tôi phân tích một chuỗi (tôi định nghĩa ngữ pháp) thành một số cấu trúc dữ liệu đại diện cho một cuộc gọi phương thức Java (hoặc hàm tạo hoặc truy cập trường) và sau đó chuyển cấu trúc dữ liệu đó tới thư viện này. kết quả. Đặc biệt, tôi muốn nó đã xử lý tất cả các trường hợp cạnh mà tôi không muốn tìm ra:

  • Tự động chọn đúng phương pháp dựa trên các loại đối số (như Class.getDeclaredMethod thông minh)))
  • Xử lý phân biệt giữa mảng và đối tượng bình thường tham chiếu
  • vv

tôi đã dành một ít thời gian nhìn vào hiện thực của các ngôn ngữ động trên JVM, nhưng đây là những thường phức tạp hơn nhiều so với tôi đang tìm kiếm hoặc được tối ưu hóa cao cho các hạt ngôn ngữ ular.

Một tùy chọn khác là chuyển ngữ pháp của tôi thành chuỗi bằng ngôn ngữ động và gọi nó bằng Rhino hoặc gì đó, nhưng chi phí cao hơn một chút so với tôi đang tìm kiếm.

Cảm ơn!

Trả lời

6

Chỉ cần nhận xét cho câu trả lời của riêng bạn; thực sự là beanutils có hỗ trợ cho việc "kết hợp chặt chẽ" cho một tập các tham số. Xem getMatchingAccessibleMethod()

BeanUtils thực sự mạnh mẽ và có rất nhiều phương pháp tiện ích để kiểm tra các lớp học. Sự hỗ trợ tương tự là tự nhiên có sẵn cho các nhà xây dựng.

2

Hãy xem Java's scripting support; Tôi tin rằng nó sẽ giúp bạn giải quyết vấn đề của bạn.

+0

Không. Tôi đang tìm một cái gì đó với một phương pháp như "Object invoke (đối tượng Object, String nameOfMethod, Object [] args)" tìm ra phương thức đúng (lấy thừa kế và chuyển đổi kiểu vào tài khoản) và gọi nó. Java scripting chỉ cho phép tôi đánh giá các chuỗi trong một ngôn ngữ kịch bản hiện có. –

+0

Vâng, Java scripting không chỉ cho phép bạn gọi các ngôn ngữ kịch bản từ Java, nếu tôi không nhầm - nó cung cấp các cơ chế để cho phép mã kịch bản tương tác với các đối tượng Java (được gọi là Ràng buộc trong tài liệu), trông rất giống với những gì bạn đang cố gắng làm. – alex

+0

... ít nhất, hãy xem triển khai tập lệnh hiện có sẽ giúp bạn – alex

7

Hãy thử các module FEST Reflection. Đó là một cách thông thạo để làm phản xạ Java. Ví dụ:

String name = method("get").withReturnType(String.class) 
         .withParameterTypes(int.class) 
         .in(names) 
         .invoke(8); 
0

Tôi đã kết thúc với đề xuất của Alex. BeanUtils giúp rất nhiều cho đậu, nhưng tôi không muốn làm việc chỉ với Đậu. FEST trông thực sự tuyệt vời và tôi đã đánh dấu nó để nghiên cứu thêm, nhưng giống như BeanUtils, nó không xuất hiện để giải quyết những gì tôi coi là vấn đề khó khăn ở đây. Cụ thể, được đưa ra một tên phương thức và danh sách các đối số, chọn phương thức phù hợp nhất với các đối số. Nếu một phương pháp có một phao và tôi có một đôi, nó phải đủ thông minh để không từ chối phương pháp đó bởi vì chữ ký không khớp chính xác.

Rõ ràng, các ngôn ngữ kịch bản được xây dựng trên JVM giải quyết vấn đề này, nhưng theo một cách phức tạp hơn nhiều so với tôi cần do tối ưu hóa ngôn ngữ cụ thể. Vì vậy, vì đây là một tính năng nhỏ và thử nghiệm, tôi đã chọn một giải pháp nhanh chóng bằng cách sử dụng hỗ trợ công cụ tạo kịch bản (JavaScript, đặc biệt) trong Java 1.6. Đây là ý tưởng cơ bản:

private ScriptEngine engine = ... initialize with JavaScript engine ... 

private Object invoke(Object object, String methodName, Object[] args) 
    throws RhsFunctionException 
{ 
    // build up "o.method(arg0, arg1, arg2, ...)" 
    StringBuilder exp = new StringBuilder("o." + methodName); 
    engine.put("o", object); 
    buildArgs(arguments, exp); 

    try { 
     return engine.eval(exp.toString()); 
    } 
    catch (ScriptException e) { 
     throw new RhsFunctionException(e.getMessage(), e); 
    } 
} 

private void buildArgs(Object[] args, StringBuilder exp) 
{ 
    // Use bindings to avoid having to escape arguments 
    exp.append('('); 
    int i = 0; 
    for(Symbol arg : args) { 
     String argName = "arg" + i; 
     engine.put(argName, arg); 
     if(i != 0) { 
      exp.append(','); 
     } 
     exp.append(argName); 
     ++i; 
    } 
    exp.append(')'); 
} 

Rõ ràng là một chút nữa, nhưng đây là ý tưởng cơ bản. Tôi không thực sự thích xây dựng một chuỗi và đánh giá nó, nhưng bằng cách sử dụng các ràng buộc được đề xuất bởi Alex, tôi tránh hầu hết các cạm bẫy xung quanh thoát. Hơn nữa, tôi có một giao diện đơn giản, sạch sẽ mà tôi có thể trao đổi với một thực thi "thực" nếu nó chứng minh cần thiết.

Mọi phản hồi hoặc giải pháp thay thế đều được hoan nghênh hơn.

1

Tôi rất muốn xem xét cũng xem xét lớp ReflectionUtils của lò xo. Xử lý phản chiếu rất mạnh mẽ.

1

ĐẾN nêu vấn đề này lại từ cõi chết:

invoke(Object object, String methodName, Object[] args) 

Apache Commons lang có chính xác phương pháp đó. MethodUtils#invoke

1

Tôi đã bắt đầu để tạo ra một thư viện com.lexicalscope.fluent phản chiếu: thông thạo phản chiếu mà tích hợp với hamcrestlambdaj

Bạn có thể viết mã như thế này; trong đó kêu gọi tất cả các phương pháp sau xây dựng chú thích trong một lớp học:

forEach(
    object(subject).methods(annotatedWith(PostConstruct.class)), 
    ReflectedMethod.class).call(); 

Blog bài ở đây: http://www.lexicalscope.com/blog/category/software-projects/fluent-reflection/

Tài liệu ở đây: http://fluent-reflection.lexicalscope.com/

Bạn có thể lấy nó từ maven trung tâm ở đây: http://repo1.maven.org/maven2/com/lexicalscope/fluent-reflection/fluent-reflection/

Có một số tính năng cơ bản bị thiếu tại thời điểm này, như truy cập vào các trường, nhưng nó hoạt động cho các phương thức. Nó có thể sẽ mất một thời gian để có được một điểm ổn định thực sự tính năng (như một hoặc hai năm), vì tôi chỉ làm việc trên nó đôi khi. Nhưng nó được phát triển theo tiêu chuẩn chất lượng cao (tôi hy vọng) và nó là nguồn mở để bạn về cơ bản có thể sử dụng nó như bây giờ nếu nó có tất cả các tính năng bạn cần (bạn chỉ cần điều chỉnh mã của mình một chút nếu bạn muốn để sử dụng các phiên bản mới hơn được phát hành). Tôi đang sử dụng nó trong một số mã sản xuất tại thời điểm đó.

Nó được thiết kế để có thể mở rộng, vì vậy bạn có thể cắm vào các chiến lược để tìm ra các phương pháp bạn muốn theo kiểu lỏng lẻo (tổng hợp). Vì vậy, nếu nó không có chiến lược tra cứu phương pháp chính xác bạn muốn, hy vọng nó rất dễ dàng để thêm nó.

+0

Điều đó trông thực sự mạnh mẽ. Bạn cũng có thêm 1-2 ví dụ đơn giản không? –

+0

Và ví dụ về việc chọn tất cả các phương thức get: đối tượng (chủ đề) .methods (callableHasNameStartingWith ("get") và (callableHasNoArguments()) và (không (callableHasVoidReturn()))); – lexicalscope

2

Nếu bạn đang tìm kiếm sự đơn giản, tôi đã tạo một thư viện đơn giản có tên là jOOR để tạo điều kiện truy cập vào API phản chiếu trong Java. Nó hỗ trợ các hành động thiết yếu nhất mà không cần xây dựng một API lớn. Dưới đây là ví dụ về mã jOOR trông như thế nào:

String world = 
on("java.lang.String") // Like Class.forName() 
.create("Hello World") // Call the most specific matching constructor 
.call("substring", 6) // Call the most specific matching substring() method 
.call("toString")  // Call toString() 
.get()     // Get the wrapped object, in this case a String 
Các vấn đề liên quan