trả về một đối tượng Void


113

Cách chính xác để trả về một Voidkiểu, khi nó không phải là kiểu nguyên thủy? Ví dụ. Tôi hiện đang sử dụng null như bên dưới.

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something
        return null;
    }
}

1
Tôi đang viết một thông dịch viên cho một định dạng tập tin, sử dụng các mô hình thông dịch viên, nhưng một số biểu thức không có giá trị trả lại
Robert

2
Không có cách nào để khởi tạo loại Void, vì vậy nếu bạn thực sự phải trả lại thứ gì đó thuộc loại đó, null là lựa chọn duy nhất của bạn. Tuy nhiên, bạn có thể không cần giá trị trả về cho bất kỳ thứ gì, vì vậy null sẽ ổn.
Jorn

yeah, đó là logic của tôi quá - chỉ tự hỏi nếu có một cách ngữ nghĩa hơn
Robert

1
Tôi sẽ viết mã nó giống như ví dụ của bạn. Đó là một cách tiếp cận tốt.
David Roussel

Câu trả lời:


134

Lớp Void là một lớp giữ chỗ không thể tin cậy để giữ một tham chiếu đến đối tượng Lớp đại diện cho từ khóa void trong Java.

Vì vậy, bất kỳ điều nào sau đây sẽ đủ:

  • tham số hóa với Objectvà trả về new Object()hoặcnull
  • tham số hóa với Voidvà trả vềnull
  • tham số hóa với NullObjectcủa bạn

Bạn không thể thực hiện phương thức này voidvà bất kỳ thứ gì khác sẽ trả về một thứ gì đó . Vì điều gì đó bị bỏ qua, bạn có thể trả lại bất cứ thứ gì.


2
thì cách chung chung đúng để đạt được kiểu trả về của khoảng trống là gì?
Robert

1
Nếu bạn muốn trả về null as void, bạn cần phải bỏ nó trong một số trường hợp: (Void) null
Patrick Favre

return (Void)null;
Alex R

(Void) null có thể được phân biệt với null theo bất kỳ cách nào không?
Orangle

13

Java 8 đã giới thiệu một lớp mới Optional<T>, có thể được sử dụng trong những trường hợp như vậy. Để sử dụng nó, bạn sẽ sửa đổi mã của mình một chút như sau:

interface B<E>{ Optional<E> method(); }

class A implements B<Void>{

    public Optional<Void> method(){
        // do something
        return Optional.empty();
    }
}

Điều này cho phép bạn đảm bảo rằng bạn luôn nhận được giá trị trả về không phải null từ phương thức của mình, ngay cả khi không có bất kỳ thứ gì để trả về. Điều này đặc biệt mạnh mẽ khi được sử dụng cùng với các công cụ phát hiện khi nào nullcó thể hoặc không thể trả lại, ví dụ như Eclipse @NonNull@Nullablecác chú thích.


5
Ý kiến ​​của tôi là điều này đang đi sai hướng. Tốt hơn là trả về một kiểu ràng buộc hơn nhiều để truyền tải ý nghĩa rõ ràng hơn nhiều. Có một cái gì đó trả về một Optional<Void>là không cần thiết vì cùng một lý do mà bạn đưa ra, bạn luôn nhận được một Optional<Void>cái trống và vì vậy tất cả các phương thức khác là vô nghĩa. Điều này ngược lại với lý do tại sao nên sử dụng giá trị tùy chọn. Bạn sử dụng nó vì nó có thể có hoặc không có giá trị. Ngoài ra, trình biên dịch không thể thực thi mà method()thực thi nó một cách chính xác. Điều này sẽ thất bại trong thời gian chạy: return Optional.of(null).
steinybot

3

Nếu bạn không cần bất cứ thứ gì như loại của mình, bạn có thể sử dụng void. Điều này có thể được sử dụng để triển khai các chức năng hoặc hành động. Sau đó, bạn có thể làm điều gì đó như sau:

interface Action<T> {
    public T execute();
}

abstract class VoidAction implements Action<Void> {
    public Void execute() {
        executeInternal();
        return null;
    }

    abstract void executeInternal();
}

Hoặc bạn có thể bỏ qua lớp trừu tượng và thực hiện trả về null trong mọi hành động mà bản thân không yêu cầu giá trị trả về.

Sau đó, bạn có thể sử dụng những hành động như sau:

Đưa ra một phương pháp

private static <T> T executeAction(Action<T> action) {
    return action.execute();
}

bạn có thể gọi nó như thế

String result = executeAction(new Action<String>() {
    @Override
    public String execute() {
        //code here
        return "Return me!";
    }
});

hoặc, đối với hành động void (lưu ý rằng bạn không gán kết quả cho bất kỳ thứ gì)

executeAction(new VoidAction() {
    @Override
    public void executeInternal() {
        //code here
    }
});

2
điều này khác với những gì tôi đã có? nó vẫn chỉ trả về null, như tôi đã đề xuất
Robert

Tại sao bạn phải trả lại bất cứ thứ gì khác? Điểm tôi đang cố gắng đưa ra là bạn không cần giá trị trả về, vì vậy bạn trả về là gì không quan trọng. Tôi đã cố gắng làm rõ điều đó với bản chỉnh sửa của mình.
Jorn

1

Chỉ vì lợi ích của nó, tất nhiên có khả năng tạo Voidcá thể bằng cách sử dụng phản chiếu:

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something

        try {
            Constructor<Void> voidConstructor = Void.class.getDeclaredConstructor();
            voidConstructor.setAccessible(true);
            return voidConstructor.newInstance();
        } catch (Exception ex) {
            // Rethrow, or return null, or whatever.
        }
    }
}

Bạn có thể sẽ không làm điều đó trong sản xuất.


0

Không có kiểu chung chung nào cho trình biên dịch biết rằng một phương thức không trả về kết quả nào.

Tôi tin rằng quy ước là sử dụng Đối tượng khi kế thừa dưới dạng tham số kiểu

HOẶC LÀ

Tuyên truyền tham số kiểu lên và sau đó cho phép người dùng trong lớp của bạn khởi tạo bằng Đối tượng và gán đối tượng cho một biến được nhập bằng ký tự đại diện kiểu ?:

interface B<E>{ E method(); }

class A<T> implements B<T>{

    public T method(){
        // do something
        return null;
    }
}

A<?> a = new A<Object>();

1
đây có phải là quy ước để đặt kiểu trả về là void với generics - nó không có vẻ gì là vô hiệu đối với tôi?
Robert

Tôi tin rằng đây là con đường để đi. Bất kỳ người dùng nào của lớp A<?>sẽ không thể sử dụng bất kỳ giá trị trả về nào của method().
Christopher Oezbek
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.