Questions tagged «java8»

Java 8是指Java平台的最新版本。

10
为什么在Java 8+中使用Optional而不是传统的空指针检查?
我们最近已经迁移到Java8。现在,我看到应用程序充斥着Optional对象。 Java 8之前(样式1) Employee employee = employeeServive.getEmployee(); if(employee!=null){ System.out.println(employee.getId()); } Java 8之后(样式2) Optional<Employee> employeeOptional = Optional.ofNullable(employeeService.getEmployee()); if(employeeOptional.isPresent()){ Employee employee = employeeOptional.get(); System.out.println(employee.getId()); } 我看不到Optional<Employee> employeeOptional = employeeService.getEmployee();服务本身返回可选值时的附加值: 来自Java 6背景,我认为样式1更清晰,代码行更少。我在这里没有任何真正的优势吗? 通过对所有答案的理解和博客的进一步研究得到巩固
110 java  java8 

5
当我们已经有了抽象类时,为什么要将默认方法和静态方法添加到Java 8的接口中?
在Java 8中,接口可以包含已实现的方法,静态方法和所谓的“默认”方法(实现类不需要重写)。 以我的观点(可能是幼稚的),不需要违反这样的接口。接口一直是您必须履行的合同,这是一个非常简单而纯粹的概念。现在,它是几件事情的混合体。在我看来: 静态方法不属于接口。它们属于实用程序类。 根本不应该在接口中允许使用“默认”方法。为此,您可以始终使用抽象类。 简而言之: 在Java 8之前: 您可以使用抽象和常规类来提供静态和默认方法。接口的作用很明显。 接口中的所有方法都应通过实现类来覆盖。 您不能在不修改所有实现的情况下在接口中添加新方法,但这实际上是一件好事。 在Java 8之后: 接口和抽象类之间几乎没有区别(除了多重继承)。实际上,您可以使用接口模拟常规类。 在对实现进行编程时,程序员可能会忘记覆盖默认方法。 如果类试图实现两个或多个具有默认方法且具有相同签名的接口,则会出现编译错误。 通过向接口添加默认方法,每个实现类都会自动继承此行为。这些类中的某些类可能并未在设计时考虑到该新功能,因此可能会引起问题。例如,如果有人将新的默认方法添加default void foo()到interface Ix,则不会编译Cx实现Ix并具有具有foo相同签名的私有方法的类。 进行此类重大更改的主要原因是什么?它们会带来哪些新的好处(如果有)?

3
不带参数不返回任何值的函数的名称是什么?[关闭]
在Java 8的java.util.function程序包中,我们有: 功能:接受一个参数,产生一个结果。 消费者:采取一种论点,什么都不做。 供应商:不带任何争议,得出一个结果。 ...:其他处理原语,2个参数等的情况... 但是我需要处理“ 不带参数,不产生任何东西 ”的情况。 在中没有任何内容java.util.functionnal。 因此,问题是: “ 不带参数不返回任何值的函数 ”的名称是什么? 在Java 8中,其定义为: @FunctionalInterface public interface InsertANameHere { void execute(); } 执行程序已经存在并具有另一个用途:“ 一个对象,该对象执行已提交的可运行任务 ”。签名不匹配(execute(Runnable):void),甚至都不是一个功能接口。 Runnable存在,但它与线程上下文紧密关联: 这个包java.lang不是java.util.function。 javadoc指出:“ Runnable接口应该由实例打算由线程执行的任何类实现 ”。 名称“ Runnable”建议在线程内运行一些代码。

