ZetCode

Java Void 类

最后修改时间:2025 年 4 月 13 日

java.lang.Void 类是一个占位符类,代表 Java 中的 void 关键字。它是一个不可实例化的类,用作 void 返回类型的引用。 虽然不常用,但在泛型和反射中具有特定的应用。

Void 类是 final 的,不能被实例化。它只包含一个静态字段 TYPE,它保存表示 void 关键字的 Class 对象。 当需要在泛型上下文中表示 void 类型时,主要使用此类。

Void 类定义

Void 类是 java.lang 包中的一个简单的 final 类。它的定义很简单,只包含 TYPE 字段和一个私有构造函数以防止实例化。 以下是它在 Java API 中的定义方式

public final class Void {
    public static final Class<Void> TYPE = Class.getPrimitiveClass("void");
    
    private Void() {}
}

当需要检查方法是否返回 void 时,TYPE 字段在反射场景中特别有用。私有构造函数确保无法创建 Void 的实例,因为拥有 void 值没有意义。

Void 的基本用法

Void 最常见的用途是在泛型上下文中,在这些上下文中需要指定一个类型参数,但实际上不需要返回值。 这通常发生在 Callable 或 Future 中,当操作不返回任何内容时。

Main.java
package com.zetcode;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        
        Callable<Void> task = new Callable<Void>() {
            @Override
            public Void call() {
                System.out.println("Performing task that returns nothing");
                return null; // Must return null for Void
            }
        };
        
        Future<Void> future = executor.submit(task);
        future.get(); // Waits for task completion
        executor.shutdown();
    }
}

在此示例中,当我们需要一个不返回任何值的任务时,我们将 Void 用作 Callable 的类型参数。 由于 Void 无法实例化,因此 call 方法必须返回 null。 这种模式在并发编程中很常见。

函数式接口中的 Void

Void 可以与 Runnable 等函数式接口或不返回值自定义接口一起使用。 当需要在处理不产生结果的操作时保持类型安全时,这特别有用。

Main.java
package com.zetcode;

@FunctionalInterface
interface VoidFunction {
    void execute();
}

public class Main {

    public static void main(String[] args) {
        VoidFunction task = () -> System.out.println("Executing void function");
        task.execute();
        
        // Using Void in a generic context
        processVoidOperation(() -> System.out.println("Processed void operation"));
    }
    
    public static void processVoidOperation(VoidFunction operation) {
        System.out.println("Before operation");
        operation.execute();
        System.out.println("After operation");
    }
}

此示例演示了如何概念性地将 Void 与函数式接口一起使用。 VoidFunction 接口表示不返回任何内容的操作。 虽然我们没有在此处直接使用 Void 类,但它是相同的概念 - 不返回值的操作。

反射中的 Void

Void.TYPE 字段主要用于反射中,以识别返回 void 的方法。 当需要在运行时动态检查方法返回类型时,这很有用。

Main.java
package com.zetcode;

import java.lang.reflect.Method;

public class Main {
    public void doSomething() {
        System.out.println("Doing something");
    }
    
    public int calculate() {
        return 42;
    }
    
    public static void main(String[] args) throws Exception {
        Method doSomethingMethod = Main.class.getMethod("doSomething");
        Method calculateMethod = Main.class.getMethod("calculate");
        
        System.out.println("doSomething returns void: " + 
            (doSomethingMethod.getReturnType() == Void.TYPE));
        System.out.println("calculate returns void: " + 
            (calculateMethod.getReturnType() == Void.TYPE));
    }
}

在此反射示例中,我们通过将方法的返回类型与 Void.TYPE 进行比较来检查方法是否返回 void。 doSomething 方法返回 void,而 calculate 返回 int。 这种技术对于需要根据返回类型以不同方式处理方法的框架很有用。

CompletableFuture 中的 Void

当链接不返回值的异步操作时,Void 通常与 CompletableFuture 一起使用。 这提供了类型安全,同时表明不期望返回值。

