web-dev-qa-db-fra.com

Qu'est-ce qu'un type brut et pourquoi ne devrions-nous pas l'utiliser?

Des questions:

  • Quels sont les types bruts en Java et pourquoi est-ce que j'entends souvent dire qu'ils ne devraient pas être utilisés dans du nouveau code?
  • Quelle est l'alternative si nous ne pouvons pas utiliser de types bruts, et comment est-il meilleur?
603

Qu'est-ce qu'un type brut?

La spécification de langage Java définit un type brut comme suit:

types bruts JLS 4.8

Un type brut est défini comme étant l'un des suivants:

  • Le type de référence formé en prenant le nom d'une déclaration de type générique sans liste d'arguments de type associée.

  • Un type de tableau dont le type d'élément est un type brut.

  • Un type de membre non -static de type brut R qui n'est pas hérité d'une superclasse ou d'une superinterface de R.

Voici un exemple pour illustrer:

public class MyType<E> {
    class Inner { }
    static class Nested { }

    public static void main(String[] args) {
        MyType mt;          // warning: MyType is a raw type
        MyType.Inner inn;   // warning: MyType.Inner is a raw type

        MyType.Nested nest; // no warning: not parameterized type
        MyType<Object> mt1; // no warning: type parameter given
        MyType<?> mt2;      // no warning: type parameter given (wildcard OK!)
    }
}

Ici, MyType<E> est un type paramétré ( JLS 4.5 ). Il est courant de désigner familièrement ce type comme étant simplement MyType en bref, mais techniquement, le nom est MyType<E>.

mt a un type brut (et génère un avertissement de compilation) par le premier point dans la définition ci-dessus; inn a également un type brut par le troisième point.

MyType.Nested n'est pas un type paramétré, même s'il s'agit d'un type de membre d'un type paramétré MyType<E>, car il s'agit de static.

mt1 et mt2 sont tous deux déclarés avec les paramètres de type réels, de sorte qu'ils ne sont pas des types bruts.


Qu'est-ce qui rend les types bruts si particuliers?

Les types bruts se comportent essentiellement comme avant l’introduction des génériques. C'est-à-dire que ce qui suit est tout à fait légal au moment de la compilation.

List names = new ArrayList(); // warning: raw type!
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // not a compilation error!

Le code ci-dessus fonctionne correctement, mais supposons que vous disposiez également des éléments suivants:

for (Object o : names) {
    String name = (String) o;
    System.out.println(name);
} // throws ClassCastException!
  //    Java.lang.Boolean cannot be cast to Java.lang.String

Nous avons maintenant des problèmes au moment de l'exécution, car names contient quelque chose qui n'est pas un instanceof String.

Vraisemblablement, si vous voulez que names ne contienne que String, vous pourrait peut-être toujours utiliser un type brut et vérifier manuellement chaque add vous-même, puis transtypé manuellement vers String chaque élément de names. Encore mieux , bien que ce ne soit PAS d'utiliser un type brut et laissez le compilateur faire tout le travail pour vous , exploitant la puissance des Java génériques.

List<String> names = new ArrayList<String>();
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // compilation error!

Bien sûr, si DO == voulez que names autorise une Boolean, vous pouvez alors le déclarer comme List<Object> names, et ce qui précède. le code compilerait.

Voir également


En quoi un type brut est-il différent d'utiliser <Object> comme paramètres de type?

Voici une citation de Effective Java 2e édition, élément 23: n'utilisez pas de types bruts dans le nouveau code :

Quelle est la différence entre le type brut List et le type paramétré List<Object>? En gros, le premier a opté pour la vérification de type générique, tandis que le second a explicitement indiqué au compilateur qu'il est capable de contenir des objets de tout type. Vous pouvez passer un List<String> à un paramètre de type List, mais vous ne pouvez pas le transmettre à un paramètre de type List<Object>. Il existe des règles de sous-typage pour les génériques et List<String> est un sous-type du type brut List, mais pas du type paramétré List<Object>. En conséquence, vous perdez la sécurité de type si vous utilisez un type brut comme List, mais pas si vous utilisez un type paramétré comme List<Object>.

Pour illustrer ce propos, considérons la méthode suivante qui prend un List<Object> et ajoute une new Object().

void appendNewObject(List<Object> list) {
   list.add(new Object());
}

Les génériques dans Java sont invariants. Un List<String> n'est pas un List<Object>, le message suivant générerait donc un avertissement du compilateur:

List<String> names = new ArrayList<String>();
appendNewObject(names); // compilation error!