3
为什么Java 8 java.time类缺少getMillis()方法?
Java 8在java.time包中提供了一个用于日期和时间的全新库,这对于以前必须使用JodaTime或使其成为自己的日期处理助手方法而感到烦恼的人来说,是一件非常受欢迎的事情。该程序包中的许多类都表示时间戳,并具有一些辅助方法,例如getHour()从时间戳获取小时,从时间戳getMinute()获取分钟,从时间戳getNano()获取nano等。 我注意到他们没有一种方法getMillis()来获取时间戳的毫秒数。相反,必须调用method get(ChronoField.MILLI_OF_SECOND)。在我看来,这似乎是图书馆中的矛盾之处。有谁知道为什么缺少这种方法,或者由于Java 8仍在开发中,是否有可能稍后再添加呢? https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html 此处定义的类代表主要的日期时间概念,包括瞬间,持续时间,日期,时间,时区和时间段。它们基于ISO日历系统,这是遵循通用格里高利规则的事实世界日历。所有的类都是不可变的并且是线程安全的。 每个日期时间实例均由API方便提供的字段组成。对于较低级别的字段访问,请参考java.time.temporal软件包。每个类都支持打印和解析各种日期和时间。请参阅java.time.format软件包以获取自定义选项... 此类示例:https : //docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html ISO-8601日历系统中没有时区的日期时间,例如2007-12-03T10:15:30。 LocalDateTime是一个不变的日期时间对象,代表一个日期时间,通常被视为年-月-日-时-分-秒。也可以访问其他日期和时间字段,例如,一年中的某天,一周中的某天和一周中的某周。时间以纳秒精度表示。例如,值“ 2nd October 2007 at 13:45.30.123456789”可以存储在LocalDateTime...中
64 java  java8 

3
在Java 8中使用方法引用语法而不是lambda语法是否会对性能产生好处?
方法引用是否跳过了lambda包装器的开销?他们将来可能吗? 根据有关方法参考的Java教程: 有时... lambda表达式除了调用现有方法外什么也不做。在这种情况下,通常更容易按名称引用现有方法。方法引用使您可以执行此操作;它们是紧凑的,易于阅读的lambda表达式,用于已经具有名称的方法。 由于以下几个原因,我更喜欢lambda语法而不是方法引用语法: Lambda更清晰 尽管有Oracle的主张,但我发现lambda语法比对象方法引用的简写形式更易于阅读,因为方法引用的语法是模棱两可的: Bar::foo 您是否在x的类上调用静态的一参数方法并将其传递给x? x -> Bar.foo(x) 还是在x上调用零参数实例方法? x -> x.foo() 方法参考语法可以代表任何一种。它隐藏了您的代码实际在做什么。 Lambda更安全 如果将Bar :: foo引用为类方法,并且Bar以后添加了同名的实例方法(反之亦然),则代码将不再编译。 您可以始终使用lambda 您可以将任何函数包装在lambda中-因此您可以在所有位置一致地使用相同的语法。方法引用语法不适用于采用或返回原始数组,引发已检查异常或具有与实例和静态方法相同的方法名称的方法(因为该方法引用语法对于调用哪种方法尚不明确) 。当您使用相同数量的参数重载方法时,它们不起作用,但是无论如何您都不应这样做(请参见Josh Bloch的第41项),因此我们不能将其与方法引用相对应。 结论 如果这样做不影响性能,我很想在我的IDE中关闭警告,并始终使用lambda语法,而不会将偶然的方法引用散布到我的代码中。 聚苯乙烯 无论在这里还是那里,但在我的梦中,对象方法引用看起来都更像这样,并且无需lambda包装器就直接在对象上对方法应用invoke-dynamic: _.foo()