Main.java
package com.zetcode;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("Async task running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        future.thenRun(() -> System.out.println("Task completed"));
        future.get(); // Wait for completion
    }
}

此示例显示了带有 Void 类型的 CompletableFuturerunAsync 方法接受一个 Runnable,它返回 void,因此我们使用 Void 作为类型参数。 thenRun 方法也使用这种模式来处理不返回值的延续任务。

泛型类中的 Void

当需要表示缺少返回类型时,可以将 Void 用作泛型类中的类型参数。 这对于创建可以处理返回值和非返回值操作的灵活 API 很有用。

Main.java
package com.zetcode;

class ResultProcessor<T> {
    private T result;
    
    public void process(Runnable operation) {
        operation.run();
        this.result = null;
    }
    
    public T getResult() {
        return result;
    }
}

public class Main {

    public static void main(String[] args) {
        ResultProcessor<Void> processor = new ResultProcessor<>();
        processor.process(() -> System.out.println("Processing data"));
        
        System.out.println("Result is: " + processor.getResult());
    }
}

在此示例中,我们创建了一个可以处理任何类型的泛型 ResultProcessor,包括 Void。 当使用 Void 作为类型参数时,我们表明不会返回有意义的结果。 在这种情况下,getResult 方法返回 null。

Void vs. Void vs. void

重要的是要了解 Void 类、Void 类型和 void 关键字之间的区别。 每个在 Java 类型系统中都有不同的用途。

Main.java
package com.zetcode;

import java.lang.reflect.Type;
import java.util.List;

public class Main {
    // Method returning primitive void
    public void primitiveVoidMethod() {}
    
    // Method returning Void (boxed void)
    public Void boxedVoidMethod() {
        return null; // Must return null
    }
    
    public static void main(String[] args) throws NoSuchMethodException {
        System.out.println("void.class: " + void.class);
        System.out.println("Void.TYPE: " + Void.TYPE);
        System.out.println("Void.class: " + Void.class);
        
        System.out.println("Are they equal? " + (void.class == Void.TYPE));
        
        Type returnType = Main.class
            .getMethod("boxedVoidMethod")
            .getGenericReturnType();
        System.out.println("Generic return type: " + returnType);
    }
}

此示例演示了 void、Void.TYPE 和 Void.class 之间的区别。 原始 void 和 Void.TYPE 代表相同的概念,但在 Java 的类型系统中是不同的实体。 Void.class 是 Void 包装类的 Class 对象,而 void.class 是原始 void 关键字的 Class 对象。

方法引用中的 Void

当引用的方法返回 void 时,方法引用可以与泛型上下文中的 Void 一起使用。 这提供了一种类型安全的方式来处理函数式编程中返回 void 的方法。

Main.java
package com.zetcode;

import java.util.concurrent.Callable;

public class Main {
    public static void printMessage() {
        System.out.println("Hello from void method");
    }
    
    public static void main(String[] args) throws Exception {
        // Using method reference with Callable<Void>
        Callable<Void> task = Main::printMessage;
        task.call();
        
        // Using lambda expression
        Callable<Void> anotherTask = () -> {
            System.out.println("Another void operation");
            return null;
        };
        anotherTask.call();
    }
}

此示例演示了如何在泛型上下文中使用带有 Void 的方法引用。 printMessage 方法返回 void,但我们可以将其引用为 Callable<Void>。 lambda 表达式版本使 null 返回显式,这对于返回 Void 的 callable 是必需的。

来源

Java Void 类文档

在本教程中,我们探讨了 Java Void 类及其各种用例。 虽然 Void 在日常编程中不常用,但在需要以类型安全的方式表示缺少返回值时,它在泛型、反射和并发编程中发挥着重要作用。

作者

我叫 Jan Bodnar,是一位敬业的程序员,在该领域拥有多年的经验。 我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和 8 本电子书。 凭借超过 8 年的教学经验,我致力于分享我的知识并帮助其他人掌握编程概念。

列出所有Java教程