Si vous aviez déclaré appendNewObject prendre un type brut List en tant que paramètre, la compilation serait alors effectuée et vous perdriez donc le type de sécurité obtenu avec les génériques.

Voir également


En quoi un type brut est-il différent d'utiliser <?> comme paramètre de type?

List<Object>, List<String>, etc sont tous List<?>, il peut donc être tentant de simplement dire qu'ils sont simplement List à la place. Cependant, il y a une différence majeure: comme un List<E> ne définit que add(E), vous ne pouvez ajouter aucun objet arbitraire à un List<?>. D'autre part, étant donné que le type brut List n'a pas le type de sécurité, vous pouvez add à peu près n'importe quoi sur un List.

Considérez la variante suivante de l'extrait précédent:

static void appendNewObject(List<?> list) {
    list.add(new Object()); // compilation error!
}
//...

List<String> names = new ArrayList<String>();
appendNewObject(names); // this part is fine!

Le compilateur a fait un travail remarquable en vous protégeant d’une violation potentielle de l’invariance de type de List<?>! Si vous aviez déclaré le paramètre comme type brut List list, le code se compilerait et vous violeriez le type invariant de List<String> names.


Un type brut est l'effacement de ce type

Retour à JLS 4.8:

Il est possible d'utiliser comme type l'effacement d'un type paramétré ou l'effacement d'un type tableau dont le type d'élément est un type paramétré. Un tel type s'appelle un type brut .

[...]

Les superclasses (respectivement, les superinterfaces) d'un type brut sont les effacements des superclasses (superinterfaces) de l'un des paramétrisations du type générique.

Le type d'un constructeur, d'une méthode d'instance ou d'un champ non -static de type brut C qui n'est pas hérité de ses superclasses ou superinterfaces est le type brut qui correspond à l'effacement de son type dans déclaration générique correspondant à C.

En termes plus simples, lorsqu'un type brut est utilisé, les constructeurs, les méthodes d'instance et les champs non -static sont également effacé .

Prenons l'exemple suivant:

class MyType<E> {
    List<String> getNames() {
        return Arrays.asList("John", "Mary");
    }

    public static void main(String[] args) {
        MyType rawType = new MyType();
        // unchecked warning!
        // required: List<String> found: List
        List<String> names = rawType.getNames();
        // compilation error!
        // incompatible types: Object cannot be converted to String
        for (String str : rawType.getNames())
            System.out.print(str);
    }
}

Lorsque nous utilisons le brut MyType, getNames est également effacé, de sorte qu'il renvoie un brut List!

JLS 4.6 continue d'expliquer ce qui suit:

L'effacement de type mappe également la signature d'un constructeur ou d'une méthode à une signature qui n'a pas de types paramétrés ni de variables de type. L'effacement d'une signature de constructeur ou de méthode s est une signature composée du même nom que s et des effacements de tous les types de paramètres formels indiqués dans s.

Le type de retour d'une méthode et les paramètres de type d'une méthode ou d'un constructeur générique sont également effacés si la signature de la méthode ou du constructeur est effacée.

L'effacement de la signature d'une méthode générique n'a aucun paramètre de type.

Le rapport de bogue suivant contient quelques réflexions de Maurizio Cimadamore, un développeur de compilateur, et Alex Buckley, un des auteurs du JLS, sur les raisons pour lesquelles ce type de comportement devrait se produire: https://bugs.openjdk.Java .net/browse/JDK-6400189 . (En bref, cela simplifie la spécification.)


Si c'est dangereux, pourquoi est-il permis d'utiliser un type brut?

Voici une autre citation de JLS 4.8:

L'utilisation de types bruts n'est autorisée qu'à titre de concession à la compatibilité du code hérité. L'utilisation de types bruts dans du code écrit après l'introduction de la généricité dans le langage de programmation Java est fortement déconseillée. Il est possible que les futures versions de la programmation Java la langue interdira l'utilisation des types bruts.

Effective Java 2e édition a également ceci à ajouter:

Étant donné que vous ne devriez pas utiliser de types bruts, pourquoi les concepteurs de langage les ont-ils autorisés? Pour assurer la compatibilité.

La plate-forme Java était sur le point d'entrer dans sa deuxième décennie, lorsque les génériques ont été introduits, et il existait une quantité énorme de code Java qui n'utilisait pas de génériques. Il a été jugé essentiel que tout ce code reste légal et interopérable avec le nouveau code qui utilise des génériques. Il devait être légal de passer des instances de types paramétrés à des méthodes conçues pour être utilisées avec des types ordinaires, et inversement. Cette exigence, connue sous le nom de compatibilité de migration , a motivé la décision de prendre en charge les types bruts.

