Java, 3 chấm trong tham số


822

3 chấm trong phương pháp sau có nghĩa là gì?

public void myMethod(String... strings){
    // method body
}

Câu trả lời:


987

Điều đó có nghĩa là không hoặc nhiều đối tượng String (hoặc một mảng của chúng) có thể được truyền dưới dạng (các) đối số cho phương thức đó.

Xem phần "Số lượng tranh luận tùy ý" tại đây: http://java.sun.com/docs/books/tutorial/java/javaOO/argument.html#varargs

Trong ví dụ của bạn, bạn có thể gọi nó là một trong những điều sau đây:

myMethod(); // Likely useless, but possible
myMethod("one", "two", "three");
myMethod("solo");
myMethod(new String[]{"a", "b", "c"});

Lưu ý quan trọng: Các) đối số được truyền theo cách này luôn luôn là một mảng - ngay cả khi chỉ có một. Hãy chắc chắn rằng bạn đối xử với nó theo cách đó trong cơ thể phương pháp.

Lưu ý quan trọng 2: Đối số nhận được ...phải là cuối cùng trong chữ ký phương thức. Vì vậy, myMethod(int i, String... strings)là được, nhưng myMethod(String... strings, int i)không ổn.

Cảm ơn Vash đã làm rõ trong bình luận của mình.


112
Bạn đã nhầm, trong đó "một hoặc nhiều", với các vararg chúng ta có thể chỉ định 0 hoặc nhiều hơn và đây phải luôn là tham số cuối cùng trong phương thức. Phương thức x (Chuỗi ... params) có thể được gọi là x () hoặc phương thức y (Chuỗi pram, Chuỗi ... params) có thể được gọi là y ("1")
Damian Leszczyński - Vash

