优雅地检查 Java 中的两个参数,要么不为 null,要么都为 null
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34586109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check two arguments in Java, either both not null or both null elegantly
提问by zhuguowei
I used spring boot to develop a shell project used to send email, e.g.
我用spring boot开发了一个用来发邮件的shell项目,例如
sendmail -from [email protected] -password foobar -subject "hello world" -to [email protected]
If the from
and password
arguments are missing, I use a default sender and password, e.g. [email protected]
and 123456
.
如果缺少from
andpassword
参数,我使用默认的发件人和密码,例如[email protected]
and 123456
。
So if the user passes the from
argument they must also pass the password
argument and vice versa. That is to say, either both are non-null, or both are null.
因此,如果用户传递from
参数,他们也必须传递password
参数,反之亦然。也就是说,要么两者都非空,要么都为空。
How do I check this elegantly?
我如何优雅地检查这个?
Now my way is
现在我的方法是
if ((from != null && password == null) || (from == null && password != null)) {
throw new RuntimeException("from and password either both exist or both not exist");
}
采纳答案by coolguy
There is a way using the ^
(XOR) operator:
有一种使用^
( XOR) 运算符的方法:
if (from == null ^ password == null) {
// Use RuntimeException if you need to
throw new IllegalArgumentException("message");
}
The if
condition will be true if only one variable is null.
该if
要是只有一个变量是空的条件将是真实的。
But I think usually it's better to use two if
conditions with different exception messages. You can't define what went wrong using a single condition.
但我认为通常最好使用if
具有不同异常消息的两个条件。您无法使用单个条件来定义出了什么问题。
if ((from == null) && (password != null)) {
throw new IllegalArgumentException("If from is null, password must be null");
}
if ((from != null) && (password == null)) {
throw new IllegalArgumentException("If from is not null, password must not be null");
}
It is more readable and is much easier to understand, and it only takes a little extra typing.
它更具可读性,更容易理解,并且只需要额外输入一点。
回答by Jon Skeet
Well, it sounds like you're trying to check whether the "nullity" condition of the two is the same or not. You could use:
好吧,听起来您正在尝试检查两者的“无效”条件是否相同。你可以使用:
if ((from == null) != (password == null))
{
...
}
Or make it more explicit with helper variables:
或者使用辅助变量使其更加明确:
boolean gotFrom = from != null;
boolean gotPassword = password != null;
if (gotFrom != gotPassword)
{
...
}
回答by JordiVilaplana
As I see your intentions, there is no need to always check both exclusive nullities but to check if password
is null if and only if from
is not null. You can ignore the given password
argument and use your own default if from
is null.
正如我看到你的意图,没有必要总是检查两个排他性无效,而是password
当且仅当from
不为空时才检查是否为空。password
如果from
为空,您可以忽略给定的参数并使用您自己的默认值。
Written in pseudo must be like this:
写成伪必须是这样的:
if (from == null) { // form is null, ignore given password here
// use your own defaults
} else if (password == null) { // form is given but password is not
// throw exception
} else { // both arguments are given
// use given arguments
}
回答by Traubenfuchs
Put that functionality in a 2 argument method with the signature:
将该功能放在带有签名的 2 参数方法中:
void assertBothNullOrBothNotNull(Object a, Object b) throws RuntimeException
This saves space in the actual method you are interested in and makes it more readable. There is nothing wrong with slightly verbose method names and there is nothing wrong with very short methods.
这可以节省您感兴趣的实际方法中的空间并使其更具可读性。稍微冗长的方法名称没有错,非常短的方法也没有错。
回答by Stig Hemmer
Personally, I prefer readable to elegant.
就个人而言,我更喜欢可读而不是优雅。
if (from != null && password == null) {
throw new RuntimeException("-from given without -password");
}
if (from == null && password != null) {
throw new RuntimeException("-password given without -from");
}
回答by matt
I think a correct way to handle this is to consider three situations: both 'from' and 'password' are provided, neither are provided, a mix of the two are provided.
我认为处理这个问题的正确方法是考虑三种情况:提供“from”和“password”,都没有提供,提供两者的混合。
if(from != null && password != null){
//use the provided values
} else if(from == null && password == null){
//both values are null use the default values
} else{
//throw an exception because the input is not correct.
}
It sounds like the original question wants to break the flow if it is incorrect input, but then they will have to repeat some of the logic later. Perhaps a good throw statement might be:
听起来如果输入不正确,原始问题想要中断流程,但随后他们将不得不重复一些逻辑。也许一个好的 throw 语句可能是:
throw new IllegalArgumentException("form of " + form +
" cannot be used with a "
+ (password==null?"null":"not null") +
" password. Either provide a value for both, or no value for both"
);
回答by x4u
I would like to suggest another alternative which is how I would actually write this piece of code:
我想建议另一种选择,这就是我实际编写这段代码的方式:
if( from != null )
{
if( password == null )
error( "password required for " + from );
}
else
{
if( password != null )
warn( "the given password will not be used" );
}
To me this seems to be the most natural way to express this condition which makes it easy to understand for somebody who might have to read it in the future. It also allows you to give more helpful diagnostic messages and treat the unnecessary password as less serious and it makes it easy to modify which is rather likely for such a condition. I.e. you may find out that giving a password as a command line argument is not the best idea and may want allow reading the password from standard input optionally if the argument is missing. Or you may want to silently ignore the superfluous password argument. Changes like these would not require you to rewrite the whole thing.
对我来说,这似乎是表达这种情况的最自然的方式,这使得将来可能需要阅读它的人很容易理解。它还允许您提供更多有用的诊断消息并将不必要的密码视为不那么严重,并且可以轻松修改这种情况很可能发生的情况。即,您可能会发现将密码作为命令行参数提供并不是最好的主意,如果缺少参数,您可能希望允许从标准输入中读取密码。或者您可能想默默地忽略多余的密码参数。像这样的改变不需要你重写整个事情。
Besides that it executes only the minimum number of comparisons, so it's not more expensive than the more "elegant"alternatives. Although performance is very unlikely a problem here because starting a new process is already much more expensive than a extra null check.
除此之外,它只执行最少数量的比较,因此它并不比更“优雅”的替代方案更昂贵。虽然性能在这里不太可能成为问题,因为启动一个新进程已经比额外的空检查昂贵得多。
回答by Didier L
A Java 8 solution would be to use Objects.isNull(Object)
, assuming a static import:
Objects.isNull(Object)
假设静态导入,Java 8 解决方案是使用:
if (isNull(from) != isNull(password)) {
throw ...;
}
For Java < 8 (or if you don't like using Objects.isNull()
), you can easily write your own isNull()
method.
对于 Java < 8(或者如果您不喜欢使用Objects.isNull()
),您可以轻松编写自己的isNull()
方法。
回答by Khaled.K
Here is a general solution for any number of null checks
这是任意数量的空检查的通用解决方案
public static int nulls(Object... objs)
{
int n = 0;
for(Object obj : objs) if(obj == null) n++;
return n;
}
public static void main (String[] args) throws java.lang.Exception
{
String a = null;
String b = "";
String c = "Test";
System.out.println (" "+nulls(a,b,c));
}
Uses
用途
// equivalent to (a==null & !(b==null|c==null) | .. | c==null & !(a==null|b==null))
if (nulls(a,b,c) == 1) { .. }
// equivalent to (a==null | b==null | c==null)
if (nulls(a,b,c) >= 1) { .. }
// equivalent to (a!=null | b!=null | c!=null)
if (nulls(a,b,c) < 3) { .. }
// equivalent to (a==null & b==null & c==null)
if (nulls(a,b,c) == 3) { .. }
// equivalent to (a!=null & b!=null & c!=null)
if (nulls(a,b,c) == 0) { .. }
回答by Arnab Datta
Here's a relatively straight-forward way that does not involve any Xor og lengthy ifs. It does however require you to be slightly more verbose, but on the upside, you can use the custom Exceptions I suggested to get a more meaningful error message.
这是一种相对直接的方式,不涉及任何异或冗长的 if。然而,它确实需要您稍微详细一点,但从好的方面来说,您可以使用我建议的自定义异常来获得更有意义的错误消息。
private void validatePasswordExists(Parameters params) {
if (!params.hasKey("password")){
throw new PasswordMissingException("Password missing");
}
}
private void validateFromExists(Parameters params) {
if (!params.hasKey("from")){
throw new FromEmailMissingException("From-email missing");
}
}
private void validateParams(Parameters params) {
if (params.hasKey("from") || params.hasKey("password")){
validateFromExists(params);
validatePasswordExists(params);
}
}