6
Java检查的异常的解决方法
我非常感谢有关lambda和默认方法接口的Java 8新功能。但是,我仍然对检查的异常感到无聊。例如,如果我只想列出对象的所有可见字段,我想简单地写一下: Arrays.asList(p.getClass().getFields()).forEach( f -> System.out.println(f.get(p)) ); 但是,由于该get方法可能会抛出一个与Consumer接口协定不同的已检查异常,所以我必须捕获该异常并编写以下代码: Arrays.asList(p.getClass().getFields()).forEach( f -> { try { System.out.println(f.get(p)); } catch (IllegalArgumentException | IllegalAccessException ex) { throw new RuntimeException(ex); } } ); 但是,在大多数情况下,我只希望将异常作为a抛出,RuntimeException并让程序处理或不处理没有编译错误的异常。 因此,我想就我对有争议的异常进行检查的方法发表您的看法。为此,我创建了一个辅助接口ConsumerCheckException<T>和一个实用程序功能rethrow(根据Doval的评论进行了更新),如下所示: @FunctionalInterface public interface ConsumerCheckException<T>{ void accept(T elem) throws Exception; } public class Wrappers { public static <T> Consumer<T> rethrow(ConsumerCheckException<T> c) …

3
为什么要使用“函数操作”而不是for循环?
for (Canvas canvas : list) { } NetBeans建议我使用“功能操作”: list.stream().forEach((canvas) -> { }); 但是,这是为什么首选?如果有的话,很难阅读和理解。您正在调用stream(),然后forEach()使用带参数的lambda表达式canvas。我看不出有什么比for第一个片段中的循环更好。 显然,我只是出于美学目的。也许这里缺少我的技术优势。它是什么?为什么我应该改用第二种方法?

3
使用peek()修改流元素是否是反模式?
假设我有一个事物流,并且想在流中“丰富”它们,我可以使用peek()它,例如: streamOfThings.peek(this::thingMutator).forEach(this::someConsumer); 假设在代码的这一点上对事物进行变异是正确的行为-例如,该thingMutator方法可以将“ lastProcessed”字段设置为当前时间。 但是,peek()在大多数情况下,它的意思是“看起来,但不要碰”。 是使用peek()到发生变异流元素的反模式或不明智的? 编辑: 另一种更常规的方法是转换消费者: private void thingMutator(Thing thing) { thing.setLastProcessed(System.currentTimeMillis()); } 到返回参数的函数: private Thing thingMutator(Thing thing) { thing.setLastProcessed(currentTimeMillis()); return thing; } 并map()改用: stream.map(this::thingMutator)... 但这会引入敷衍的代码(return),但我不认为它会更清晰,因为您知道peek()返回的对象相同,但是map()乍一看并不清楚它是同一类对象。 此外,使用peek()lambda可以突变,但是map()您必须构建火车残骸。比较: stream.peek(t -> t.setLastProcessed(currentTimeMillis())).forEach(...) stream.map(t -> {t.setLastProcessed(currentTimeMillis()); return t;}).forEach(...) 我认为peek()版本更清晰,lambda也很明显是变异的,因此没有“神秘的”副作用。同样,如果使用方法引用,并且该方法的名称明确暗含了突变,则该名称也很明显。 就个人而言,我不会回避使用peek()变异-我觉得这很方便。


9
为什么使用可选的优先选择对变量进行空检查?
举两个代码示例: if(optional.isPresent()) { //do your thing } if(variable != null) { //do your thing } 据我所知,最明显的区别是Optional需要创建一个附加对象。 但是,许多人已经开始迅速采用Optionals。使用可选与空检查相比有什么优势?
25 java  java8 

3
为什么不调用isPresent()而不是iterator.next()的Optional.get()不好?
当使用新的Java8流api在集合中查找一个特定元素时,我编写如下代码: String theFirstString = myCollection.stream() .findFirst() .get(); 此处IntelliJ警告说,在不首先检查isPresent()的情况下调用get()的情况。 但是,此代码: String theFirstString = myCollection.iterator().next(); ...没有警告。 两种技术之间是否存在深刻的区别,从而使流传输方法在某种程度上更加“危险”,所以在不首先调用isPresent()的情况下永远不要调用get()至关重要。到处搜寻,我发现一些文章谈论程序员对Optional <>粗心大意,并假定他们可以随时调用get()。 问题是,我想在我的代码有错误的地方尽可能近地引发异常,在这种情况下,这是我在找不到元素时调用get()的地方。我不想写无用的文章,例如: Optional<String> firstStream = myCollection.stream() .findFirst(); if (!firstStream.isPresent()) { throw new IllegalStateException("There is no first string even though I totally expected there to be! <sarcasm>This exception is much more useful than NoSuchElementException</sarcasm>"); } String …
23 java8 

1
测量Java 8代码的条件覆盖范围是否有意义?
我想知道自Java 8出现以来,当前使用Java的工具来衡量条件代码覆盖率是否还没有过时。使用Java 8 Optional,Stream我们通常可以避免代码分支/循环,这使得在不测试所有可能的执行路径的情况下轻松获得很高的条件覆盖率。让我们将旧的Java代码与Java 8代码进行比较: 在Java 8之前: public String getName(User user) { if (user != null) { if (user.getName() != null) { return user.getName(); } } return "unknown"; } 以上方法有3条可能的执行路径。为了获得100%的条件覆盖率,我们需要创建3个单元测试。 Java 8: public String getName(User user) { return Optional.ofNullable(user) .map(User::getName) .orElse("unknown"); } 在这种情况下,分支是隐藏的,我们只需要进行一次测试即可获得100%的覆盖率,无论哪种情况我们都将进行测试。我相信,尽管仍然存在相同的三个逻辑分支。我认为这使有条件覆盖范围统计这些天完全不可信。 测量Java 8代码的条件覆盖范围是否有意义?还有其他工具可以发现未经测试的代码吗?

3
在通常返回集合的地方返回Streams是理智的事情吗?
在开发与任何旧代码无关的API时,我经常发现自己编写的方法纯粹是通过收集结果终止的Streams管道。像这个: ImmutableSet<T> deriveSomethingMeaningfulFromPrivateState() { return myPrivateThingies.stream() .map(this::ownerOfThing) .map(Owner::socialStatus) .filter(SocialStatus::isHeAFineMatey) .collect(MyCustomCollectors.toImmutableSet()); } 现在,此类的大多数客户端通常将需要Collection(在本例中为ImmutableSet)来搜索元素并对其进行迭代,但是某些客户端可能会受益于拥有Stream,因此可以在此基础上传递更多的操作流,而无需从集合中获取新的流。因此,返回Stream会给客户提供他们如果拥有Collection便拥有的选项超集(毕竟,他们总是可以collect()自己拥有Stream: Stream<T> deriveSomethingMeaningfulFromPrivateState() { return myPrivateThingies.stream() .map(this::ownerOfthing) .map(Owner::socialStatus) .filter(SocialStatus::isHeAFineMatey); // No collect } 这种方法对我来说很诱人,因为我看不到它可能存在的任何潜在缺陷。但是,我在任何库中都从未见过这种方法(可能是因为Java 8出现后没有发布太多的库),所以我有点害怕采用它。现有的库类通常在从私有状态派生出某些东西时返回Collections。 如果我决定在Java-8之前的我自己会返回Collection的任何地方返回Stream ,会发生什么不好的事情?还是我可能在这里做一些反模式的事情,而这一切都源于私人国家?

1
将Scala函数传递给Java 8方法
以下Scala代码可以正常工作,并且可以传递给需要功能的Java方法。有没有更清洁的方法可以做到这一点?这是我的第一遍: val plusOne = new java.util.function.Function[Int,Int] { override def apply(t:Int):Int = t + 1 override def andThen[V](after:function.Function[_ >: Int, _ <: V]): function.Function[Int, V] = ??? override def compose[V](before:function.Function[_ >: V, _ <: Int]): function.Function[V, Int] = ??? } 这是我的第二遍-它使用Java-8 Function接口的通用包装器来简化Scala语法: // Note: Function1 is Scala's functional interface, // Function …

1
与每个循环的标准相比,Collection.stream()。filter()。forEach()效率低下吗?
IntelliJ IDEA刚刚向我建议用Java 8“ forEach”调用替换以下for-each循环: for (Object o : objects) { if (o instanceof SomeObject) { doSomething(); } } 推荐的电话如下所示: objects.stream().filter(o -> o instanceof SomeObject).forEach(o -> doSomething()); 除非我误解了Stream的基础功能如何工作,否则在我看来,使用stream是一个O(2n)操作,而不是标准for-each循环的O(n)操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.