J'apprends les bases de Java et j'explore les Optionals and abstract classes , je suis donc tombé sur le problème suivant,
J'ai ce code
Start
it is a Dog
Barking...
Exception in thread "main" java.lang.NullPointerException
at com.example.helloworldeclipse.Animal.main(Animal.java:24)
Je m'attendais à voir les impressions sur la console "C'est un chien" suivi de 2 "Ce n'est pas un chien" Puisque j'utilise la méthode .isPresent() sur les options,
Mais j'ai eu 1 impression, puis une NullPointerException :
C'est ce que j'ai imprimé:
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......");
}
}
IsPresent ne devrait-il pas être sûr? y a-t-il un meilleur moyen de convertir des classes abstraites en sous-classes dans des situations similaires?
Je ne comprends pas pourquoi cela ne fonctionne pas. Qu'est-ce que je fais de mal ici?
Merci d'avance pour toutes les réponses.
3 Réponses :
Vous ne devez pas utiliser null, utilisez à la place Optional<T>.empty() , lisez ici https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#empty--
Le problème est que vous vérifiez si dog.isPresent mais que vous attribuez également potentiellement null à dog lorsque la valeur n'est pas dog. c'est-à-dire sur la deuxième itération.
Optional<Dog> dog = animal instanceof Dog ? Optional.of((Dog) animal) : Optional.empty();
Le problème est que vous attribuez null à une référence Optional lorsque la vérification d' instanceof échoue.
Vous avez au moins deux options:
Utilisez Optional.empty() au lieu de null
Optional<Dog> dog = Optional.of(animal)
.filter(Dog.class::isInstance)
.map(Dog.class::cast);
Utilisez les méthodes de filter et de map facultatives:
Optional<Dog> dog = animal instanceof Dog ? Optional.of((Dog) animal) : Optional.empty();
Le prédicat Dog.class::isInstance vérifie si l'instance donnée, qui est la valeur dans Optional , est une instance de Dog . C'est equivalent à instanceof . Puis Dog.class::cast l'objet donné en une instance Dog .
Remarque: Si animal lui animal même peut être null , alors vous devez utiliser Optional::ofNullable au lieu de Optional::of .
Je pense que je suis trop habitué à swift) Merci beaucoup, la deuxième option est encore plus compacte et lisible 👍
@Lucas Je suis totalement d'accord avec vous!
Vous devez affecter
_dog,_catet_horseàOptional.empty()au lieu de null lorsque le type ne correspond pas.Une variable / champ / paramètre
Optionalne devrait jamais êtrenull, cela anéantirait fondamentalement toute la raison de son existence.