2
Tôi ước nếu điều này sẽ làm việc quá. myMethod ("một", "hai", "ba", Chuỗi mới [] {"a", "b", "c" "});
2sb

2
Tại sao bạn được phép đưa ra các tham số phương thức 0? Điều đó rất có thể sẽ dẫn đến ArrayIndexOutOfBoundException. Bây giờ bạn luôn phải xem xét trường hợp đó.
Olle Söderström

11
Bởi vì chúng là tùy chọn. Tùy thuộc vào nhà phát triển đã quyết định sử dụng các đối số tùy chọn để triển khai đúng phương thức để xử lý có 0 hoặc nhiều trong số chúng.
kiswa

@ OlleSöderström Một lý do khác là tham số chính thức được chuyển đổi thành một mảng tại thời gian biên dịch. Điều đó có nghĩa là việc truyền vào một mảng mang lại kết quả tương tự. Vì độ dài của một mảng không được biết đến tại thời điểm biên dịch, nên việc hạn chế vượt qua ít nhất một phần tử có thể được bỏ qua bằng cách gọi đơn giản someMethod(new SomeType[] { }). Đó sẽ là một hack, phải không?
MC Hoàng đế

124

Tính năng đó được gọi là varargs và đó là một tính năng được giới thiệu trong Java 5. Điều đó có nghĩa là chức năng đó có thể nhận được nhiều Stringđối số:

myMethod("foo", "bar");
myMethod("foo", "bar", "baz");
myMethod(new String[]{"foo", "var", "baz"}); // you can even pass an array

Sau đó, bạn có thể sử dụng Stringvar như một mảng:

public void myMethod(String... strings){
    for(String whatever : strings){
        // do what ever you want
    }

    // the code above is is equivalent to
    for( int i = 0; i < strings.length; i++){
        // classical for. In this case you use strings[i]
    }
}

Câu trả lời này mượn rất nhiều từ của kiswa và Lorenzo ... và cũng từ nhận xét của Graphain.


13
Khi mã chạm mã byte, nó một mảng. Mọi thứ khác là cú pháp chỉ được hỗ trợ bởi trình biên dịch.
Donal Fellows

Câu trả lời này mượn rất nhiều từ kiswa's và Lorenzo nếu tôi đọc các chỉnh sửa chính xác.
Matt Mitchell

3
@Graph 'tốt hơn là chỉnh sửa câu trả lời của bạn và làm cho câu trả lời đúng hơn là để nó một mình. Và nếu một câu trả lời khác là nguồn gốc của sự cải thiện của bạn, thì nó sẽ đi. Ít nhất là anh ấy thành thật về điều đó (và tôi cho rằng anh ấy đã đưa ra những câu trả lời khác giúp anh ấy ... đúng không?).

1
@ Anh ấy sẽ thành thật sau khi tôi chỉ ra điều đó là đủ tốt. Cảm ơn đã tìm kiếm.
Matt Mitchell

23

Đó là Varargs :)

Các varargs viết tắt của các đối số có độ dài thay đổi là một tính năng cho phép phương thức chấp nhận số lượng đối số biến (không hoặc nhiều hơn). Với varargs, việc tạo ra các phương thức cần lấy một số lượng đối số khác nhau đã trở nên đơn giản. Tính năng của đối số biến đã được thêm vào trong Java 5.

Cú pháp của varargs

Một vararg được bảo mật bằng ba dấu chấm lửng (ba dấu chấm) sau kiểu dữ liệu, dạng chung của nó là

return_type method_name(data_type ... variableName){
}  

Cần cho varargs

Trước Java 5, trong trường hợp có nhu cầu về số lượng đối số thay đổi, có hai cách để xử lý nó

Nếu số lượng đối số tối đa, một phương thức có thể mất là nhỏ và đã biết, thì các phiên bản quá tải của phương thức có thể được tạo. Nếu số lượng đối số tối đa mà một phương thức có thể lấy là lớn hoặc / và không xác định thì cách tiếp cận là đặt các đối số đó trong một mảng và chuyển chúng đến một phương thức lấy mảng làm tham số. Hai cách tiếp cận này dễ bị lỗi - xây dựng một mảng các tham số mỗi lần và khó duy trì - vì việc thêm đối số mới có thể dẫn đến việc viết một phương thức quá tải mới.

Ưu điểm của varargs

Cung cấp một tùy chọn đơn giản hơn nhiều. Ít mã hơn vì không cần phải viết các phương thức quá tải.

Ví dụ về varargs

public class VarargsExample {
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 public static void main(String[] args) {
  VarargsExample vObj = new VarargsExample();
  // four args
  vObj.displayData("var", "args", "are", "passed");
  //three args
  vObj.displayData("Three", "args", "passed");
  // no-arg
  vObj.displayData();
 }
}
Output

Number of arguments passed 4
var 
args 
are 
passed 
Number of arguments passed 3
Three 
args 
passed 
Number of arguments passed 0

Có thể thấy từ chương trình có độ dài được sử dụng ở đây để tìm số lượng đối số được truyền cho phương thức. Có thể bởi vì các vararg được truyền hoàn toàn dưới dạng một mảng. Bất cứ đối số nào được truyền dưới dạng vararg đều được lưu trữ trong một mảng được gọi bằng tên được đặt cho varargs. Trong chương trình này tên mảng là giá trị. Cũng lưu ý rằng phương thức được gọi với số lượng đối số khác nhau, cuộc gọi đầu tiên với bốn đối số, sau đó là ba đối số và sau đó với đối số bằng không. Tất cả các cuộc gọi này được xử lý theo cùng một phương thức có các varargs.

Hạn chế với varargs

Có thể có các tham số khác với tham số varargs trong một phương thức, tuy nhiên trong trường hợp đó, tham số varargs phải là tham số cuối cùng được phương thức khai báo.

void displayValues(int a, int b, int  values) // OK
   void displayValues(int a, int b, int  values, int c) // compiler error

Một hạn chế khác với varargs là chỉ có một tham số varargs.

void displayValues(int a, int b, int  values, int  moreValues) // Compiler error

Phương thức quá tải varargs

Có thể quá tải một phương thức có tham số varargs. Phương pháp Varargs có thể bị quá tải bởi -

Các loại tham số vararg của nó có thể khác nhau. Bằng cách thêm các tham số khác. Ví dụ về phương thức nạp chồng varargs

public class OverloadingVarargsExp {
 // Method which has string vararg parameter
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 // Method which has int vararg parameter
 public void displayData(int ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 // Method with int vararg and one more string parameter
 public void displayData(String a, int ... values){
  System.out.println(" a " + a);
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 public static void main(String[] args) {
  OverloadingVarargsExp vObj = new OverloadingVarargsExp();
  // four string args
  vObj.displayData("var", "args", "are", "passed");

  // two int args
  vObj.displayData(10, 20);

  // One String param and two int args
  vObj.displayData("Test", 20, 30);
 }
}
Output

Number of arguments passed 4
var 
args 
are 
passed 

Number of arguments passed 2
10 
20

 a Test
Number of arguments passed 2
20 
30 

Sự đa dạng và quá tải mơ hồ

Trong một số trường hợp, cuộc gọi có thể mơ hồ trong khi chúng ta có phương thức varargs quá tải. Hãy xem một ví dụ

public class OverloadingVarargsExp {
 // Method which has string vararg parameter
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 // Method which has int vararg parameter
 public void displayData(int ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 public static void main(String[] args) {
  OverloadingVarargsExp vObj = new OverloadingVarargsExp();
  // four string args
  vObj.displayData("var", "args", "are", "passed");

  // two int args
  vObj.displayData(10, 20);

  // This call is ambiguous
  vObj.displayData();
 }
}

Trong chương trình này khi chúng ta thực hiện một cuộc gọi đến phương thức displayData () mà không có bất kỳ tham số nào, nó sẽ báo lỗi, bởi vì trình biên dịch không chắc chắn liệu cuộc gọi phương thức này là dành cho displayData(String ... values)haydisplayData(int ... values)

Tương tự như vậy nếu chúng ta có các phương thức quá tải trong đó một phương thức có một varargphương thức và một phương thức khác có một tham số và varargtham số cùng loại, thì chúng ta cũng có sự mơ hồ - Như Exp - displayData(int ... values)displayData(int a, int ... values)

Hai phương thức quá tải này sẽ luôn có sự mơ hồ.


15

Đây là cách Java để truyền varargs (đối số số biến).

Nếu bạn quen thuộc với C, điều này tương tự như ...cú pháp được sử dụng, printfhàm này:

int printf(const char * format, ...);

nhưng theo kiểu an toàn: mọi đối số phải tuân thủ loại đã chỉ định (trong mẫu của bạn, chúng phải là tất cả String).

Đây là một mẫu đơn giản về cách bạn có thể sử dụng varargs :

class VarargSample {

   public static void PrintMultipleStrings(String... strings) {
      for( String s : strings ) {
          System.out.println(s);
      }
   }

   public static void main(String[] args) {
      PrintMultipleStrings("Hello", "world");
   }
}

Đối ...số thực sự là một mảng, vì vậy bạn có thể truyền một String[]tham số.


11

Có thể cho rằng, đây là một ví dụ về đường cú pháp, vì nó được triển khai như một mảng dù sao (điều đó không có nghĩa là nó vô dụng) - Tôi thích truyền một mảng để giữ cho nó rõ ràng, và cũng khai báo các phương thức với các mảng có loại. Thay vào đó là một ý kiến ​​hơn là một câu trả lời.


5

Ngoài ra để làm sáng tỏ, điều quan trọng cần biết là các tham số var-arg được giới hạn ở một và bạn không thể có một vài thông số var-art. Ví dụ, điều này là không đúng mực:

public void myMethod(String... strings, int ... ints){
// method body
}


2

Một cách thực sự phổ biến để xem một ví dụ rõ ràng về việc sử dụng ba dấu chấm mà nó hiện diện trong một trong những phương pháp nổi tiếng nhất trong Android AsyncTask (ngày nay không được sử dụng quá nhiều vì RXJAVA, không đề cập đến các thành phần Kiến trúc của Google), bạn có thể tìm thấy hàng ngàn ví dụ tìm kiếm thuật ngữ này, và cách tốt nhất để hiểu và không bao giờ quên nữa ý nghĩa của ba dấu chấm là chúng diễn tả một ... nghi ngờ ... giống như trong ngôn ngữ chung. Cụ thể là không rõ số lượng tham số phải truyền, có thể là 0, có thể là 1 có thể nhiều hơn (một mảng) ...


1

String... giống như String[]

import java.lang.*;

public class MyClassTest {

    //public static void main(String... args) { 

    public static void main(String[] args) {
        for(String str: args) {
            System.out.println(str);
        }
    }
}

1
Nếu String...giống như String[], bạn không thể nói như vậy sao?
Scott Hunter

8
Về mặt kỹ thuật không đúng vì String[]yêu cầu một đối số (ít nhất là một mảng trống) trong khi String...không (xem câu trả lời ở trên).
Aurel

0

Thêm vào các câu trả lời được viết tốt khác, một lợi thế của varagrstôi thấy hữu ích là, khi tôi gọi một phương thức với mảng là một kiểu tham số, nó sẽ loại bỏ nỗi đau của việc tạo một mảng; thêm các yếu tố và sau đó gửi nó. Thay vào đó, tôi chỉ có thể gọi phương thức với nhiều giá trị như tôi muốn; từ không đến nhiều.


0
  • Nó có nghĩa là không hoặc nhiều tham số của cùng một loại dữ liệu.
  • Nó phải là tham số cuối cùng của hàm tạo hoặc hàm.
  • Chúng ta chỉ có thể có một trong các tham số loại này trong hàm tạo hoặc hàm tương ứng.

Ví dụ 1:

public class quest1 {

    public quest1(String... mynum) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1();

        quest1 q1=new quest1("hello");

    }
}

Ví dụ 2:

public class quest1 {

    public quest1(int... at) {
        System.out.println("yee haa");
    }

    public quest1(String... at) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1("value");

        quest1 q1=new quest1(1);

    }

    public void name(String ... s) {

    }
}

đầu ra:

yee haa

yee haa


-1

Cú pháp: (Dấu ba chấm ...) -> Có nghĩa là chúng ta có thể thêm 0 hoặc nhiều đối tượng vượt qua trong một đối số hoặc truyền một mảng của đối tượng loại.

public static void main(String[] args){}
public static void main(String... args){}

Định nghĩa: 1) Đối số ... chỉ là một tham chiếu đến một mảng các Đối tượng.

2) ('Chuỗi []' hoặc Chuỗi ...) Nó có thể xử lý bất kỳ số lượng đối tượng chuỗi nào. Trong nội bộ, nó sử dụng một mảng của đối tượng loại tham chiếu.

i.e. Suppose we pass an Object array to the ... argument - will the resultant argument value be a two-dimensional array - because an Object[] is itself an Object:

3) Nếu bạn muốn gọi phương thức bằng một đối số duy nhất và nó xảy ra là một mảng, bạn phải gói nó một cách rõ ràng

another. method(new Object[]{array}); 
OR 
method((Object)array), which will auto-wrap.

Ứng dụng: Nó được sử dụng chủ yếu khi số lượng đối số là động (số lượng đối số biết trong thời gian chạy) và ghi đè. Quy tắc chung - Trong phương thức chúng ta có thể vượt qua bất kỳ loại và bất kỳ số lượng đối số. Chúng tôi không thể thêm đối số (...) trước bất kỳ đối số cụ thể nào. I E

void m1(String ..., String s) this is a wrong approach give syntax error.
void m1(String s, String ...); This is a right approach. Must always give last order prefernces.   
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.