IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Question au sujet des generics (Java8/Java7)


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut Question au sujet des generics (Java8/Java7)
    Salut,

    J'ai toujours quelques problèmes de compréhension de certains cas de syntaxe au sujet des classes/méthodes paramétrées et je suis tombé sur un cas qui ne m'aide pas à une meilleure compréhension.

    Voici une classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    public class Optional<T> {
     
    	private final static Optional<?> EMPTY = new Optional<>();
     
    	private final T value;
     
    	private Optional() {
    		this.value = null;
    	}
     
    	public static <T> Optional<T> empty() {
    		@SuppressWarnings("unchecked")
    		Optional<T> t = (Optional<T>) EMPTY;
    		return t;
    	}
     
    	private Optional(T value) {
    		if (value == null) { 
    			throw new NullPointerException();
    		}
    		this.value = value;
    	}
     
    	public static <T> Optional<T> of(T value) {
    		return new Optional<T>(value);
    	}
     
    	public static <T> Optional<T> ofNullable(T value) { 
    		return value == null ? empty() : of(value);
    	}
     
    	public T get() {
    		if ( value == null ) {
    			throw new NoSuchElementException("No value present");
    		}
    		return value;
    	}
     
    	public boolean isPresent() {
    		return value!=null;
    	}
     
    }
    Cette classe compile en Java8.

    Maintenant, je tente de la compiler en Java7 et j'ai une erreur dans cette méthode (Type mismatch) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public static <T> Optional<T> ofNullable(T value) {
    	return value == null ? empty() : of(value);
    }
    Que je peux corriger en faisant un cast (Optional<T) sur la valeur retournée, mais qui est toutefois signalé en "unchecked". Là, déjà, ça m'interpelle, mais bon admettons. J'écris donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @SuppressWarnings("unchecked")
    public static <T> Optional<T> ofNullable(T value) { 
        return value == null ? (Optional<T>)empty() : of(value);
    }
    et ça compile sans warning en Java7.

    Là, je commence à être un peu perdu : pourquoi l'appel de of() ne nécessite pas de cast, alors que celui de empty() si. A part l'argument de of(), je ne vois pas de différence dans la déclaration des deux méthodes. Et je ne vois en quoi l'argument pourrait avoir une influence ici. Encore, je serais obligé de caster les deux, je me dirais qu'il y a un point de la doc que je n'ai pas bien lu, ou pas compris, dans le fonctionnement des génériques. Mais, là, j'avoue que ça m'échappe.

    Encore plus quand j'écris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static <T> Optional<T> ofNullable(T value) {
        if ( value==null ) {
    	return empty();
        }
        else {
    	return of(value);
        }
    }
    et que ça compile, en Java7 (en Java5 d'ailleurs aussi, avec la petite modification nécessaire de private final static Optional<?> EMPTY = new Optional<Object>();).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  2. #2
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    à peu près:
    je crois qu'il y a un double problème:
    - l'évaluation du type paramètre de empty()
    - les règles régissant la compilation/évaluation de l'opérateur ternaire

    le paramètre T de l'un n'est pas forcément le paramètre T de l'autre (je veux dire la difficulté pour le compilateur c'est de savoir évaluer T dans le contexte du code)
    T pour of(value) ne pose pas de problème: on a une correspondance entre le paramètre de of et son résultat. dans le contexte de la méthode ofNullable on a ce qu'il faut (il s'agit du paramètre T de l'appel de ofNullable)
    c'est un peu plus dur pour empty() parcequ'ici l'évaluation de T par le compilateur ne me saute pas aux yeux (c'est le type de la variable à laquelle on l'affecte ... ) je suppute que le compilo ne sait plus faire l'harmonisation nécessaire à la gestion de l'opération ternaire .... il faut que je mette ça au clair dans ma tête)

  3. #3
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Déjà il faut faire attention au fait que les méthodes empty() et of() sont elles aussi paramétrées... indépendamment du paramétrage de la classe Optional.
    Ce n'est pas très lisible dans le code car ils utilisent toujours T, mais ce ne sont pas forcément les mêmes paramétrages.
    Il faut bien prendre en compte que ce sont des paramétrages qui peuvent être différents. Par exemple ce code là est strictement identique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Optional<T> {
            // ...
    	public static <U> Optional<U> empty() {
    		@SuppressWarnings("unchecked")
    		Optional<U> t = (Optional<U>) EMPTY;
    		return t;
    	}
            // ...
    	public static <V> Optional<V> of(V value) {
    		return new Optional<V>(value);
    	}


    Ensuite, tout comme pour les classes paramétrées, il faut théoriquement définir le type des méthodes paramétrées lorsqu'on les appelles.
    Cela se fait en en préfixant la méthode par le tag des Generics (eux même obligatoirement préfixé par l'instance ou le nom de classe pour une méthode static).
    Ce qui donnerait par exemple Optional.<String>empty() pour appeler empty() en le paramétrant avec String.

    Ainsi le code exact de ofNullable() devrait plutôt correspondre à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	public static <T> Optional<T> ofNullable(T value) { 
    		return value == null ? Optional.<T>empty() : Optional.<T>of(value);
    	}
    Et là on corrige ton premier problème : le code compile sans warning.




    Cette syntaxe n'est pas très connu car elle est rarement utile, puisque depuis Java 5 le compilateur utilise l'inférence de type pour déterminer ce paramétrage.
    C'est à dire qu'il va analyser les types en présence pour déterminer le paramétrage de la méthode.
    Par exemple si tu écris ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Optional<String> o = Optional.empty();
    Optional<String> o = Optional.of("hello");
    Le compilateur va déterminer que le paramétrage des méthodes empty() et of selon le type de retour et les paramètre reçu, et il va générer le paramétrage pour toi.
    En fait c'est équivalent à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Optional<String> o = Optional.<String>empty();
    Optional<String> o = Optional.<String>of("hello");
    Cette inférence de type fonctionne très bien dans la majorité des cas... mais pour diverses raisons il y avait quelques lacunes pour les méthodes dont seul le type de retour était paramétré.
    Il y a alors certains cas où le compilateur n'arrive pas à détecter le type du paramétrage de la méthode.

    C'est le cas lorsqu'on utilise l'opérateur ternaire ?: ou lorsqu'on passe le retour de la méthode paramétré en paramètre d'une autre méthode.
    Exemple de code qui ne compile pas sous Java 7 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	public static void method(List<String> l) {
     
    	}
     
    	public static void main(String[] args) throws Exception {
    		method(Collections.emptyList()); // ERREUR sous Java 7
     
    		Collection<String> c = (args.length==0)
    				? Collections.emptyList()  // ERREUR sous Java 7
    				: Arrays.asList(args);
    	}
    Le compilateur n'arrive pas à déterminer le paramétrage des méthodes et génère donc une erreur (pas forcément compréhensible d'ailleurs).

    Il faut donc corriger comme cela en spécifiant manuellement le paramétrage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	public static void main(String[] args) throws Exception {
    		method(Collections.<String>emptyList()); // ERREUR sous Java 7
     
    		Collection<String> c = (args.length==0)
    				? Collections.<String>emptyList()  // ERREUR sous Java 7
    				: Arrays.asList(args);
    	}


    Du coup cela explique ton problème sur la méthode ofNullable() : le compilateur n'arrive pas à déterminer le paramétrage de empty() via son seul type de retour.
    Par contre il n'a aucun problème pour la méthode of(), tout simplement car il prend en compte son paramètre (value) qui est lui aussi paramétré.
    Donc en Java 7 ceci suffit amplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	public static <T> Optional<T> ofNullable(T value) { 
    		return value == null ? Optional.<T>empty() : of(value);
    	}




    Avec Java 8 l'inférence de type a été grandement amélioré (c'était un prérequis pour les lambdas), et ces deux soucis n'existent plus.
    D'ailleurs sauf erreur de ma part il ne doit plus y avoir aucun cas où l'on est obligé de spécifier le paramétrage des méthodes...


    a++

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Merci @adiGuba, c'est beaucoup plus clair maintenant. Je ne connaissais pas cette syntaxe (enfin si un peu, j'avais déjà vu ça, mais sans vraiment tilter), et donc je n'avais pas en effet capté cette subtilité, car la plupart du temps, mes appels compilaient. Je vois mieux comment résoudre certains cas qui m'ont posé problème du coup.

    Pourquoi, par contre, le code suivant compile ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static <X> Optional<X> ofNullable(X value) {
       if ( value==null ) {
           return empty();
       }
       else {
           return of(value);
       }
    }
    Je ne vois pas ce qui permettrait au compilateur de mieux déterminer le bon type dans ce cas.

    PS. C'est vrai que d'utiliser le même nom de paramètre pour des méthodes différentes peut être confusant. Je n'ai pas de difficulté pour ma part dans ce type de confusion, mais j'essaye d'utiliser des noms de type paramétré différents. Là, j'ai repris directement le code de la classe, comme tu t'en ai aperçu.

    D'ailleurs, question subsidiaire : je trouve vraiment intéressant cette nouvelle classe de Java8, pour éviter de retourner null en résultat de méthode. C'est pourquoi, j'ai repris l'extrait de code pour l'intégrer dans mon application Java5 (J'utilisais déjà un wrapper similaire dans l'idée dans certains cas, mais je me suis dit autant utiliser directement la version Java8, ce qui me permettra une migration plus facile par la suite). Que pensez-vous de cette classe Optional de Java8 ?
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par joel.drigo Voir le message
    Pourquoi, par contre, le code suivant compile ?

    Je ne vois pas ce qui permettrait au compilateur de mieux déterminer le bon type dans ce cas.
    Contrairement au cas à opérateur ternaire, les expressions pour lesquelles il doit inférer un paramètre, sont uniques. Une fois qu'un paramètre candidat a été trouvé, ce candidat ne peut pas être un choix invalide ou contraignant pour une autre expression qui ait besoin d'un paramètre inféré, car il n'existe pas de telle autre expression. Il n'y a pas besoin de négocier le candidat avec autre chose, et donc trouver le meilleur candidat se fait sans prendre en compte d'autre contrainte que le type de retour attendu et les paramètres possibles pour la méthodes.

    Mitiger avec une autre expression ou plus de contexte, n'est pas insurmontable. Java 8 le fait, comme les lambdas l'exigeaient pour servir à quelque chose. Mais ça nécessite la définition d'un mécanisme de recherche du type acceptable le plus spécialisé, bien plus complexe que quand on ne cherche pas à le faire.

    Citation Envoyé par joel.drigo Voir le message
    Que pensez-vous de cette classe Optional de Java8 ?
    Bien pratique.

    Le pointeur null n'est pas forcément l'expression d'une variable à laquelle on était libre de donner une valeur ou non. Il peut être là par erreur.
    Par corollaire, quand on appelle une API qui renvoie un type objet, on ignore si le retour peut être null pour exprimer l'absence de valeur, ou si ce n'est jamais censé arriver.
    La question qui se pose en tant que développeur est : dans lequel de ces deux cas est-on ? Avec une variable de type Optional on définit une valeur optionnelle et c'est une question qui ne se pose plus. Une documentation peut donner ces informations c'est vrai... Mais au prix d'avoir fait cette documentation et de la consulter. Avec un type dédié à l'expression de la chose, on gagne en clarté.

    Comme cela implique la création d'un objet supplémentaire et des appels de méthodes en plus, on ne peut pas toujours se permettre de s'en servir pour lever les ambiguïtés. Mais pour définir des APIs générales, ça soulage pas mal.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Ok, merci @Thelvin.

    Je crois comprendre pourquoi il n'y a pas d'ambiguïté dans le cas du bloc if/else : parce en quelque sorte, il est équivalent à un return unique. Chaque bloc étant forcément exécutable exclusivement, on peut réduire le cas à un cas avec un simple return, cas qui ne pose aucun problème d'ambiguïté forcément. C'est bien ça ?

    Et ambiguïté "résolue" automatiquement en Java8, pour l'opérateur ternaire.

    Je vois encore mieux la portée de la syntaxe explicite donnée par @AdiGuba : elle permet de lever ce type d’ambiguïté pour forcer le compilateur à ne pas avoir de "doute".
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  7. #7
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Comme l'a dit thelvin, ce cas est simple car empty() est affecté au type de retour de la méthode, qui est connu à ce moment.

    Pour les opérations ternaires le problème devait venir du fait que les deux opérandes peuvent avoir un type différent du résultat.
    Je pense qu'il s'agissait sûrement d'un bug ou d'un oubli qui est resté comme cela car pas très problématique...

    Le cas le plus complexe c'est lorsqu'on passe directement dans un paramètre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    method( Optional.empty() );
    Car pour déterminer le paramétrage de empty(), il faut connaitre le type exact du paramètre de méthode.
    Or le compilateur doit rechercher la méthode à appeler selon les paramètre qu'elle reçoit... et donc selon le retour exact de empty()...
    C'est un peu le serpent qui se mort la queue !
    Surtout qu'avec la surcharge de méthode ca peut bien complexifier la chose...

    J'avais vu quelques discussions sur le sujet, et cela avait nécessité pas mal de modification du compilateur...



    Citation Envoyé par thelvin Voir le message
    Comme cela implique la création d'un objet supplémentaire et des appels de méthodes en plus, on ne peut pas toujours se permettre de s'en servir pour lever les ambiguïtés. Mais pour définir des APIs générales, ça soulage pas mal.
    Ca soulage mais perso j'aurais préféré avoir des références non-null... sans avoir à passer par un type supplémentaire, et avec des vérifs du compilateur.
    Mais je ne sais pas si cela aurait pu s'insérer dans le langage sans poser de problème...


    a++

  8. #8
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 900
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 900
    Billets dans le blog
    54
    Par défaut
    Citation Envoyé par joel.drigo Voir le message
    Que pensez-vous de cette classe Optional de Java8 ?
    J'aime bien et je commence a l'utiliser un peu partout. Après, comme l'indique thelvin, et c'est un constat global sur l'utilisation des lambda sur le JDK8, on passe notre temps a créer de petits objets temporaires de courte de durée de vie, et donc d'un coté on rend le code plus lisible mais de l'autre on le rend aussi peut-etre moins performant/moins bien géré.

    Je trouve qu'il manque cependant une méthode ifNotPresent()/ifEmpty() car pour le moment dans les UI je me trouve a devoir faire des trucs du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    myOptional.ifPresent(truc -> [...]);
    if (!myOptional.isPresent()) {
      [...]
    }
    J'aurai préféré pouvoir faire quelque chose dans le genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    myOptional.ifPresent(truc -> [...]);
    myOptional.ifNotPresent(() -> [...]);
    // Ou
    myOptional.ifPresent(truc -> [...]);
    myOptional.ifEmpty(() -> [...]);
    Ou même mieux:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    myOptional.ifPresent(truc -> [...]).ifNotPresent(() -> [...]);
    // Ou
    myOptional.ifPresent(truc -> [...]).ifEmpty(() -> [...]);
    Les methodes orElse(), orElseGet() et orElseThrow() ne me satisfaisant pas (toujours dans le cadre d'un usage dans une UI).
    Bref l'API est perfectible.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  9. #9
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Ca soulage mais perso j'aurais préféré avoir des références non-null... sans avoir à passer par un type supplémentaire, et avec des vérifs du compilateur.
    Mais je ne sais pas si cela aurait pu s'insérer dans le langage sans poser de problème...
    Moi aussi j'aurais préféré des références non null, mais je suppose également que l'impact sur le langage serait probablement assez colossale, en particulier pour le côté évolutions syntaxiques nécessitées par le typage (ça me rapelle un peu le type Any de powerbuilder) pour pouvoir invoquer des méthodes de traitement, comme celles de la classe Optional. Sans parler de la compatibilité ascendante. D'un autre côté, les deux systèmes ne sont pas exclusifs (ce n'est d'ailleurs pas tout à fait la même chose) et pourraient cohabiter.

    Citation Envoyé par bouye Voir le message
    J'aime bien et je commence a l'utiliser un peu partout. Après, comme l'indique thelvin, et c'est un constat global sur l'utilisation des lambda sur le JDK8, on passe notre temps a créer de petits objets temporaires de courte de durée de vie, et donc d'un coté on rend le code plus lisible mais de l'autre on le rend aussi peut-etre moins performant/moins bien géré.
    J'ai effectivement pensé immédiatement à ce problème en m'en servant la première fois. D'autant plus qu'on ne peut même pas faire de pool.

    Citation Envoyé par bouye Voir le message
    Je trouve qu'il manque cependant une méthode ifNotPresent()/ifEmpty() ...
    Je suis d'accord. Une proposition à faire pour Java9, peut être ? On est pas les seuls à y penser en tout cas, et on trouve des solutions pour résoudre ce cas, comme cet exemple (pas complètement satisfaisant à mon goût, mais l'idée de base est là), trouvé sur stackoverflow :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class OptionalEx {
        private boolean isPresent;
     
        private OptionalEx(boolean isPresent) {
            this.isPresent = isPresent;
        }
     
        public void orElse(Runnable runner) {
            if (!isPresent) {
                runner.run();
            }
        }
     
        public static <T> OptionalEx ifPresent(Optional<T> opt, Consumer<? super T> consumer) {
            if (opt.isPresent()) {
                consumer.accept(opt.get());
                return new OptionalEx(true);
            }
            return new OptionalEx(false);
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    import static com.example.OptionalEx.ifPresent;
     
    ...
     
    ifPresent(opt, x -> System.out.println("found " + x))
        .orElse(() -> System.out.println("NOT FOUND"));
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  10. #10
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par joel.drigo Voir le message
    Citation Envoyé par bouye Voir le message
    J'aime bien et je commence a l'utiliser un peu partout. Après, comme l'indique thelvin, et c'est un constat global sur l'utilisation des lambda sur le JDK8, on passe notre temps a créer de petits objets temporaires de courte de durée de vie, et donc d'un coté on rend le code plus lisible mais de l'autre on le rend aussi peut-etre moins performant/moins bien géré.
    J'ai effectivement pensé immédiatement à ce problème en m'en servant la première fois. D'autant plus qu'on ne peut même pas faire de pool.
    Mais avez-vous vraiment constaté un coût à cela ?

    Parce qu'il ne faut pas oublier que la JVM sait faire de l'Escape Analysis (depuis Java 6 via des flags, puis activé par défaut dans Java 7 si je ne dis pas de bêtises).

    Cela permet à la JVM d'analyser la portée des variables locales, et de déterminer si elle reste confinée au même thread et au bloc d'exécution de la méthode.
    Si c'est le cas, la JVM peut stocker l'objet dans le stack au lieu du heap (donc pas de travail pour le GC, de meilleure perfs à l'exécution grace aux caches-CPU).
    Mieux : couplé à l'inlining il lui est possible de ne pas instancier du tout l'objet, en créant une (ou plusieurs) variables locales.

    Par exemple le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        Optional<String> optional = Optional.of(value);
        optional.ifPresent(System.out::println);
    Avec l'inlining il peut déjà être compilé en quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        Optional<String> optional = new Optional<>(value)
        if (optional.value!=null) {
            Consumer<String> consumer = System.out::println;
            consumer.accept(value);
        }
    Et si la variable "optional" ne sort pas de la méthode, elle peut carrément ne pas être instancié et remplacé par ses champs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        String tmp$Optional$value = value;
        if (tmp$Optional$value !=null) {
            Consumer<String> consumer = System.out::println;
            consumer.accept(tmp$Optional$value);
        }
    Plus d'info ici : http://www.ibm.com/developerworks/ja...index.html#2.1




    a++

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Question au sujet des crochets pour les listes
    Par LinuxUser dans le forum Prolog
    Réponses: 7
    Dernier message: 28/08/2008, 00h01
  2. question au sujet des threads
    Par Portanoo dans le forum Général Python
    Réponses: 1
    Dernier message: 31/07/2008, 17h29
  3. Questions au sujet des archives et des packages
    Par lecharcutierdelinux dans le forum Administration
    Réponses: 17
    Dernier message: 15/06/2007, 09h14
  4. Questions au sujet des activex
    Par Sonic dans le forum VB.NET
    Réponses: 1
    Dernier message: 14/04/2007, 12h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo