web-dev-qa-db-fra.com

Java génériques "capture de?"

Je travaille avec un TreeTable et lorsque je change d’usine de cellules, je dois passer un

Callback<TreeTableColumn<A, capture of ?>, TreeTableCell<A, capture of ?>>

où A est une classe avec laquelle je travaille mais je ne sais pas comment travailler avec la "capture de"?

J'ai essayé de créer

new Callback<TreeTableColumn<A, ?>, TreeTableCell<A, ?>>

mais IDEA affiche un avertissement

setCellFactory(Callback<TreeTableColumn<A, capture<?>>, TreeTableCell<A, capture<?>>>) in TreeTableColumn cannot be applied to (anonymous Callback<TreeTableColumn<A, ?>, TreeTableCell<A, ?>>)

J'ai essayé d'utiliser des classes spécifiques (comme String) au lieu de "?" aussi, mais rien n'y fait.

Quelqu'un pourrait-il m'expliquer comment travailler avec cela?

Merci.

MODIFIER:

J'ai rassemblé un peu plus d'informations .. le CellFactory de TreeTableColumn<S,T> devrait être Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>>, cependant, la TreeTableColumn avec laquelle je travaille est créée en tant que type brut (dans une bibliothèque).

L'utilisation d'un rappel de type brut fonctionne. Mais existe-t-il d'autres options pour contourner ce problème?

20
kotycheese

Un caractère générique représente un type inconnu.

capture générique est le processus de liaison de la valeur d'un type générique à une nouvelle variable de type. Par exemple:

List<?> list = ...;
shuffle(list);

<T> void shuffle(List<T> list) {
    ...
}

Ici, la valeur inconnue de ? est lié à la nouvelle variable de type T lors de l'appel de la méthode shuffle, permettant à la méthode shuffle de faire référence à ce type.

Le compilateur Java représente en interne la valeur d'un caractère générique en le capturant dans une variable de type anonyme, qu'il appelle "capture de?" (En fait, javac les appelle "capture # 1 de?" Car différentes utilisations de ? peut faire référence à différents types, et donc avoir différentes captures).

Ok, alors qu'est-ce qui ne va pas dans votre code? Vous essayez d'invoquer une méthode

<S,T> setCellFactory(Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> factory);

avec

Callback<TreeTableColumn<S,?>, TreeTableCell<S, ?>> factory;

Dans la signature de méthode, le paramètre de type T représente un type unique, qui doit être fourni par l'appelant. Par commodité, le compilateur tente automatiquement d'inférer une valeur appropriée (-> inférence de type). Votre erreur de compilation signifie que le compilateur n'a pas pu le faire.

Dans ce cas, il ne s'agit pas d'une lacune de l'inférence de type, car il est en fait impossible d'attribuer une valeur appropriée à T, car les deux ? doivent être des sous-types de T, mais le compilateur ne peut pas savoir que les deux ? représente le même type, ou même des types associés.

Pour appeler avec succès cette méthode, votre type d'argument doit utiliser le même type pour toutes les occurrences de T. Si vous avez déjà un tel type à portée de main, allez-y et utilisez-le. Sinon, vous pourrez peut-être en introduire une à l'aide de la capture générique:

setCellFactory(newFactory());

<S,T> Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> newFactory() {
    return new Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> {
        ...
    }
}
15
meriton

d'après ce que j'ai trouvé de qu'est-ce qu'une conversion de capture et documents de capture génériques Oracle il semble que vous rencontriez un problème où le compilateur ne peut pas trouver la classe d'assistance nécessaire, ou essaie de placer l'objet là-dedans, mais ce que vous lui donnez ne peut pas être converti en toute sécurité.

MODIFIER:

DEFAULT_CELL_FACTORY

public static final Callback<TreeTableColumn<?,?>,TreeTableCell<?,?>>

Si aucun cellFactory n'est spécifié sur une instance TreeTableColumn, alors celle-ci sera utilisée par défaut. À l'heure actuelle, il rend simplement la propriété d'élément TableCell dans la propriété graphique si l'élément est un nœud, ou il appelle simplement toString () s'il n'est pas nul, définissant la chaîne résultante à l'intérieur de la propriété text.

et

setCellFactory

public final void setCellFactory(Callback<TreeTableColumn<S,T>,TreeTableCell<S,T>> value)

Définit la valeur de la propriété cellFactory. Description de la propriété: fabrique de cellules pour toutes les cellules de cette colonne. La fabrique de cellules est responsable du rendu des données contenues dans chaque TreeTableCell pour une seule TreeTableColumn. Par défaut, TreeTableColumn utilise une fabrique de cellules par défaut, mais celle-ci peut être remplacée par une implémentation personnalisée, par exemple pour afficher les données d'une manière différente ou pour prendre en charge la modification. Il y a beaucoup de documentation sur la création d'usines de cellules personnalisées ailleurs (voir Cell et TreeTableView par exemple).

Enfin, un certain nombre d'usines de cellules prédéfinies sont disponibles dans le package javafx.scene.control.cell.

retiré de Java 8 API Doc .

donc quelque chose comme ça devrait aller plus dans la bonne direction:

public static <S> Callback<TableColumn<S,String>, TableCell<S,String>> forTableColumn() {
   return forTableColumn(new DefaultStringConverter());
}

ou quelque chose comme ça en fonction de ce que vous voulez donner exactement dans la cellule.

setCellFactory(TextFieldTableCell.<DataModel, Integer>forTableColumn(new IntegerStringConverter()));

ces extraits de code sont tirés de Ce fil StackOverflow

et enfin ce lien pourrait vous aider aussi: Tutoriel CellView TableView

Cela devrait donc vous donner plus de lumière dans l'obscurité sur ce qui pourrait être à l'origine du problème.

2
Nico