如何正确解包 Java 中的可选值?
How to properly unwrap an optional in Java?
我正在学习 Java 的基础知识并且正在探索 Optionals and abstract classes
所以我遇到了以下问题,
我有这个代码
import java.util.Optional;
public abstract class Animal {
abstract void makeSound();
public static void main(String[] args) {
System.out.println("Start");
Dog dog = new Dog();
Cat cat = new Cat();
Horse horse = new Horse();
Animal[] animals = {dog, cat, horse};
for (Animal animal : animals) {
Optional<Dog> _dog = animal instanceof Dog ? Optional.of((Dog) animal) : null;
Optional<Cat> _cat = animal instanceof Cat ? Optional.of((Cat) animal) : null;
Optional<Horse> _horse = animal instanceof Horse ? Optional.of((Horse) animal) : null;
if (_dog.isPresent()) {
System.out.println("it is a Dog");
} else {
System.out.println("it is NOT a Dog");
}
animal.makeSound();
}
}
}
class Horse extends Animal {
String speed = "Fast";
@Override
void makeSound() {
System.out.println("Neighing...");
}
}
class Dog extends Animal {
String color = "Brown";
@Override
void makeSound() {
System.out.println("Barking...");
}
}
class Cat extends Animal {
Integer lives = 9;
@Override
void makeSound() {
System.out.println("Mewoing......");
}
}
我期待在控制台上看到“It is a Dog”后面跟着 2 个“It is not a Dog”的打印,因为我在选项上使用方法 .isPresent()
,
但我打印了 1 张,然后是 NullPointerException
:
这就是我打印的内容:
Start
it is a Dog
Barking...
Exception in thread "main" java.lang.NullPointerException
at com.example.helloworldeclipse.Animal.main(Animal.java:24)
isPresent 不应该是安全的吗?在类似这样的情况下,是否有更好的方法将 abstract 类 转换为 sub类?
我不明白为什么它不起作用..我做错了什么?
预先感谢您的所有回答..
您不应使用 null,请改用 Optional<T>.empty()
,请阅读此处 https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#empty--
问题是您正在检查 dog.isPresent 但当值不是 dog 时,您也可能将 null 分配给 dog。即在第二次迭代中。
Optional<Dog> dog = animal instanceof Dog ? Optional.of((Dog) animal) : Optional.empty();
问题是当 instanceof
检查失败时,您将 null
分配给 Optional
引用。
您至少有两个选择:
使用Optional.empty()
代替null
Optional<Dog> dog = animal instanceof Dog ? Optional.of((Dog) animal) : Optional.empty();
使用 Optional 的 filter
and map
方法:
Optional<Dog> dog = Optional.of(animal)
.filter(Dog.class::isInstance)
.map(Dog.class::cast);
谓词 Dog.class::isInstance
检查给定实例(即 Optional
中的值)是否是 Dog
的实例。这是 equivalent
到 instanceof
。然后 Dog.class::cast
将给定对象转换为 Dog
实例。
注意:如果animal
本身可以是null
,那么你应该使用Optional::ofNullable
instead of Optional::of
.
我正在学习 Java 的基础知识并且正在探索 Optionals and abstract classes
所以我遇到了以下问题,
我有这个代码
import java.util.Optional;
public abstract class Animal {
abstract void makeSound();
public static void main(String[] args) {
System.out.println("Start");
Dog dog = new Dog();
Cat cat = new Cat();
Horse horse = new Horse();
Animal[] animals = {dog, cat, horse};
for (Animal animal : animals) {
Optional<Dog> _dog = animal instanceof Dog ? Optional.of((Dog) animal) : null;
Optional<Cat> _cat = animal instanceof Cat ? Optional.of((Cat) animal) : null;
Optional<Horse> _horse = animal instanceof Horse ? Optional.of((Horse) animal) : null;
if (_dog.isPresent()) {
System.out.println("it is a Dog");
} else {
System.out.println("it is NOT a Dog");
}
animal.makeSound();
}
}
}
class Horse extends Animal {
String speed = "Fast";
@Override
void makeSound() {
System.out.println("Neighing...");
}
}
class Dog extends Animal {
String color = "Brown";
@Override
void makeSound() {
System.out.println("Barking...");
}
}
class Cat extends Animal {
Integer lives = 9;
@Override
void makeSound() {
System.out.println("Mewoing......");
}
}
我期待在控制台上看到“It is a Dog”后面跟着 2 个“It is not a Dog”的打印,因为我在选项上使用方法 .isPresent()
,
但我打印了 1 张,然后是 NullPointerException
:
这就是我打印的内容:
Start
it is a Dog
Barking...
Exception in thread "main" java.lang.NullPointerException
at com.example.helloworldeclipse.Animal.main(Animal.java:24)
isPresent 不应该是安全的吗?在类似这样的情况下,是否有更好的方法将 abstract 类 转换为 sub类?
我不明白为什么它不起作用..我做错了什么?
预先感谢您的所有回答..
您不应使用 null,请改用 Optional<T>.empty()
,请阅读此处 https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#empty--
问题是您正在检查 dog.isPresent 但当值不是 dog 时,您也可能将 null 分配给 dog。即在第二次迭代中。
Optional<Dog> dog = animal instanceof Dog ? Optional.of((Dog) animal) : Optional.empty();
问题是当 instanceof
检查失败时,您将 null
分配给 Optional
引用。
您至少有两个选择:
使用
Optional.empty()
代替null
Optional<Dog> dog = animal instanceof Dog ? Optional.of((Dog) animal) : Optional.empty();
使用 Optional 的
filter
andmap
方法:Optional<Dog> dog = Optional.of(animal) .filter(Dog.class::isInstance) .map(Dog.class::cast);
谓词
Dog.class::isInstance
检查给定实例(即Optional
中的值)是否是Dog
的实例。这是equivalent
到instanceof
。然后Dog.class::cast
将给定对象转换为Dog
实例。
注意:如果animal
本身可以是null
,那么你应该使用Optional::ofNullable
instead of Optional::of
.