J'ai un appel de fonction donné et java me donne une erreur car les objets ne sont pas comparables aux ints (bien sûr ...). Quelqu'un peut-il m'expliquer ce que je dois changer?
J'ai essayé d'accolade l'expression lambda différemment mais sans résultat utile. Je pense que l'expression lambda est correcte et que la fonction de filtre est légèrement fausse, mais je ne suis pas en mesure de trouver mon erreur ...
// function call filter(v -> v > 5) // function public Optional<T> filter(Predicate<T> tester) { if(isPresent() && tester.test(get())) { return this; } else { return Optional.empty(); } }
Je m'attendrais a Optional.empty-Object mais j'obtiens une erreur java car v> 5
Object v n'est pas comparable à un int.
4 Réponses :
Dans les primitives Java, les types (par exemple int
) et les objets (par exemple Object
) n'ont pas d'ancêtre commun dans la hiérarchie des types. En raison de cela, les prédicats et autres constructions de flux sont disponibles en deux versions, par exemple il y a IntPredicate
que vous devez utiliser lorsque vous travaillez avec int
et Predicate
que vous devez utiliser lorsque vous travaillez avec Object
.
Activé la façon d'écrire votre fonction de filtre serait d'utiliser OptionalInt
et IntPredicate
:
public OptionalInt filter(IntPredicate tester) { if (isPresent() && tester.test(get())) { return ... } else { return OptionalInt.empty(); } }
Remarque: Predicate
où T étend le nombre
conviendrait.
@PeterLawrey vous avez absolument raison, la boxe est une autre option.
Existe-t-il un moyen d'y parvenir sans modifier les options
@PeterLawrey utilisant un filtre public facultatif
ne fonctionne malheureusement pas
@Hugugagegi Vous ne pouvez définir
que lorsque vous l'avez déclaré le premier tine, éventuellement sur la ligne class Xxxx
.
Vous devez faire de T
une classe wrapper comparable à un int. par exemple
class MyClass { public IntOptional filter(IntPredicate test) {
est très bien car v
est un int
.
Vous ne pouvez pas utiliser cette expression lorsque T est inconnu.
Ce que vous pouvez faire est de supposer que le T
doit être un nombre, par exemple
class MyClass<T extends Number> { public Optional<T> filter(Predicate<T> test) {
cependant cela produira un ClassCastExpection est T
est un autre type.
La vraie solution est de faire de T
un Number code >
par exemple
filter( v -> ((Number) v).doubleValue() > 5)
ou en faire un type spécifique comme int
IntStream.range(0, 10) .filter(v -> v > 5) .forEach(System.out::println);
La classe est une classe générique. Casting v
en Number
et utiliser doubleValue ()
pour le rendre compatible avec Predicate
ressemble à un hack . Le problème est à la racine: la déclaration T dans la classe.
Je pense que l'expression lambda est correcte et que le la fonction de filtrage est légèrement fausse, mais je ne suis pas en mesure de trouver mon erreur ...
Vous avez raison.
Votre méthode semble vaincre le type générique déclaré pour la classe car tout d'abord votre méthode est définie dans une classe générique.En supposant que votre classe s'appelle
Foo
, ici la méthodefilter ()
repose sur le type génériqueT
comme retour / type de paramètre:public class Foo<T extends Integer>{ // ... public Optional<T> filter(Predicate<T> tester) { // ... } }Cela fonctionne avec l'inférence.
Vous obtenez ainsiPredicate
deT
. Mais leT
dépend du type générique défini dans la classe et aussi de la manière dont vous avez déclaré l'instance de la classeFoo
.
Et il semble qu'iciT
n'est pas unNumber
.Comme alternative, vous pouvez également vous fier à l'inférence à partir de la variable Foo déclarée.
Si vous faites cela:Foo<Integer> foo = new Foo<>(); Optional<Integer> optInt = foo.filter(v -> v > 5);il se compilera correctement car
Integer
sera déduit deFoo
.Je pense donc que pour résoudre votre problème, vous devez déclarer Number ou Integer comme classe de base du type générique:
public class Foo<T>{ // ... public Optional<T> filter(Predicate<T> tester) { // ... } }ou vous fier à inférence du client comme dans l'exemple précédent.
v -> v> 5
peut signifier différentes choses. Cela dépend du contexte.
Il peut s'agir d'un (Object v) -> v> 5
provoquant une erreur de compilation car >
ne peut pas être appliqué à un objet
:
IntStream.of(123, 123).filter(v -> v > 5);
Il peut s'agir d'un (Integer v) -> v> 5
signifiant que le déballage et l'autoboxing seront effectués afin de faire la comparaison et de renvoyer le résultat:
Stream.<Integer>of(123, 123).filter(v -> v > 5);
Il peut s'agir d'un (int v) -> v> 5
signifiant qu'il s'agit d'une instance de IntPredicate
et tout se passera bien ici:
Stream.<Object>of("123", 123).filter(v -> v > 5);
Il serait bon de regarder également le bloc de code complet. Où utilisez-vous
filter
et quel est le résultat que vous essayez d'en déduire?C'est impossible. Vous renvoyez
this
ce qui signifie que votre classe doit étendreOptional
qui estfinal
. Avez-vous votre propreFacultatif
?