简体   繁体   English

如何使方法采用空值?

[英]How can I make a method take a null value?

If you have two overloaded methods like so: 如果您有两个这样的重载方法:

public void methodName(File file){}
public void methodName(String string){}

If you try to call methodName with null you will get an error saying that it's ambiguous which is understandable because it doesn't know which method to do. 如果尝试使用null调用methodName ,则会收到一条错误消息,指出它模棱两可,这是可以理解的,因为它不知道该使用哪种方法。

I know that you can just cast the null: methodName((String) null) but how can I create a method specifically to handle the situations where you call methodName(null) ? 我知道您可以methodName((String) null)为null: methodName((String) null)但是如何创建专门用于处理调用methodName(null)的情况的方法?

Something like this: 像这样:

public void methodName(null null){}

How can I make a method which must take a null? 如何制作必须为null的方法?

Just make a method without any parameters. 只需创建一个没有任何参数的方法即可。

public void methodName(){}

Requiring a method that must take a null is the same as requiring a method that always takes 5 or a method that always takes "foo". 要求must take a null的方法与要求始终为5的方法或始终为“ foo”的方法相同。 If the passed argument should always contain the same value, there's no need for that argument at all. 如果传递的参数应始终包含相同的值,则根本不需要该参数。

And if you were asking for a method that will be chosen whenever the passed argument is null, regardless of its type (ie both method calls below would call the same overloaded method), 而且,如果您要求的是在传递的参数为null时无论其类型如何都将选择的方法(即,下面的两个方法调用都将调用相同的重载方法),

File f = null;
String s = null;
methodName (f);
methodName (s);

that's not possible, since the overloaded method to be used must be chosen in compile time using the compile time types of the arguments. 这是不可能的,因为必须在编译时使用参数的编译时类型选择要使用的重载方法。 At compile time the compiler can't know that the passed variable with contain null when the method is executed. 在执行该方法时,编译器在编译时无法知道所传递的变量是否包含null。

There is a type which is often used to represent a null and this is Void where the only valid value is null . 有一种类型通常用于表示null ,这是Void ,其中唯一有效的值是null

You can write 你可以写

void methodName(Void v);

Where it is typically used is for generic return types like. 通常将其用于通用返回类型,例如。

Future<Void> future = executorService.submit(new Callable<Void>() {
    public Void call() throws IOException {
        try(FileInputStream fis = new FileInputStream(filename)) {
            doSomething(fis);
        }
        return null;
    }
});

// later
future.get();

You might wonder, why not use Runnable as we would not need return null; 您可能想知道,为什么不使用Runnable因为我们不需要return null; , however Runnable cannot throw a checked exception, so we much use Callable if we expect to capture the IOException in the future object. ,但是Runnable不能引发已检查的异常,因此如果我们希望在future对象中捕获IOException,则可以大量使用Callable。

In Java 8, you can use lambdas but the compiler will still expect to return a null if you throw a checked exception as it works out you have to be using Callable 在Java 8中,您可以使用lambdas,但如果抛出已检查的异常,编译器仍然希望返回null,因为它必须使用Callable

Future<Void> future = executorService.submit(() -> {
        try(FileInputStream fis = new FileInputStream(filename)) {
            doSomething(fis);
        }
        return null;
    });

An argument passed can always always be null if it is an Object . 如果传递的参数Object ,则始终可以始终为null。 It is when you try running a method on a null reference that you get a null pointer exception. 当您尝试在null引用上运行方法时,会得到null指针异常。

So, public void methodName(File file){} could be called as methodName(null) without an exception. 因此, public void methodName(File file){}可以毫无例外地称为methodName(null)

However, 然而,

public void methodName(File file) {
    file.delete();
}

will result in a null pointer exception if null is passed. 如果传递null,将导致null指针异常。

You can't write a method that specifically takes null . 您不能编写专门采用null的方法。 You'd have to do something like this: 您必须执行以下操作:

methodName(File file) {
   if(file == null) {
      someOtherMethod();
   }
   else {
      // other stuff
   }
}

But it would be more common to just have methodName(File) handle null , and document what it does with null . 但是,仅使methodName(File)处理null并记录其对null所做的操作会更常见。 If you have it call another method and methodName(File) and someOtherMethod() are not both final, you should document the internal call. 如果您有调用另一个方法,而methodName(File)someOtherMethod()都不都是最终的,则应记录内部调用。

You cannot do this. 你不可以做这个。 Remember that you may have implicit null . 请记住,您可能具有隐式null For example: 例如:

File file = null;
methodName(file);

However, Java compiler must link the call to the specific method signature, so it should know in compile time whether the null was passed. 但是,Java编译器必须将调用链接到特定的方法签名,因此它应该在编译时知道是否传递了null

On the other hand why stick to null ? 另一方面,为什么要坚持为null Nothing stops you to define the special type: 没有什么可以阻止您定义特殊类型的:

enum Null { NULL }
public void methodName(File file){}
public void methodName(String string){}
public void methodName(Null n) {}

methodName(Null.NULL); // or methodName(NULL); with import static

As you've seen, the compiler can't resolve two methods that take different kinds of objects when you pass null . 如您所见,当传递null时,编译器无法解析采用不同类型对象的两个方法。

The only way around this is either typecast, like you have done, or to have a method that takes a generic Object type and attempts to downcast: 解决此问题的唯一方法是像您一样进行类型转换,或者采用一种采用通用Object类型并尝试向下转换的方法:

public void methodName( Object object ) {
    if ( object == null ) {
        // do something with null
    } else if ( object instanceof File ) {
        // do something with ((File)object)
    } else {
        // do something else
    }
}

Writing code that looks like this tends to be viewed as smelly, and for good reason. 编写看起来像这样的代码通常被认为是臭的,这是有充分理由的。 It gets complicated quickly, is difficult to maintain, etc. Your best bet is to typecast or to change your method signatures so that you (and the compiler) always know which function should be called to handle a specific null object. 它很快就会变得复杂,难以维护等。您最好的选择是进行类型转换或更改方法签名,以便您(和编译器)始终知道应调用哪个函数来处理特定的null对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM