5

我有一个梦想....

在这个梦想中,我可以替换以下结构:

if(aLongVariableName.equals(classInstance.aPropertyOfThatInstance) ||  
   aLongVariableName.equals(classInstance.aDifferentProperty)){  
    ...  
}

if(aLongVariableName.equals(classInstance.aDifferentProperty || aPropertyOfThatInstance)){ 
   ...  
}

我认为后者更简洁,更易于阅读。我确信有些事情应该是可能的,因为可以使用这种带有逗号分隔变量的签名声明方法public void readUnlimitedVariables(Variable ... vars)不是||or &&)。

这可以对任何返回布尔值的东西开放,例如:

if(myLovelyInstance instanceof AwesomeClass && EpicClass){
    ...
}

在哪里myLovelyInstance实现AwesomeClass && EpicClass

这在Java中可能吗?到目前为止,通过谷歌搜索或 SO,我还没有找到任何关于此的内容。如果它不在 vanilla Java 中,是否有任何第三方软件包(如 Lombok 或 lambdaJ)允许这样做?如果不是这样,如果这是任何语言的特征?这对我来说似乎很直观,但我在任何地方都没有看到它。

4

6 回答 6

8

这在Java中可能吗?

不。

运算符采用||两个布尔操作数。没有办法改变这一点。Java 不允许您重载运算符,或以其他方式“扩展语言语法”。

最接近的方法是为 equals 定义一个重载,如下所示:

public boolean equals(Object ... others) {
    for (Object other: others) {
        if (this.equals(other)) {
            return true;
        }
    }
    return false;
}

并像这样使用它:

if (aLongVariableName.equals(classInstance.aDifferentProperty,
                             classInstance.anotherProperty)) {
    ...  
}

...这根本不是很接近。(也是一个非常糟糕的主意,IMO)

事实上,我想不出任何支持类似于您所提议的语法的语言。让我感到震惊的是,有太多的歧义可能会成为一个合理的结构。

于 2013-06-29T09:40:08.333 回答
5

为了便于阅读,如果检查的次数足够少,您可以只使用简单的变量。

例如(对于任何类型的对象都相同)

boolean isPDFFile  = extension.equalsIgnoreCase("PDF");
boolean isHTMLFile = extension.equalsIgnoreCase("html");

if (isPDFFile || isHTMLFile ) {
   // do your processing
}

如果您使用字符串,正则表达式是另一种方式:

if (extension.matches("PDF|HTML")) {
   // do your processing
}

有时简单胜于聪明!

于 2013-06-29T10:11:15.763 回答
3

你能考虑像一个不好的做法吗?(我对 Java 还很陌生,所以我可能会发明轮子或者只是胡说八道*t :))

public class Main {
    public static <Type> boolean equalsVariadicOr(Type toComp, Type ... args) {
                for (Type arg : args) {
                        if (toComp.equals(arg)) {
                                return true;
                        }
                }
                return false;
        }

        public static <Type> boolean equalsVariadicAnd(Type toComp, Type ... args) {
                for (Type arg : args) {
                        if (!toComp.equals(arg)) {
                                return false;
                        }
                }
                return true;
        }

        public static void main(String args[]) {
                String testcaseAllA[]  = new String[] {"a", "a", "a", "a", "a", "a", "a", "a", "a", "a"};
                String testcaseWithB[] = new String[] {"b", "a", "a", "a", "a", "a", "a", "a", "a", "a"};
                System.out.println(equalsVariadicAnd("a", testcaseAllA));
                System.out.println(equalsVariadicAnd("b", testcaseWithB));
                System.out.println(equalsVariadicOr("b", testcaseWithB));
                System.out.println(equalsVariadicOr("a", testcaseAllA));
        }
}

如果答案不是,也许 OP 会觉得这很有用?

于 2013-06-29T09:48:45.753 回答
2

您可以使用 varargs 和 Lombok 的扩展方法获得非常相似的东西:

  1. 在实用程序类中定义以下静态方法:

    package test;
    
    public final class Util {
        private Util() {}
    
        public static boolean eqOr(Object tthis, Object ... those) {
            for (Object that : those) {
                if (tthis.equals(that)) return true;
            }
            return false;
        }
    
        public static boolean eqAnd(Object tthis, Object ... those) {
            for (Object that : those) {
                if (!tthis.equals(that)) return false;
            }
            return true;
        }
    }
    
  2. 使用Lombok制作eqAndeqOr扩展方法:

    package test;
    
    @lombok.experimental.ExtensionMethod({test.Util.class})
    public class Work {
      public static void main(String[] args) {
        System.out.println("a".eqOr("b", "c", "a"));
        System.out.println("a".eqOr("b", "c"));
        System.out.println("a".eqAnd("a", "a", "a"));
        System.out.println("a".eqAnd("a", "a", "c"));
      }
    }
    

    显然,如果您不喜欢 lombok,您可以将它们用作常规静态方法。

于 2013-06-29T11:15:32.033 回答
1

这在 Java 中是不可能的。的参数||must 是booleans,现在决定为时已晚.equals,因为它没有得到两个值,只是一个boolean.

为此,必须更改 Java 语言规范。我看不出会有这样的趋势,所以你应该告诉 Java 的维护者你想要这个。即使他们接受它,也可能需要数年时间才能使其符合语言规范,然后才能部署到大多数 Java 安装中。

于 2013-06-29T09:25:16.293 回答
1

不要忘记封装。

您通常可以使用实例方法清理代码:

您可以这样做,而不是冗长且令人困惑的 if 语句:

if (classInstance.matches(reallyLongVariableName)) {
    doStuff();
}

你把丑陋埋在一个方法里:

class LongNamedObject {

    String propertyWithNameThatIsLong;
    String anotherLongNamedProperty;

    public boolean matches(String s) {
        return ( s.equals(propertyWithNameThatIsLong) ||
                 s.equals(anotherLongNamedProperty) );
    }
}

使用富有表现力的名称编写布尔方法是使代码更易于阅读的好方法。

你经常看到这样的混乱:

if (userInputFile != null && userInputFile.getAbolutePath() != null 
      && user != null && user.getAccessRules() != null 
      && userHasAccess(user, userInputFile) {
    doStuff();
}

它可能看起来像这样:

if (isValid(userInputFile, user)) {
    doStuff();
}

你把丑陋埋在一个方法里:

private boolean isValid(File f, User u) {
    if (u == null || f == null) {
        return false;
    }
    if (f.getAbsolutePath() == null) {
        return false;
    }
    if (u.getAccessRules() == null) {
        return false;
    }
    return userHasAccess(u, f);
}
于 2013-06-29T10:14:09.263 回答