juillet
2005
L’AutoBoxing/UnBoxing et l’API JDBC
J’aimerais, pour terminer sur l’auto/unboxing, attirer votre attention sur l’API JDBC.
En effet, je trouve que l’introduction de l’AutoBoxing/UnBoxing dans le JDK 5.0 révèle bien l’erreur de ceux qui ont conçu cette API en choisissant de retourner des primitives et non des classes enveloppes.
Imaginer que vous avez une table appelée INDIVIDU avec les éléments suivants:
id NUMBER NOT NULL
nom VARCHAR NOT NULL
prenom VARCHAR NOT NULL
date_naissance DATE NOT NULL
date_marriage DATE NULLABLE
id_conjoint NUMBER NULLABLE
Notez que les éléments id, nom, prenom, et date_naissance sont obligatoires. Ils ne peuvent être à NULL.
Notez également que les éléments date_marriage et id_conjoint peuvent être à NULL. Car tous les individus sont nés à un moment donné, mais pas nécessairement marié.
Maintenant, vous désirez stoquer un individu:
Connection conn = getConnection();
PreparedStatement st = conn.prepareStatement("INSERT INTO INDIVIDU VALUES(?, ?, ?, ?, ?, ?);");
Integer id = 1;
String nom = "Mon enfant";
String prenom = "qui vient de naitre";
java.sql.Date date_naissance = new java.sql.Date();
//Il n'est pas encore marié
java.sql.Date date_marriage = null;
Integer id_conjoint = null;
On pourrait être tenté d’écrire quelque chose comme
st.setInt(1, id);
st.setString(2, nom);
st.setString(3, prenom);
st.setDate(4, date_naissance);
st.setDate(5, date_marriage);
st.setInt(6, id_conjoint);
Mais cela donnerait une NullPointerException sur la dernière ligne. Il faudrait en fait utiliser quelque chose comme
st.setNull(6, java.sql.types.INTEGER);
Maintenant, en supposant que cela est stoqué dans la table, nous allons récupérer les données:
PreparedStatement query = conn.prepareStatement(SELECT * FROM INDIVIDU WHERE ID = ?;");
st.setInt(1, id);
ResultSet rs = query.executeQuery();
if (rs.next()) {
nom = rs.getString(2);
prenom = rs.getString(3);
date_naissance = rs.getDate(4);
date_marriage = rs.getDate(5);
Integer id_conjoint = rs.getInt(6);
}
A votre avis, quelle sera la valeur de id_conjoint ?
En fait, id_conjoint ne vaudra pas null, mais 0.
Vous devez en fait remplacer
Integer id_conjoint = rs.getInt(6);
par
Integer id_conjoint = rs.getInt(6);
if (rs.wasNull()) { id_conjoint = null; }
Ce qui enlève quelque peu l’utilité de l’autoboxing/unboxing.
Imaginer maintenant un seul instant que les concepteurs de l’API JDBC auraient utiliser les classes enveloppes au lieu des primitives. Par exemple, on aurait
Integer getInt(int pos);
et
void setInt(int pos, Integer value);
Et bien, on pourrait alors écrire
st.setInt(6, new Integer(1000));
st.setInt(6, 1000);
set.setInt(6, null);
sans aucun problème.
et on pourrait par exemple écrire
Integer id_conjoint = rs.getInt(6);
int idConjoint = rs.getInt(6) == null ? 0 : rs.getInt(6);
sans aucun problème également.
6 Commentaires + Ajouter un commentaire
Commentaires récents
Archives
- janvier 2012
- novembre 2010
- février 2009
- janvier 2009
- décembre 2008
- septembre 2008
- août 2008
- décembre 2007
- octobre 2007
- septembre 2007
- juillet 2007
- mai 2007
- avril 2007
- mars 2007
- février 2007
- janvier 2007
- décembre 2006
- novembre 2006
- octobre 2006
- septembre 2006
- août 2006
- juillet 2006
- juin 2006
- mai 2006
- avril 2006
- février 2006
- janvier 2006
- décembre 2005
- novembre 2005
- octobre 2005
- septembre 2005
- août 2005
- juillet 2005
- juin 2005
- mai 2005
- avril 2005
Catégories
- Certification
- Défis
- Devoxx
- Devoxx 2008
- Devoxx 2010
- Devoxx France 2012
- Divers
- Événements Java
- Fiches
- Hardware
- In English
- Java
- JavaDay 2006
- JavaFX
- JavaOne 2005
- JavaOne 2006
- JavaOne 2007
- Javapolis 2005
- Javapolis 2006
- Javapolis 2007
- JBoss
- Livres
- Mac
- NetBeans
- OpenJDK
- Pensée
- Performance
- Perles
- Sun Tech Days Paris 2007
- Traduction

Un article de vbrabant
très intéressant.
En lisant tout cela j’ai testé :
Integer a = 5;
int b = 5;
double c =5;
System.out.println(a==b);
System.out.println(b==a);
System.out.println(a==c);
System.out.println(c==a);
pour information cela renvoie vrai a chaque fois, de l’unboxing donc en cas de comparaison entre primitives et objets
merci beaucoup !!!
Très bonne fiche :). Avant de lire cette fiche, je n’y entendais rien en autoboxing. Maintenant c’est beaucoup plus clair. A manipuler avec beaucoup de précautions tout de même. L’exemple du lock est édifiant : l’autoboxing est dangereux si on ne sait pas parfaitement le manipuler.
Je sens que je vais me la relire une dizaine de fois à chaque auto ou unboxing que je ferai dans un programme :). Merci !
Oui je n’avais pas pensé à ce problème… en général j’utilise un simple Object comme lock.
a++
== et equals() fera le sujet d’une autre fiche. Et donc cela ne devrait pas être un problème.
Par contre, pour revenir au fait que cela ne devrait pas être un réel problème, j’aimerais raconter l’histoire suivante:
Des classes qui devaient supporter le multithreading. Et on crée un object lock, sur lequel on fait un synchronize, pour certaines méthodes. Et on crée un autre objet lock sur lequel on fait un synchronize, pour d’autres méthodes.
Les objets de locks étaient définis comme suit:
Byte lock1 = new Byte(0);
Byte lock2 = new Byte(0);
Et furent ensuite transformés, lors du passage vers JDK 5 en
Byte lock1 = 0;
Byte lock2 = 0;
Les deux locks pointaient maintenant vers les mêmes objets. Et donc le synchronize ne se passait plus du tout comme précédemment, et chute des performances, …
Bref, toujours faire attention.
Très intérréssant et complet…
Mais tu aurais du insister sur le fait que l’opérateur == s’effectue sur les références et que généralement on ne compare pas les références mais les valeurs avec .equals()
Donc ce ne devrait pas être un réel problème…
a++