2012-02-16 27 views
5

Các Python sau snipped thực hiện chính xác những gì tôi có nghĩa là:Làm cách nào để mở rộng các đối số trong Java?

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

def function(a, b, c): 
    print("%i :: %s :: %f" % (a,b,c)) 

a = 1 
b = "abc" 
c = 1.0 

function(a, b, c) 

list = [a, b, c] 

# This is what I am searching for in Java 
function(*(list)) 

Vì vậy, tôi có một cấu trúc danh sách giống như và tôi không biết có bao nhiêu lý lẽ nó có, nhưng tôi biết rằng nó có đúng số đối số với đúng loại và định dạng. Và tôi muốn truyền cho họ một phương pháp. Vì vậy, tôi phải "mở rộng" những lập luận đó. Có ai biết làm thế nào để làm như vậy trong Java?

+0

Có lẽ bạn đang tìm kiếm [cho] (http://stackoverflow.com/questions/766559/when-do-you-use-varargs-in-java) [varargs] (http://docs.oracle.com /javase/1.5.0/docs/guide/language/varargs.html)? –

+0

Xác định "mở rộng"? Nó không rõ ràng từ ví dụ của bạn điều này có nghĩa là gì. – Tudor

+0

Nếu bạn chỉ muốn sử dụng một cái gì đó giống như toán tử '%', bạn có thể sử dụng lớp 'Formatter' như trong câu trả lời của tôi bên dưới. –

Trả lời

5

Java không có cơ sở này, vì ngôn ngữ tĩnh, được đánh máy là không phổ biến cho một phương thức lấy một tập hợp các giá trị kiểu đồng nhất có thể được lưu trữ trong một số đối tượng hỗn hợp (mảng, danh sách, v.v. .). Python không có vấn đề này bởi vì mọi thứ đều được nhập động. Bạn có thể làm điều này trong Java bằng cách định nghĩa một phương thức trợ giúp nhận một đối tượng duy nhất trong việc giữ tất cả các tham số, sau đó mở rộng chúng trong một cuộc gọi đến phương thức thực.

Hy vọng điều này sẽ hữu ích!

1

Bạn không thể. Trong Java, các tham số phương thức được kiểm tra tại thời gian biên dịch, và vì nội dung của mảng chỉ được định nghĩa trong thời gian chạy, kiểm tra này sẽ là không thể.

Giải pháp gần nhất của bạn là có phương thức lấy mảng làm tham số và cuối cùng mở rộng các đối số để thực hiện cuộc gọi đến phương pháp được nhắm mục tiêu.

2

Bạn có thể khai báo các thông số tùy chọn với Object... như vậy mà bạn có thể vượt qua một số tùy ý của các đối số và sau đó đúc mỗi trong số họ để loại yêu cầu:

public void method1(String p1, Integer p2) { 
} 

public void method2(Object... params) { 
    method1((String)params[0], (Integer)params[1]; 
} 

Bạn có thể gọi method2 như:

method2("abc", 1); 

Tất nhiên, ví dụ này hơi dư thừa, vì bạn có thể gọi trực tiếp method1, nhưng đó không phải là những gì tôi muốn minh họa. :)

0

Bạn có thể làm điều này:

import java.util.Formatter; 

// ... 

StringBuilder target = new StringBuilder(); 
Formatter formatter = new Formatter(target); 

List<Integer> integers = new ArrayList<Integer>(); 
integers.add(1); 
integers.add(2); 
integers.add(3); 

formatter.format("%d %d %d", integers.toArray()); 
System.out.println(target.toString()); 

Edit:Javadoc for java.util.Formatter

0

Tôi nghĩ rằng đây làm điều tương tự như mã ban đầu của bạn với một cú pháp tương tự ...

public class MultiArgs { 

    public static void main(String[] args) { 
     int a = 1; 
     String b = "abc"; 
     double c = 1.0; 
     List<?> list = Arrays.asList(a, b, c); 

     System.out.println(function(a, b, c)); // 1 :: abc :: 1.000000 
     System.out.println(function(list.toArray())); // 1 :: abc :: 1.000000 
    } 

    private static <T extends Object> String function(T... objects) { 
     return String.format("%d :: %s :: %f", objects); 
    } 
} 
0

Nó không được khuyến khích (như ghi chú câu trả lời của templatetypedef, đây là một mẫu rất phổ biến cho một ngôn ngữ được đánh máy mạnh), nhưng bạn ld làm những gì bạn muốn bằng cách sử dụng sự phản chiếu.

SomeType foo = //obtained from elsewhere 
List<?> args = //obtained from somewhere else 

//this bit obtains the method handle 
Method theMethod = null; 
for (Method m : foo.getClass().getMethods()) { 
    if (m.getName().equals("theMethodIWant") { 
     theMethod = m; 
     break; 
    } 
} 

theMethod.invoke(foo, args.toArray()); //this is the line that does the magic 

Hãy cẩn thận khá nghiêm trọng:

  • Reflection có thể có tác động hiệu suất đáng kể so với một cuộc gọi trực tiếp - nhiều hơn rất nhiều so với trong một ngôn ngữ động như trăn. Điều này có thể hoặc có thể không quan trọng. Khi nghi ngờ, đo lường.

  • Khối rằng có được một phương pháp xử lý sẽ dẫn đến một con trỏ null nếu một phương pháp với tên này không được tìm thấy

  • Danh sách các đối số phải có chính xác số bên phải của đối số, với đúng loại . Bạn chịu trách nhiệm xác minh điều này ở một nơi khác. Điều này là khó hơn nó sẽ được trong một ngôn ngữ năng động, như thời gian chạy sẽ làm ít hơn rất nhiều (nếu có) loại cưỡng chế cho bạn.

  • method.invoke() có thể ném một loạt các ngoại lệ (IllegalAccessException, IllegalArgumentException, InvocationTargetException, v.v ...) mà ví dụ này bỏ qua. Bạn sẽ phải nắm bắt và xử lý các lỗi đó một cách thích hợp

  • nếu phương pháp được gọi là không công khai, bạn sẽ phải làm nhiều việc hơn thế này để gọi nó.

  • ví dụ này thậm chí không cố giải quyết trường hợp bạn có phương thức quá tải. Hai phương thức có tên là "theMethodIWant" với các danh sách đối số khác nhau sẽ yêu cầu một phương pháp khác để có được phương thức xử lý.

Tất cả trong tất cả, tôi khuyên bạn không nên sử dụng sự phản chiếu nếu có thể.

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