En résumé, les types bruts ne doivent JAMAIS être utilisés dans le nouveau code. Vous devez toujours utiliser des types paramétrés .


N'y a-t-il aucune exception?

Malheureusement, étant donné que les génériques Java ne sont pas réifiés, il existe deux exceptions où les types bruts doivent être utilisés dans le nouveau code:

  • Littéraux de classe, par exemple List.class, pas List<String>.class
  • instanceof opérande, par ex. o instanceof Set, pas o instanceof Set<String>

Voir également

697

Quels sont les types bruts en Java et pourquoi est-ce que j'entends souvent dire qu'ils ne devraient pas être utilisés dans du nouveau code?

Les types bruts sont une histoire ancienne du langage Java. Au début, il y avait Collections et ils ne tenaient Objects ni plus ni moins. Chaque opération sur Collections requise nécessite de Object vers le type souhaité.

List aList = new ArrayList();
String s = "Hello World!";
aList.add(s);
String c = (String)aList.get(0);

Bien que cela ait fonctionné la plupart du temps, des erreurs se sont produites

List aNumberList = new ArrayList();
String one = "1";//Number one
aNumberList.add(one);
Integer iOne = (Integer)aNumberList.get(0);//Insert ClassCastException here

Les anciennes collections sans type ne pouvaient pas appliquer la sécurité de type, le programmeur devait donc se rappeler ce qu'il stockait dans une collection.
Les génériques ont été inventés pour contourner cette limitation, le développeur déclare le type stocké une fois et le compilateur le fait à la place.

List<String> aNumberList = new ArrayList<String>();
aNumberList.add("one");
Integer iOne = aNumberList.get(0);//Compile time error
String sOne = aNumberList.get(0);//works fine

En comparaison:

// Old style collections now known as raw types
List aList = new ArrayList(); //Could contain anything
// New style collections with Generics
List<String> aList = new ArrayList<String>(); //Contains only Strings

Plus complexe l'interface Comparable:

//raw, not type save can compare with Other classes
class MyCompareAble implements CompareAble
{
   int id;
   public int compareTo(Object other)
   {return this.id - ((MyCompareAble)other).id;}
}
//Generic
class MyCompareAble implements CompareAble<MyCompareAble>
{
   int id;
   public int compareTo(MyCompareAble other)
   {return this.id - other.id;}
}

Notez qu'il est impossible d'implémenter l'interface CompareAble avec compareTo(MyCompareAble) avec des types bruts. Pourquoi vous ne devriez pas les utiliser:

  • Tout Object stocké dans un Collection doit être converti avant de pouvoir être utilisé
  • L'utilisation de génériques permet d'effectuer des contrôles de compilation
  • Utiliser des types bruts revient à stocker chaque valeur sous la forme Object

Que fait le compilateur? Les génériques sont compatibles avec les versions antérieures, ils utilisent les mêmes classes Java que les types bruts. La magie se produit surtout au moment de la compilation.

List<String> someStrings = new ArrayList<String>();
someStrings.add("one");
String one = someStrings.get(0);

Sera compilé comme:

List someStrings = new ArrayList();
someStrings.add("one"); 
String one = (String)someStrings.get(0);

C'est le même code que vous écririez si vous utilisiez directement les types bruts. Bien que je ne sois pas sûr de ce qui se passe avec l'interface CompareAble, je suppose qu'elle crée deux fonctions compareTo, l'une prenant MyCompareAble et l'autre prenant Object, et passant au premier après l'avoir coulé.

Quelles sont les alternatives aux types bruts: Utilisez génériques

58
josefx

Un type brut est le nom d'une classe ou d'une interface générique sans aucun argument de type. Par exemple, étant donné la classe Box générique:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

Pour créer un type paramétré de Box<T>, vous devez fournir un argument de type réel pour le paramètre de type formel T:

Box<Integer> intBox = new Box<>();

Si l'argument de type réel est omis, vous créez un type brut de Box<T>:

Box rawBox = new Box();

Par conséquent, Box est le type brut du type générique Box<T>. Toutefois, une classe ou un type d'interface non générique n'est pas un type brut.

Les types bruts apparaissent dans le code hérité car de nombreuses classes d'API (telles que les classes Collections) n'étaient pas génériques avant JDK 5.0. Lorsque vous utilisez des types bruts, vous obtenez essentiellement un comportement pré-générique - un Box vous donne Objects. Pour la compatibilité ascendante, l’affectation d’un type paramétré à son type brut est autorisée:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;               // OK

