JavaRush /Blog Java /Random-VI /Các biến thể Java

Các biến thể Java

Xuất bản trong nhóm
Hôm nay chúng ta sẽ thảo luận về một thứ như varargs trong Java. Varargs - hay Variable Arguments - là công nghệ cho phép bạn tạo các phương thức với số lượng đối số tùy ý. Trong bài viết này, chúng ta sẽ tìm hiểu cách tạo các phương thức như vậy, thảo luận lý do tại sao cần có varargs và khi nào thì sử dụng chúng là tốt nhất.

Varargs là gì?

Varargs là các đối số có độ dài thay đổi: một tính năng xuất hiện trong JDK5. Varargs cho phép chúng ta tạo các phương thức với số lượng đối số tùy ý. Nhìn chung, trước đây có thể tạo ra những phương pháp như vậy. Đúng, làm điều này không thuận tiện lắm. Hãy đưa ra một ví dụ. Giả sử chúng ta cần viết một phương thức lấy một số lượng đối số nguyên tùy ý và cộng chúng lại với nhau. Các biến thể Java - 1Chúng tôi có hai lựa chọn. Tùy chọn 1 - quá tải:
class Calculator {
    int sum(int a, int b){...};
    int sum(int a, int b, int c){...};
    int sum(int a, int b, int c, int d){...};
    int sum(int a, int b, int c, int d, int e){...};
}
Nhưng có hai vấn đề với tình trạng quá tải. Thứ nhất, không phải lúc nào cũng rõ ràng khi nào thì nên dừng lại, thứ hai là nó cồng kềnh. Mảng tốt hơn. Tùy chọn 2 - mảng:
class Calculator {
    int sum(int[] numbers){...};
}
Với một mảng, nó không còn cồng kềnh nữa và mảng dường như chẳng có gì... cho đến lúc gọi phương thức:
public static void main(String... sss) {
    Calculator calculator = new Calculator();

    int[] arguments = new int[7];
    arguments[0] = 1;
    arguments[1] = 10;
    arguments[2] = 123;
    arguments[3] = 234;
    arguments[4] = 6234;
    arguments[5] = 12;
    arguments[6] = 8;

    int sum = calculator.sum(arguments);
}
Chúng tôi đồng ý, tất nhiên bạn có thể viết mọi thứ ngắn gọn hơn. Nhưng trước tiên, tôi vẫn muốn chứng minh sự bất tiện của việc sử dụng mảng làm đối số có độ dài thay đổi và thứ hai, ngay cả khi chúng ta viết nó như thế này:
int[] arguments = {1,10,123,234,6234,12,8};
int sum = calculator.sum(arguments);
Sau đó, chúng tôi vẫn sẽ không loại bỏ được số lượng mã quá lớn. Tuy nhiên, với việc phát hành Java 5, tính năng Varargs xuất hiện để giải quyết những vấn đề này. Nó cho phép truyền một số lượng đối số tùy ý cho các phương thức. Nó trông giống như thế này:
public class Calculator {
    public static void main(String... sss) {
        Calculator calculator = new Calculator();
        int sum = calculator.sum(1,10,123,234,6234,12,8);
    }
    int sum(int... numbers){
       return Arrays.stream(numbers).sum();
    }
}
Vì vậy, hãy tóm tắt. Varargs là các đối số có độ dài thay đổi, một tính năng xuất hiện cùng với bản phát hành Java 5. Tiếp theo, chúng ta sẽ xem xét kỹ hơn một số quy tắc để làm việc với Varargs.

5 quy tắc của varargs

Quy tắc 1. Đối số Vararg (hoặc đối số có độ dài thay đổi/tùy ý) được biểu thị bằng dấu chấm lửng như sau:
String... words
Integer... numbers
Person... people
Cat... cats
Quy tắc 2. Một đối số có độ dài tùy ý chỉ có thể được chỉ định làm đối số cho một số phương thức:
void print(String... words)
int sum(Integer... numbers)
void save(Person... people)
void feed(Cat... cats)
Quy tắc 3. Mỗi đối số có độ dài thay đổi như vậy trong nội dung phương thức là một mảng:
void print(String... words){
    for (int i = 0; i < words.length; i++) {
        System.out.println(words[i]);
    }
}
Quy tắc 4. Đối số Vararg phải là đối số cuối cùng trong danh sách đối số phương thức:
void print(String... words, String anotherWord) // - Так нельзя!
void print(String... words, int someNumber) // - Так нельзя!

