Lambda vs Anon与静态嵌套类

时间:2016-12-26 11:08:41

标签: java

这个类有三个方法可以做同样的事情,它们等待三秒钟加载页面,如果页面已加载则返回true。
我的问题是,我如何确定哪一段代码最好?
我知道Lambda is preferred above Anon classes,但为什么静态嵌套类(pageLoaded3)不好?根据{{​​3}},它也应该适合。

public final class ExpectedConditions {

    private ExpectedConditions() {
    }

    public static ExpectedCondition<Boolean> pageLoaded1() {
        return (driver) -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return !((JavascriptExecutor) driver).executeScript("return performance.timing.loadEventEnd", new Object[0])
                    .equals("0");
        };
    }

    public static ExpectedCondition<Boolean> pageLoaded2() {
        return new ExpectedCondition<Boolean>() {
            @Override
            public Boolean apply(WebDriver driver) {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return !((JavascriptExecutor) driver)
                        .executeScript("return performance.timing.loadEventEnd", new Object[0]).equals("0");
            }
        };
    }

    public static ExpectedCondition<Boolean> pageLoaded3() {
        return new PageLoaded();
    }

    private static class PageLoaded implements ExpectedCondition<Boolean> {
        @Override
        public Boolean apply(WebDriver driver) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return !((JavascriptExecutor) driver).executeScript("return performance.timing.loadEventEnd", new Object[0])
                    .equals("0");
        }
    }

}

这是三种方法的返回类型的接口:

public interface ExpectedCondition<T> extends Function<WebDriver, T> {}

1 个答案:

答案 0 :(得分:1)

正如评论中已经提到的:功能是等效的。所以技术上,差别很小。所有方法都编译为类似的字节码。所以关于哪一个是最好的&#34;只能根据代码本身来回答。在那里,可以应用不同的标准。

首先,正如Peter Lawrey在评论中所说的那样:你可以将Thread.sleep召唤变成帮助方法:

private static void pause(long ms)
{
    try
    {
        Thread.sleep(ms);
    }
    catch (InterruptedException e)
    {
        Thread.currentThread().interrupt();
    }
}

此外,您可以将在那里实现的核心功能转换为辅助方法:

private static Boolean execute(WebDriver driver)
{
    pause(3000);
    return !((JavascriptExecutor) driver)
        .executeScript("return performance.timing.loadEventEnd", new Object[0])
        .equals("0");
}

使用这种方法,给定方法之间的相似性变得更加明显:它们只是调用此方法的不同方式!我认为引入这种方法将具有额外的优势。该方法是一个清晰的构建块&#34;,具有清晰的接口(并且希望具有清晰的JavaDoc)。

此外,此方法将为第四次实现打开大门 - 即使用方法引用的方法:

public static ExpectedCondition<Boolean> pageLoaded4()
{
    return ExpectedConditions::execute;
}

因此,您现在有四种方法可以实现所需的功能:

  1. 使用lambda
  2. 使用匿名课程
  3. 使用静态内含课程
  4. 使用方法参考
  5. 实际上,人们可以争论利弊:

    • 方法3,使用静态内含类:这不是必需的。如果静态内部类是方法调用的包装器,则它不能用于实际目的。它引入了一个新的名称(在您的情况下为PageLoaded),并在源代码中引入了一个新的间接 - 这意味着程序员必须查找PageLoaded类来查看它确实。在其他情况下,这可能是一个不同的故事。例如。如果PageLoaded类有其他方法或字段,但这不是这种情况。

    • 方法2,有一个匿名的内部类:有人可能会认为功能界面的匿名类只是老式的#34;或者#Java; pre-Java8-way&#34;写它。如果必须实现的类型是功能接口(即具有单个抽象方法),则使用lambda或方法引用只是更短且更方便,并且没有任何明显的缺点。 (当然,如果必须实现的类型具有多个抽象方法,那么这是不可能的。但同样,这不是这种情况)

    • 方法1,使用lambda:这是在Java 8中实现这种功能接口的标准方法。我个人更喜欢拥有 lambda体。像你问题中那样的lambda

      return (driver) -> {
          // "Many" lines of code, maybe even nested, with try-catch blocks
      };
      

      是恕我直言,不那么可读和简洁,我通常尽量保持这些身体尽可能短。在最好的情况下,可以省略{括号} - 通过引入包含lambda主体的方法来确定。在这种情况下,人们通常可以将其归结为最后一种方法:

    • 方法4,方法参考。这可能有点主观,但我认为这个是最具可读性的。该方法的优点是成为&#34;构建块&#34;具有明确的功能,可以在JavaDocs中明确指定。此外,您甚至可以考虑省略包装方法(上面称为pageLoaded4),并简单地将该方法作为public提供。用户,以前称为

      ExpectedCondition<Boolean> condition = 
          ExpectedConditions::pageLoaded4();
      

      然后可以直接使用该方法

      ExpectedCondition<Boolean> condition = 
          ExpectedConditions::execute;
      

      但是这个取决于确切的应用程序模式和这个类的预期接口。可能不希望直接公开此方法。