Mais si vous affectez un type brut à un type paramétré, vous recevez un avertissement:

Box rawBox = new Box();           // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox;     // warning: unchecked conversion

Vous recevez également un avertissement si vous utilisez un type brut pour appeler des méthodes génériques définies dans le type générique correspondant:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8);  // warning: unchecked invocation to set(T)

L'avertissement indique que les types bruts contournent les vérifications de type génériques, reportant la capture du code non sécurisé à l'exécution. Par conséquent, vous devriez éviter d'utiliser des types bruts.

La section Type Erasure contient plus d'informations sur la manière dont le compilateur Java utilise les types bruts.

Messages d'erreur non vérifiés

Comme mentionné précédemment, lorsque vous mélangez du code hérité avec du code générique, vous pouvez rencontrer des messages d'avertissement semblables aux suivants:

Remarque: Example.Java utilise des opérations non contrôlées ou non sécurisées.

Remarque: Recompiler avec -Xlint: décoché pour plus de détails.

Cela peut se produire lors de l'utilisation d'une ancienne API qui fonctionne sur des types bruts, comme illustré dans l'exemple suivant:

public class WarningDemo {
    public static void main(String[] args){
        Box<Integer> bi;
        bi = createBox();
    }

    static Box createBox(){
        return new Box();
    }
}

Le terme "décoché" signifie que le compilateur ne dispose pas d'assez d'informations sur le type pour effectuer toutes les vérifications de type nécessaires pour assurer la sécurité du type. L'avertissement "non coché" est désactivé par défaut, bien que le compilateur donne un indice. Pour voir tous les avertissements "non contrôlés", recompilez avec -Xlint: non cochée.

La recompilation de l'exemple précédent avec -Xlint: non cochée révèle les informations supplémentaires suivantes:

WarningDemo.Java:4: warning: [unchecked] unchecked conversion
found   : Box
required: Box<Java.lang.Integer>
        bi = createBox();
                      ^
1 warning

Pour désactiver complètement les avertissements non vérifiés, utilisez l'indicateur -Xlint: -unchecked. L'annotation @SuppressWarnings("unchecked") supprime les avertissements non contrôlés. Si vous ne connaissez pas la syntaxe @SuppressWarnings, reportez-vous à la section Annotations.

Source originale: Tutoriels Java

24
Adelin
 private static List<String> list = new ArrayList<String>();

Vous devez spécifier le type-paramètre.

L'avertissement indique que les types définis pour prendre en charge génériques doivent être paramétrés plutôt que d'utiliser leur forme brute.

List est défini pour prendre en charge les génériques: public class List<E>. Cela permet de nombreuses opérations sécurisées, qui sont vérifiées à la compilation.

19
Bozho

Un type "brut" dans Java est une classe non générique qui traite des objets "bruts", plutôt que des paramètres de type générique sûrs pour le type.

Par exemple, avant que Java génériques soit disponible, vous utiliseriez une classe de collection comme celle-ci:

LinkedList list = new LinkedList();
list.add(new MyObject());
MyObject myObject = (MyObject)list.get(0);

Lorsque vous ajoutez votre objet à la liste, son type importe peu, et lorsque vous le récupérez dans la liste, vous devez le convertir explicitement en un type que vous attendez.

En utilisant des génériques, vous supprimez le facteur "inconnu", car vous devez spécifier explicitement le type d'objets pouvant figurer dans la liste:

LinkedList<MyObject> list = new LinkedList<MyObject>();
list.add(new MyObject());
MyObject myObject = list.get(0);

Notez qu'avec les génériques, il n'est pas nécessaire de convertir l'objet provenant de l'appel get, la collection est prédéfinie pour fonctionner uniquement avec MyObject. Ce fait est le principal facteur déterminant pour les génériques. Cela change une source d'erreurs d'exécution en quelque chose qui peut être vérifié lors de la compilation.

16
Andy White

Ici, je considère plusieurs cas à travers lesquels vous pouvez clarifier le concept

1. ArrayList<String> arr = new ArrayList<String>();
2. ArrayList<String> arr = new ArrayList();
3. ArrayList arr = new ArrayList<String>();

Cas 1

ArrayList<String> arr c'est une variable de référence ArrayList de type String qui fait référence à un objet ArralyList de type String. Cela signifie qu'il ne peut contenir que Object de type String.

C'est un Strict to String pas un type brut alors, il ne déclenchera jamais un avertissement.

    arr.add("hello");// alone statement will compile successfully and no warning.

    arr.add(23);  //prone to compile time error.
     //error: no suitable method found for add(int)

Cas 2

Dans ce cas, ArrayList<String> arr est un type strict, mais votre objet new ArrayList(); est un type brut.

    arr.add("hello"); //alone this compile but raise the warning.
    arr.add(23);  //again prone to compile time error.
    //error: no suitable method found for add(int)

ici arr est un type strict. Donc, il va générer une erreur de compilation lors de l'ajout d'un integer.

Avertissement: - Un objet Type Raw est référencé à une variable référencée de type Strict de ArrayList.

Cas 3

Dans ce cas, ArrayList arr est un type brut mais votre objet new ArrayList<String>(); est un type Strict.

    arr.add("hello");  
    arr.add(23);  //compiles fine but raise the warning.

Il y ajoutera n'importe quel type d'objet car arr est un type brut.

Avertissement: - Un objet de type Strict est référencé à une variable référencée de type raw.

12
Vikrant Kashyap

Le compilateur veut que vous écriviez ceci:

private static List<String> list = new ArrayList<String>();

sinon, vous pourriez ajouter le type de votre choix dans list, rendant l'instanciation sous la forme new ArrayList<String>() inutile. Les génériques Java sont uniquement une fonctionnalité de compilation; ainsi, un objet créé avec new ArrayList<String>() acceptera avec plaisir les éléments Integer ou JFrame s'il est affecté à une référence de type "raw". type "List - l'objet lui-même ne sait rien des types qu'il est censé contenir, seul le compilateur le sait.

12
Michael Borgwardt

Qu'est-ce qu'un type brut et pourquoi j'entends souvent dire qu'il ne devrait pas être utilisé dans un nouveau code?

Un "type brut" est l'utilisation d'une classe générique sans spécifier d'argument (s) de type pour ses types paramétrés, par ex. en utilisant List au lieu de List<String>. Lorsque les génériques ont été introduits dans Java, plusieurs classes ont été mises à jour pour utiliser des génériques. L'utilisation de ces classes en tant que "type brut" (sans spécifier d'argument de type) permettait au code hérité de continuer à être compilé.

Les "types bruts" sont utilisés pour la compatibilité ascendante. Leur utilisation dans le nouveau code n'est pas recommandée car l'utilisation de la classe générique avec un argument de type permet un typage plus puissant, ce qui peut améliorer la compréhensibilité du code et permettre de détecter plus tôt les problèmes potentiels.

Quelle est l'alternative si nous ne pouvons pas utiliser les types bruts, et comment est-il meilleur?

L'alternative préférée consiste à utiliser les classes génériques comme prévu - avec un argument de type approprié (par exemple, List<String>). Cela permet au programmeur de spécifier les types de manière plus spécifique, donne plus de signification aux futurs responsables de la maintenance sur l'utilisation prévue d'une structure de variable ou de données et permet au compilateur de renforcer la sécurité de type. La combinaison de ces avantages peut améliorer la qualité du code et aider à prévenir l’introduction de certaines erreurs de codage.

Par exemple, pour une méthode où le programmeur veut s'assurer qu'une variable de la liste nommée 'noms' ne contient que des chaînes:

List<String> names = new ArrayList<String>();
names.add("John");          // OK
names.add(new Integer(1));  // compile error
11
Bert F

Un type brut - est le manque d'un paramètre type lors de l'utilisation d'un type générique.

Le type brut ne doit pas être utilisé car cela pourrait provoquer des erreurs d'exécution, telles que l'insertion d'un double dans ce qui était supposé être un Set sur ints.

Set set = new HashSet();
set.add(3.45); //ok

Lors de la récupération des éléments de la Set, vous ne savez pas ce qui sort. Supposons que vous vous attendiez à ce que ce soit tout ints, vous le transmettez à Integer; exception à l'exécution lorsque la double 3.45 se présente.

Avec un type paramètre ajouté à votre Set, vous obtiendrez immédiatement une erreur de compilation. Cette erreur préventive vous permet de résoudre le problème avant que quelque chose ne se produise lors de l'exécution (gain de temps et d'efforts).

Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.
8
Lars Andren

Voici un autre cas où les types bruts vont vous mordre:

public class StrangeClass<T> {
  @SuppressWarnings("unchecked")
  public <X> X getSomethingElse() {
    return (X)"Testing something else!";
  }

  public static void main(String[] args) {
    final StrangeClass<String> withGeneric    = new StrangeClass<>();
    final StrangeClass         withoutGeneric = new StrangeClass();
    final String               value1,
                               value2;

    // Compiles
    value1 = withGeneric.getSomethingElse();

    // Produces compile error:
    // incompatible types: Java.lang.Object cannot be converted to Java.lang.String
    value2 = withoutGeneric.getSomethingElse();
  }
}

Comme indiqué dans la réponse acceptée, vous perdez toute prise en charge des génériques dans le code du type brut. Chaque paramètre de type est converti en son effacement (ce qui dans l'exemple ci-dessus n'est que Object).

6
GuyPaddock

Ce que vous dites, c'est que votre list est un List d'objets non spécifiés. C'est-à-dire que Java ne sait pas quel type d'objets se trouvent dans la liste. Ensuite, lorsque vous souhaitez parcourir la liste, vous devez convertir chaque élément pour pouvoir accéder aux propriétés de cet élément (dans ce cas, String).

En règle générale, il est préférable de paramétrer les collections. Ainsi, vous n’aurez aucun problème de conversion, vous ne pourrez ajouter que des éléments du type paramétré et votre éditeur vous proposera les méthodes appropriées.

private static List<String> list = new ArrayList<String>();
5
pakore

page du tutoriel .

Un type brut est le nom d'une classe ou d'une interface générique sans aucun argument de type. Par exemple, étant donné la classe Box générique:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

Pour créer un type paramétré de Box, vous devez fournir un argument de type réel pour le paramètre de type formel T:

Box<Integer> intBox = new Box<>();

Si l'argument de type actuel est omis, vous créez un type brut de Box:

Box rawBox = new Box();
4

Évitez les types bruts

Les types bruts font référence à l’utilisation d’un type générique sans spécifier de paramètre de type.

Par exemple ,

Une liste est un type brut, tandis que List<String> est un type paramétré.

Lors de l'introduction des génériques dans JDK 1.5, les types bruts n'étaient conservés que pour préserver la compatibilité avec les versions antérieures de Java. Bien que l’utilisation de types bruts soit toujours possible,

Ils devraient être évités :

  • Ils nécessitent généralement des moulages
  • Ils ne sont pas sûrs en termes de sécurité, et certains types d'erreur importants n'apparaîtront qu'au moment de l'exécution.
  • Ils sont moins expressifs et ne s'auto-documentent pas de la même manière que les types paramétrés Exemple

    import Java.util.*;
    
    public final class AvoidRawTypes {
    
    void withRawType() {
    
        //Raw List doesn't self-document, 
        //doesn't state explicitly what it can contain
    
        List stars = Arrays.asList("Arcturus", "Vega", "Altair");
    
        Iterator iter = stars.iterator();
    
        while (iter.hasNext()) {
    
            String star = (String) iter.next(); //cast needed
    
            log(star);
        }
    
    }
    
    void withParameterizedType() {
    
        List < String > stars = Arrays.asList("Spica", "Regulus", "Antares");
    
        for (String star: stars) {
    
            log(star);
        }
    
    }
    
    private void log(Object message) {
    
        System.out.println(Objects.toString(message));
    
    }
    
    }
    

Pour référence : https://docs.Oracle.com/javase/tutorial/Java/generics/rawTypes.html

1
Ashish

J'ai trouvé cette page après avoir fait quelques exemples d'exercices et eu exactement le même étonnement.

============== Je suis passé de ce code tel que fourni par l'exemple ===============

public static void main(String[] args) throws IOException {

    Map wordMap = new HashMap();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator i = wordMap.entrySet().iterator(); i.hasNext();) {
        Map.Entry entry = (Map.Entry) i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

====================== Pour ce code =======================

public static void main(String[] args) throws IOException {
    // replace with TreeMap to get them sorted by name
    Map<String, Integer> wordMap = new HashMap<String, Integer>();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator<Entry<String, Integer>> i = wordMap.entrySet().iterator(); i.hasNext();) {
        Entry<String, Integer> entry =   i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

}

=============================================== =============================

Cela peut être plus sûr mais il a fallu 4 heures pour démudier la philosophie ...

1
user2442615

Les types bruts sont bien quand ils expriment ce que vous voulez exprimer.

Par exemple, une fonction de désérialisation peut renvoyer un List, mais elle ne connaît pas le type d'élément de la liste. Donc, List est le type de retour approprié ici.

0
Stefan Reich