Types paramétrés et déclaration

2 réponses
Avatar
Javajug
Bonjour à vous !

J'ai une petite question récurrente qu'on me pose souvent et que
j'aimerai transmettre au "bytecodeurs" ici présents (ou du moins aux
connaisseurs de la JVM) :

Les deux lignes suivantes compilent, mais ont-elles le même résultat au
niveau du bytecode ? (autrement dit, sont-elles strictement identiques
ou l'une vaut-elle mieux que l'autre ?) :

1: List<Double> l1 = new ArrayList();

2: List<Double> l2 = new ArrayList<Double>();

(ce sont bien sûr des java.util.List)

Lorsque l'on fait "Double d1 = l1.get(0)", un cast implicite d'Object
vers Double est-il fait ?

Merci pour votre temps-neurone passé sur cette question !

2 réponses

Avatar
Samuel DEVULDER
Le 10/04/2015 17:54, Javajug a écrit :

1: List<Double> l1 = new ArrayList();

2: List<Double> l2 = new ArrayList<Double>();



$ cat Test.java
import java.util.*;

class Test {
static Double ONE = Double.valueOf(1);

static Double l1() {
List<Double> l1 = new ArrayList();
l1.add(ONE);
return l1.get(0);
}

static Double l2() {
List<Double> l2 = new ArrayList<Double>();
l2.add(ONE);
return l2.get(0);
}

static void main(String arg[]) {
l1();
l2();
}
}
$ javac Test.java
$ javap -c Test
Compiled from "Test.java"
class Test {
static java.lang.Double ONE;

Test();
Code:
0: aload_0
1: invokespecial #1 // Method
java/lang/Object."<init>":()V
4: return

static java.lang.Double l1();
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method
java/util/ArrayList."<init>":()V
7: astore_0
8: aload_0
9: getstatic #4 // Field ONE:Ljava/lang/Double;
12: invokeinterface #5, 2 // InterfaceMethod
java/util/List.add:(Ljava/lang/Object;)Z
17: pop
18: aload_0
19: iconst_0
20: invokeinterface #6, 2 // InterfaceMethod
java/util/List.get:(I)Ljava/lang/Object;
25: checkcast #7 // class java/lang/Double
28: areturn

static java.lang.Double l2();
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method
java/util/ArrayList."<init>":()V
7: astore_0
8: aload_0
9: getstatic #4 // Field ONE:Ljava/lang/Double;
12: invokeinterface #5, 2 // InterfaceMethod
java/util/List.add:(Ljava/lang/Object;)Z
17: pop
18: aload_0
19: iconst_0
20: invokeinterface #6, 2 // InterfaceMethod
java/util/List.get:(I)Ljava/lang/Object;
25: checkcast #7 // class java/lang/Double
28: areturn

static void main(java.lang.String[]);
Code:
0: invokestatic #8 // Method
l1:()Ljava/lang/Double;
3: pop
4: invokestatic #9 // Method
l2:()Ljava/lang/Double;
7: pop
8: return

static {};
Code:
0: dconst_1
1: invokestatic #10 // Method
java/lang/Double.valueOf:(D)Ljava/lang/Double;
4: putstatic #4 // Field ONE:Ljava/lang/Double;
7: return
}

Comme tu peux le voir l1() et l2() ont exactement le même bytecode.

Lorsque l'on fait "Double d1 = l1.get(0)", un cast implicite d'Object
vers Double est-il fait ?



Oui tout à fait. Regarde les lignes 25 de l1() et l2().

Par la suite l'optimiseur du jit peut virer le test du cast s'il prouve
que le type est toujours le même type que celui attendu.

a+

sam.
Avatar
Javajug
Le 10/04/2015 20:30, Samuel DEVULDER a écrit :
Comme tu peux le voir l1() et l2() ont exactement le même bytecode.

Lorsque l'on fait "Double d1 = l1.get(0)", un cast implicite d'Object
vers Double est-il fait ?



Oui tout à fait. Regarde les lignes 25 de l1() et l2().



Super, et un grand merci (un peu tardif dsl) pour ta réponse. C'est bon
à savoir quand on commence à se retrouver avec des types paramétrés un
peu compliqués...

Tu m'as donné envie d'utiliser 'javap -c' plus souvent (en attendant une
vraie formation JVM) !
Je verrai plus tard pour les détails de l'optimisation JIT dans Java...