void print(String anotherWord, String... words) // - Так можно
void print(int someNumber, String... words) // - Так можно
Quy tắc 5: Mặc dù các biến thể là mảng, nhưng khi gọi một phương thức có các đối số có độ dài thay đổi, không cần thiết phải tạo một mảng. Chỉ cần liệt kê các đối số cần thiết được phân tách bằng dấu phẩy là đủ và thậm chí là mong muốn:
public class Main {
    public static void main(String... sss) {
        print("How","же","прекрасно","изучать","Java");
    }

    static void print(String... words){
        for (int i = 0; i < words.length; i++) {
            System.out.println(words[i]);
        }
    }
}

Các ví dụ của varargs

Trong ví dụ bên dưới, chúng ta sẽ viết một phương thức lấy các biến số bao gồm các số nguyên và hiển thị số phần tử được truyền cũng như tổng của chúng. Hãy chuyển cả một mảng và một chuỗi số nguyên cho phương thức này (cả hai tùy chọn đều hợp lệ):
public static void main(String... sss) {
    int[] a = new int[100];
    for (int i = 0; i < a.length; i++) {
        a[i] = i;
    }

    sum(a);
    sum(1,2,3,4,5,6,7,8,9,10);
}

static void sum(int... numbers){
    final int length = numbers.length;
    final int sum = Arrays.stream(numbers).sum();
    final String lineSeparator = System.lineSeparator();

    System.out.printf("Кол-во элементов для сложения - %d, сумма - %d%s", length, sum, lineSeparator);
}
Sau khi chạy chương trình sẽ xuất ra:

Кол-во элементов для сложения - 100, сумма - 4950 
Кол-во элементов для сложения - 10, сумма - 55 
Điều đáng nói là phương pháp này System.out.printfcũng chấp nhận các biến thể. Nếu chúng ta nhìn vào mã của phương thức này, chúng ta sẽ thấy điều này:
public PrintStream printf(String format, Object ... args) {
    return format(format, args);
}
Một phương pháp khác được sử dụng rộng rãi chấp nhận các biến thể là String.format. Mã của nó được hiển thị dưới đây:
public static String format(String format, Object... args) {
    return new Formatter().format(format, args).toString();
}

Khi nào nên sử dụng varargs?

Câu trả lời cho câu hỏi này phụ thuộc vào người hỏi. Nếu một khách hàng của một số API có các phương thức có varargs hỏi một câu hỏi tương tự, thì câu trả lời sẽ là “sử dụng các phương thức như vậy thường xuyên nhất có thể”. Đối với ứng dụng khách mã, varargs giúp cuộc sống dễ dàng hơn rất nhiều bằng cách làm cho mã dễ viết và dễ đọc hơn. Tuy nhiên, nếu câu hỏi này được đặt ra bởi một nhà phát triển API đang thắc mắc về tần suất bạn nên tạo các phương thức với varargs, thì câu trả lời sẽ là “bạn không nên sử dụng varargs thường xuyên”. Varargs chỉ nên được sử dụng khi lợi ích của việc sử dụng nó là rõ ràng. Bạn cũng nên tránh nạp chồng các phương thức bằng varargs, vì điều này sẽ khiến các máy khách trong mã của bạn khó hiểu được phương thức nạp chồng nào thực sự được gọi.

Phần kết luận

Như vậy, chúng ta đã đề cập đến một chủ đề khác, các biến thể trong Java. Chúng tôi đã tìm ra nó là gì. Chúng tôi đã mô tả các quy tắc sử dụng varargs. Chúng tôi đã xem xét các ví dụ về các phương thức với các đối số có độ dài tùy ý và cũng thảo luận khi nào nên sử dụng các biến thể thì tốt hơn và khi nào thì tốt hơn là không nên sử dụng chúng. Là bài tập về nhà, bạn có thể thực hiện các phương pháp sau:
  • Viết voidmột phương thức lấy một chuỗi các số nguyên và trả về giá trị trung bình số học của chúng.
  • Viết voidmột phương thức lấy một chuỗi các chuỗi và in ra từ dài nhất.
  • Viết một phương thức trả về booleanvà lấy một biến có loại làm đối số đầu tiên Stringvà một chuỗi booleancó độ dài thay đổi làm đối số tiếp theo.
    Các giá trị có thể có StringAND, OR, XOR. Nếu đối số đầu tiên có một số giá trị khác thì phương thức đó phải đưa ra một ngoại lệ IllegalArgumentException.
    Phương thức phải thực hiện một thao tác logic (được chỉ định trong đối số đầu tiên) trên mỗi phần tử của đối số varargs và trả về kết quả tính toán.
Ví dụ đối số và kết quả:
  • "VÀ", đúng, đúng, sai - sẽ trả về sai
  • "HOẶC", sai, đúng, sai, sai - sẽ trả về đúng
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION