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
,_cat
et_horse
àOptional.empty()
au lieu de null lorsque le type ne correspond pas.Une variable / champ / paramètre
Optional
ne devrait jamais êtrenull
, cela anéantirait fondamentalement toute la raison de son existence.