Swift编程语言指南有以下示例:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { println("\(name) is being deinitialized") }
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
var tenant: Person?
deinit { println("Apartment #\(number) is being deinitialized") }
}
var john: Person?
var number73: Apartment?
john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)
//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
Run Code Online (Sandbox Code Playgroud)
然后,当将公寓分配给该人时,他们使用感叹号来"解开实例":
john!.apartment = number73
Run Code Online (Sandbox Code Playgroud)
"打开实例"是什么意思?为什么有必要?它与仅执行以下操作有何不同:
john.apartment …Run Code Online (Sandbox Code Playgroud) 为什么要创建一个"Implicitly Unwrapped Optional"来创建一个常规变量或常量?如果您知道它可以成功解开,那么为什么要首先创建一个可选项呢?例如,为什么这样:
let someString: String! = "this is the string"
Run Code Online (Sandbox Code Playgroud)
会比以下更有用:
let someString: String = "this is the string"
Run Code Online (Sandbox Code Playgroud)
如果"optionals指示常量或变量允许'没有值'",但"有时从程序的结构中可以清楚地看到,在首次设置该值之后,可选项将始终具有值",那么有什么意义呢?首先让它成为可选项?如果你知道一个可选项总是会有一个值,那么它不是可选的吗?
我在许多网站上阅读过Optional只能用作返回类型,而不能在方法参数中使用.我很难找到合乎逻辑的原因.例如,我有一个逻辑,它有2个可选参数.因此,我认为像这样编写我的方法签名是有意义的(解决方案1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Run Code Online (Sandbox Code Playgroud)
许多网页指定Optional不应该用作方法参数.考虑到这一点,我可以使用以下方法签名并添加一个清晰的Javadoc注释来指定参数可能为null,希望将来的维护者将读取Javadoc,因此在使用参数之前始终执行空值检查(解决方案2) :
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Run Code Online (Sandbox Code Playgroud)
或者,我可以用四种公共方法替换我的方法以提供更好的界面并使其更明显p1和p2是可选的(解决方案3):
public int calculateSomething() {
calculateSomething(null, null);
}
public int calculateSomething(String p1) {
calculateSomething(p1, null);
}
public int calculateSomething(BigDecimal p2) {
calculateSomething(null, p2);
}
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Run Code Online (Sandbox Code Playgroud)
现在我尝试编写类的代码,为每种方法调用这条逻辑.我首先从另一个返回Optionals的对象中检索两个输入参数然后调用calculateSomething.因此,如果使用解决方案1,则调用代码将如下所示:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
Run Code Online (Sandbox Code Playgroud)
如果使用解决方案2,则调用代码将如下所示:
Optional<String> …Run Code Online (Sandbox Code Playgroud) 在我的Android应用程序中,我将使用国际化来实现我的字符串.我的语法和句子用不同语言构建的方式有问题.
例如:
"5分钟前" - 英文
"vor 5 Minuten" - 德语
我可以在strings.xml中执行以下操作吗?
<string name="timeFormat">{0} minutes ago</string>
Run Code Online (Sandbox Code Playgroud)
然后有些神奇的
getString(R.id.timeFormat, dynamicTimeValue)
Run Code Online (Sandbox Code Playgroud)
此行为也将解决不同单词顺序的其他问题.
Optional Java 8中引入的类型对于许多开发人员来说是一件新事物.
一个getter方法返回Optional<Foo>类型代替经典的Foo一个好习惯吗?假设值可以null.
现在已经使用Java 8超过6个月左右,我对新的API更改感到非常满意.我仍然不自信的一个领域是什么时候使用Optional.我似乎想要在任何可能的null地方使用它,而且无处可去.
似乎有很多情况我可以使用它,我不知道它是否增加了好处(可读性/无效安全性)或只是导致额外的开销.
所以,我有一些例子,我对社区是否Optional有益的想法感兴趣.
1 - 当方法可以返回时作为公共方法返回类型null:
public Optional<Foo> findFoo(String id);
Run Code Online (Sandbox Code Playgroud)
2 - 当参数可能是null以下时作为方法参数:
public Foo doSomething(String id, Optional<Bar> barOptional);
Run Code Online (Sandbox Code Playgroud)
3 - 作为bean的可选成员:
public class Book {
private List<Pages> pages;
private Optional<Index> index;
}
Run Code Online (Sandbox Code Playgroud)
4 - 在Collections:
一般来说,我不认为:
List<Optional<Foo>>
Run Code Online (Sandbox Code Playgroud)
添加任何东西 - 特别是因为可以使用filter()删除null值等,但是Optional在集合中是否有任何好的用途?
我错过了什么案例?
在Java 8中,我想对一个Optional对象做一些事情,如果它存在,并做另一件事,如果它不存在.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
Run Code Online (Sandbox Code Playgroud)
但这不是一种"功能风格".
Optional有一个ifPresent()方法,但我无法链接一个orElse()方法.
因此,我不能写:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
Run Code Online (Sandbox Code Playgroud)
在回复@assylias时,我认为不适Optional.map()用于以下情况:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当opt存在时,我更新其属性并保存到数据库.当它不可用时,我创建一个新的obj并保存到数据库.
请注意我必须返回的两个lambda null.
但是当opt存在时,两个lambdas都将被执行.obj将更新,并将新对象保存到数据库.这是因为return null在第一个lambda中.并且orElseGet()将继续执行.
使用Java 8 Optional类时,有两种方法可以将值包装在可选项中.
String foobar = <value or null>;
Optional.of(foobar); // May throw NullPointerException
Optional.ofNullable(foobar); // Safe from NullPointerException
Run Code Online (Sandbox Code Playgroud)
我理解Optional.ofNullable是唯一安全的使用方式Optional,但为什么Optional.of存在呢?为什么不Optional.ofNullable 随时使用并保持安全?
我试图理解Optional<T>.orElse()和Optional<T>.orElseGet()方法之间的区别.
该orElse()方法的描述是"如果存在则返回值,否则返回其他值".
虽然,该orElseGet()方法的描述是"如果存在则返回值,否则调用other并返回该调用的结果".
该orElseGet()方法采用供应商功能接口,基本上不接受任何参数和返回T.
你需要在哪种情况下使用orElseGet()?如果你有一个方法,你T myDefault()为什么不这样做optional.orElse(myDefault())而不是optional.orElseGet(() -> myDefault())?
似乎没有orElseGet()将lambda表达式的执行推迟到以后的某个时间或什么的,所以有什么意义呢?(我本以为如果它返回一个更安全Optional<T>的东西会更有用,它get()永远不会抛出一个NoSuchElementException并且isPresent()总是返回真实......但显然它不是,它只是返回T就像orElse()).
我还缺少其他一些差异吗?