Démarrer l'essai gratuit
Searching...
SoBrief
Français
EnglishEnglish
EspañolSpanish
简体中文Chinese
繁體中文Chinese (Traditional)
FrançaisFrench
DeutschGerman
日本語Japanese
PortuguêsPortuguese
ItalianoItalian
한국어Korean
РусскийRussian
NederlandsDutch
العربيةArabic
PolskiPolish
हिन्दीHindi
Tiếng ViệtVietnamese
SvenskaSwedish
ΕλληνικάGreek
TürkçeTurkish
ไทยThai
ČeštinaCzech
RomânăRomanian
MagyarHungarian
УкраїнськаUkrainian
Bahasa IndonesiaIndonesian
DanskDanish
SuomiFinnish
БългарскиBulgarian
עבריתHebrew
NorskNorwegian
HrvatskiCroatian
CatalàCatalan
SlovenčinaSlovak
LietuviųLithuanian
SlovenščinaSlovenian
СрпскиSerbian
EestiEstonian
LatviešuLatvian
فارسیPersian
മലയാളംMalayalam
தமிழ்Tamil
اردوUrdu
Effective Java
Essayez l'accès complet pendant 3 jours
Débloquez l'écoute et bien plus !
Continuer

Points clés

1. Usages des usines statiques plutôt que des constructeurs : nommage, contrôle et flexibilité

Proposer une méthode d’usine statique au lieu d’un constructeur public présente à la fois des avantages et des inconvénients.

Avantages liés au nommage. Les méthodes d’usine statiques permettent d’utiliser des noms explicites, contrairement aux constructeurs, ce qui améliore la lisibilité et la facilité d’utilisation du code. Cela s’avère particulièrement utile lorsque les paramètres du constructeur ne précisent pas clairement l’objet créé. Par exemple, une méthode nommée BigInteger.probablePrime() est plus parlante qu’un constructeur BigInteger(int, int, Random).

Contrôle des instances. Les usines statiques ne sont pas obligées de créer un nouvel objet à chaque appel, ce qui permet aux classes immuables de mettre en cache des instances et d’éviter des créations inutiles. Cela peut considérablement améliorer les performances, notamment pour des objets fréquemment demandés. La méthode Boolean.valueOf(boolean) illustre bien ce principe, puisqu’elle retourne toujours les mêmes instances Boolean.TRUE ou Boolean.FALSE.

Flexibilité des sous-types. Les usines statiques peuvent retourner des objets de n’importe quel sous-type de leur type de retour, ce qui permet aux API de fournir des objets sans rendre leurs classes publiques. Cela favorise une API compacte et autorise la variation de la classe retournée selon les paramètres d’entrée ou même entre différentes versions, renforçant ainsi la maintenabilité et la flexibilité. C’est le fondement des frameworks de fournisseurs de services comme la Java Cryptography Extension (JCE).

2. Implémentation du singleton : constructeurs privés et accès public

Un singleton est simplement une classe instanciée une seule fois [Gamma98, p. 127].

Garantir l’unicité. Les singletons, représentant des composants uniques du système, sont assurés en rendant le constructeur privé et en fournissant un membre statique public pour y accéder. Cela garantit qu’une seule instance existe. Deux approches courantes existent : utiliser un champ final ou une méthode d’usine statique.

Approche par champ final. Le membre statique public est un champ final initialisé avec l’instance singleton. Cette méthode est simple et explicite quant au fait que la classe est un singleton. Par exemple :

  • public static final Elvis INSTANCE = new Elvis();

Approche par usine statique. Une méthode d’usine statique publique retourne l’instance singleton. Cela offre la flexibilité de modifier l’implémentation sans changer l’API. Par exemple :

  • public static Elvis getInstance() { return INSTANCE; }

Considération liée à la sérialisation. Pour préserver la propriété singleton lors de la sérialisation, il faut fournir une méthode readResolve qui retourne l’instance existante, empêchant ainsi la création de nouvelles instances lors de la désérialisation. Cela garantit que le singleton reste unique même après ces opérations.

3. Classes utilitaires : garantir la non-instanciabilité

Ces classes utilitaires ne sont pas conçues pour être instanciées : une instance serait dénuée de sens.

Rôle des classes utilitaires. Les classes utilitaires regroupent des méthodes et champs statiques, organisant des fonctionnalités liées à des valeurs primitives, des tableaux ou des objets implémentant des interfaces spécifiques. Elles ne sont pas destinées à être instanciées, car une instance serait inutile. On peut citer java.lang.Math ou java.util.Arrays en exemples.

Empêcher l’instanciation. Pour garantir la non-instanciabilité, une pratique simple consiste à inclure un constructeur privé explicite unique. Cela empêche le compilateur de générer un constructeur public sans paramètre par défaut, assurant que la classe ne peut être instanciée de l’extérieur.

Effets secondaires. Cette pratique empêche également la sous-classification, car les sous-classes n’auraient pas de constructeur accessible pour invoquer celui de la superclasse. Il est judicieux d’ajouter un commentaire expliquant la raison de ce constructeur privé, car cela peut sembler contre-intuitif.

4. Réutilisation des objets : efficacité et immutabilité

Il est souvent approprié de réutiliser un objet unique plutôt que de créer à chaque fois un nouvel objet fonctionnellement équivalent.

Avantages de la réutilisation. Réutiliser des objets, en particulier immuables, est plus efficace et élégant que d’en créer de nouveaux à répétition. En effet, la création d’objets et la collecte des déchets peuvent être coûteuses, surtout pour des objets lourds. Par exemple, utiliser String s = "silly"; est préférable à String s = new String("silly");.

Objets immuables. Les objets immuables peuvent toujours être réutilisés en toute sécurité. Par exemple, Boolean.valueOf(String) est préférable à Boolean(String) car la première méthode peut réutiliser des instances existantes.

Objets mutables. Les objets mutables peuvent être réutilisés s’ils ne sont pas modifiés. Par exemple, initialiser statiquement des instances de Calendar et Date une seule fois, plutôt que de les recréer à chaque appel de méthode, peut améliorer significativement les performances.

5. Gestion de la mémoire : éliminer les références obsolètes

Une référence obsolète est simplement une référence qui ne sera plus jamais déréférencée.

Fuites de mémoire. Les fuites de mémoire dans les langages à collecte automatique surviennent lorsque des références à des objets sont conservées involontairement, empêchant leur collecte. Cela peut entraîner une dégradation des performances, une augmentation de l’empreinte mémoire, voire une erreur OutOfMemoryError.

Identifier les fuites. Une source fréquente de fuites est constituée par les classes qui gèrent leur propre mémoire, comme une classe Stack. Lorsqu’un élément est libéré, toutes les références aux objets qu’il contient doivent être mises à null.

Solutions. Pour éviter les fuites, il faut mettre à null les références dès qu’elles deviennent obsolètes. Il faut aussi être vigilant avec les caches, qui peuvent conserver des références longtemps après qu’elles soient devenues inutiles. Utiliser WeakHashMap pour les caches dont les entrées sont pertinentes uniquement tant qu’il existe des références aux clés en dehors du cache.

6. Contrat de la méthode equals : réflexivité, symétrie et transitivité

La méthode equals implémente une relation d’équivalence.

Relation d’équivalence. Lorsqu’on redéfinit la méthode equals, il est crucial de respecter son contrat général, qui définit une relation d’équivalence. Ce contrat inclut la réflexivité (x.equals(x) doit retourner vrai), la symétrie (x.equals(y) doit être vrai si et seulement si y.equals(x) est vrai) et la transitivité (si x.equals(y) et y.equals(z) sont vrais, alors x.equals(z) doit être vrai).

Violation de la symétrie. Ne pas respecter la symétrie peut entraîner des comportements imprévisibles lorsque les objets sont utilisés dans des collections. Par exemple, une classe CaseInsensitiveString qui tente d’interagir avec des chaînes ordinaires peut violer la symétrie.

Violation de la transitivité. La transitivité peut être violée lorsqu’on étend une classe instanciable en ajoutant un aspect affectant les comparaisons equals. Pour éviter cela, il est préférable de privilégier la composition à l’héritage.

Non-nullité. La méthode equals doit retourner faux pour toute référence non nulle x lorsque x.equals(null) est invoqué. L’opérateur instanceof gère cela automatiquement.

7. Redéfinition de hashCode : cohérence avec equals

Il faut redéfinir hashCode dans toute classe qui redéfinit equals.

Importance de hashCode. Redéfinir hashCode est essentiel lorsqu’on redéfinit equals afin de garantir que des objets égaux ont des codes de hachage égaux. Ne pas le faire viole le contrat général de Object.hashCode et empêche la classe de fonctionner correctement dans des collections basées sur le hachage comme HashMap ou HashSet.

Fonction de hachage légale mais médiocre. Une méthode hashCode triviale qui retourne toujours la même valeur est légale mais entraîne de mauvaises performances pour les tables de hachage, car tous les objets sont placés dans le même compartiment.

Recette pour une bonne fonction de hachage. Une bonne fonction de hachage tend à produire des codes différents pour des objets différents. Une recette simple consiste à :

  • Initialiser un entier result à une valeur constante non nulle (par exemple 17).
  • Pour chaque champ significatif f de l’objet, calculer un code de hachage c et l’intégrer dans result par result = 37 * result + c;.
  • Retourner result.

8. Redéfinition de toString : représentation concise et informative

La méthode toString est automatiquement invoquée lorsque votre objet est passé à println, à l’opérateur de concaténation de chaînes (+), ou, depuis la version 1.4, à assert.

Importance de toString. Redéfinir la méthode toString fournit une représentation textuelle concise et informative d’un objet, rendant la classe plus agréable à utiliser. Cela est particulièrement utile pour le débogage et la journalisation.

Contenu de toString. Lorsque c’est pertinent, la méthode toString doit retourner toutes les informations intéressantes contenues dans l’objet. Si l’objet est volumineux ou contient un état peu propice à une représentation textuelle, un résumé doit être fourni.

Spécification du format. Lors de l’implémentation de toString, il faut décider s’il faut spécifier le format de la valeur retournée dans la documentation. Spécifier le format offre une représentation standard et non ambiguë, mais limite la flexibilité pour des modifications futures. Si le format est spécifié, il faut fournir un constructeur ou une usine statique correspondante.

9. Interface Cloneable : mise en œuvre judicieuse

L’interface Cloneable était destinée à être un mixin (Item 16) pour indiquer que les objets autorisent le clonage.

Limites de Cloneable. L’interface Cloneable ne déclare pas de méthode clone, et la méthode clone de Object est protégée. Cela rend difficile l’appel de clone sur un objet simplement parce qu’il implémente Cloneable.

Contrat du clone. Le contrat général de la méthode clone est faible, indiquant qu’elle crée et retourne une copie de l’objet. Cependant, il ne précise pas comment cette copie doit être réalisée ni si les constructeurs doivent être appelés.

Implémentation de Cloneable. Pour bien implémenter Cloneable, une classe doit redéfinir la méthode clone en public, appelant d’abord super.clone, puis corrigeant les champs qui nécessitent une copie. Cela signifie généralement copier les objets mutables constituant la structure interne « profonde » de l’objet.

Alternatives à Cloneable. Une bonne approche pour copier un objet est de fournir un constructeur de copie ou une méthode d’usine statique. Ces méthodes n’utilisent pas un mécanisme de création d’objet externe risqué et ne contredisent pas l’usage approprié des champs finals.

10. Interface Comparable : ordre naturel

En implémentant Comparable, une classe indique que ses instances ont un ordre naturel.

Avantages de Comparable. Implémenter l’interface Comparable permet à une classe d’interagir avec des algorithmes génériques et des collections qui dépendent de l’ordre, comme Arrays.sort ou TreeSet.

Contrat de compareTo. Le contrat général de la méthode compareTo est similaire à celui de equals, exigeant réflexivité, transitivité et symétrie. Il est fortement recommandé que (x.compareTo(y)==0) == (x.equals(y)).

Écriture d’une méthode compareTo. Lors de l’écriture de compareTo, il faut comparer les champs de référence en appelant récursivement leur méthode compareTo. Les champs primitifs sont comparés avec les opérateurs relationnels < et >. Si la classe possède plusieurs champs significatifs, ils doivent être comparés dans l’ordre de leur importance.

11. Minimiser l’accessibilité : cacher l’information

Le facteur le plus important qui distingue un module bien conçu d’un module mal conçu est le degré auquel le module cache ses données internes et autres détails d’implémentation aux autres modules.

Avantages du masquage de l’information. Le masquage de l’information, ou encapsulation, découple les modules, leur permettant d’être développés, testés, optimisés et modifiés indépendamment. Cela accélère le développement, facilite la maintenance, augmente la réutilisation du logiciel et diminue les risques.

Niveaux d’accès. Le langage Java fournit des modificateurs d’accès (private, package-private, protected et public) pour aider au masquage de l’information. La règle générale est de rendre chaque classe ou membre aussi inaccessible que possible.

Champs publics. Les classes publiques devraient rarement, voire jamais, avoir des champs publics (contrairement aux méthodes publiques). L’exception concerne les champs public static final contenant des valeurs primitives ou des références à des objets immuables.

12. Favoriser l’immuabilité : simplicité et sécurité des threads

Une classe immuable est simplement une classe dont les instances ne peuvent pas être modifiées.

Avantages de l’immuabilité. Les classes immuables sont plus faciles à concevoir, implémenter et utiliser que les classes mutables. Elles sont moins sujettes aux erreurs et plus sûres.

Règles pour l’immuabilité. Pour rendre une classe immuable :

  • Ne pas fournir de méthodes modifiant l’objet (mutateurs).
  • S’assurer qu’aucune méthode ne peut être redéfinie (rendre la classe finale ou utiliser des constructeurs privés et des usines statiques).
  • Rendre tous les champs finals.
  • Rendre tous les champs privés.
  • Garantir un accès exclusif à tout composant mutable (faire des copies défensives).

Inconvénients de l’immuabilité. Le seul véritable inconvénient des classes immuables est qu’elles nécessitent un objet distinct pour chaque valeur différente. Pour y remédier, il est conseillé de fournir des constantes publiques static final pour les valeurs fréquemment utilisées et d’envisager une classe compagnon mutable publique.

Dernière mise à jour:

Report Issue

Résumé des avis

4.51 sur 5
Moyenne de 8 000+ évaluations de Goodreads et Amazon.

Effective Java est unanimement reconnu comme une lecture incontournable pour les développeurs Java, salué pour ses explications claires et ses conseils pratiques. Les lecteurs apprécient l’expertise de Bloch ainsi que l’accent mis sur l’écriture d’un code de haute qualité, facile à maintenir. Nombreux sont ceux qui considèrent cet ouvrage comme un passage obligé, tant pour les débutants que pour les programmeurs expérimentés. Le livre aborde de nombreuses fonctionnalités de Java, présente les meilleures pratiques et met en garde contre les erreurs fréquentes. Si certains jugent que certaines parties sont un peu dépassées ou trop techniques, la majorité s’accorde à dire qu’il améliore considérablement les compétences en programmation et la compréhension des subtilités du langage Java.

Your rating:
4.69
388 évaluations
Want to read the full book?

FAQ

What's Effective Java about?

  • Java best practices: Effective Java by Joshua Bloch is a comprehensive guide focused on best practices for Java programming. It aims to help developers write clear, correct, robust, and reusable code.
  • Practical advice: The book is tailored for developers familiar with Java who wish to enhance their coding skills. It covers a wide range of topics, including object creation, methods, classes, and interfaces.
  • Structured format: The content is organized into distinct items, each addressing a specific aspect of Java programming. This structure allows readers to easily navigate and apply the advice.

Why should I read Effective Java?

  • Improve coding skills: Reading Effective Java can significantly enhance your Java programming abilities by providing insights not commonly found in other resources.
  • Expert insights: Joshua Bloch, a key contributor to the Java platform, shares his extensive experience through practical examples and rules of thumb.
  • Code quality focus: The book emphasizes writing code that is not only functional but also maintainable and efficient, leading to fewer bugs and easier code management.

What are the key takeaways of Effective Java?

  • Clarity and simplicity: The book stresses the importance of writing clear and simple code, ensuring understandability and maintainability over time.
  • Composition over inheritance: Bloch advises using composition instead of inheritance to create more flexible and robust code structures, reducing dependencies and potential fragility.
  • Static factory methods: The book recommends using static factory methods for object creation, offering better readability and flexibility.

What are some specific rules from Effective Java?

  • Static Factory Methods: Consider providing static factory methods instead of constructors for better naming and performance.
  • Singleton Property: Enforce the singleton property with a private constructor to ensure a class has only one instance.
  • Override Equals and HashCode: Always override hashCode when you override equals to ensure correct functioning of hash-based collections.

How does Effective Java address object creation?

  • Static Factory Methods: Suggests using static factory methods for object creation instead of constructors for better naming and performance.
  • Avoiding Duplicate Objects: Advises against creating duplicate objects, especially for immutable types, to improve memory management.
  • Enforcing Noninstantiability: Discusses enforcing noninstantiability with a private constructor for utility classes to prevent unnecessary instances.

What are the benefits of immutability discussed in Effective Java?

  • Thread Safety: Immutable objects are inherently thread-safe, eliminating the need for synchronization and simplifying concurrent programming.
  • Simplicity and Clarity: Immutability leads to simpler code, making reasoning about the code easier and reducing the likelihood of bugs.
  • Reuse and Performance: Immutable objects can be shared freely, allowing for efficient memory usage and reduced overhead of object creation.

How does Effective Java suggest handling exceptions?

  • Use Exceptions for Exceptional Conditions: Advises using exceptions only for exceptional conditions, not for regular control flow, to maintain clarity and avoid performance penalties.
  • Document Exceptions: Emphasizes documenting exceptions that a method can throw to improve code readability and help users handle potential errors.
  • Favor Standard Exceptions: Recommends using standard exceptions provided by the Java platform for consistency and familiarity.

What is the significance of the Effective Java item on interfaces?

  • Define Types with Interfaces: Emphasizes using interfaces to define types, not to export constants, keeping the API clean and focused on behavior.
  • Favor Interfaces Over Abstract Classes: Advises using interfaces for flexibility, allowing multiple implementations without single inheritance constraints.
  • Avoid Constant Interfaces: Warns against using constant interfaces, suggesting utility classes instead to group constants.

How does Effective Java recommend designing for inheritance?

  • Design and Document for Inheritance: If a class is designed for inheritance, it must document the effects of overriding methods to ensure subclass understanding.
  • Prohibit Unnecessary Inheritance: Suggests making classes final or using private constructors to prevent unintended inheritance, reducing fragility.
  • Provide Protected Methods: Expose protected methods judiciously to allow subclass extension while avoiding excessive implementation detail exposure.

How does Effective Java address concurrency?

  • Synchronize Access to Shared Data: Emphasizes synchronizing access to shared mutable data to prevent data corruption and ensure thread safety.
  • Avoid Excessive Synchronization: Advises minimizing work within synchronized blocks to enhance performance and avoid deadlocks.
  • Document Thread Safety: Stresses the importance of documenting the thread safety of classes and methods for safe multithreaded use.

What is the double-checked locking idiom, and why is it problematic?

  • Lazy Initialization Purpose: Used to reduce synchronization overhead when lazily initializing a resource by checking if it's initialized before locking.
  • Inconsistent States Risk: Without proper synchronization, threads may see a partially constructed object, leading to inconsistent states and bugs.
  • Avoidance Recommendation: Advises against using double-checked locking due to its complexity and potential pitfalls, suggesting simpler alternatives.

What are the best quotes from Effective Java and what do they mean?

  • "Programs must be written for people to read, and only incidentally for machines to execute." Emphasizes writing code understandable to humans, not just optimized for machines.
  • "The single most important factor that distinguishes a well-designed module from a poorly designed one is the degree to which the module hides its internal data." Highlights the principle of encapsulation for maintainable and flexible code.
  • "Don't create a new object when you should reuse an existing one." Encourages object reuse, especially for immutable objects, to enhance performance and reduce memory usage.

À propos de l'auteur

Joshua Bloch est un informaticien de renom et un auteur spécialisé dans la programmation Java. Il a apporté des contributions majeures au langage Java et à ses bibliothèques, notamment en concevant et en mettant en œuvre le Java Collections Framework. L’expertise de Bloch découle de sa vaste expérience en développement logiciel ainsi que de son rôle dans l’évolution des fonctionnalités modernes de Java. Son style d’écriture est reconnu pour sa clarté, sa précision et son exhaustivité, rendant accessibles des concepts complexes aux lecteurs. Son œuvre, en particulier Effective Java, est devenue une référence incontournable pour les développeurs Java à travers le monde, offrant des éclairages précieux sur les bonnes pratiques et les techniques de programmation efficaces.

Follow
Écouter
Now playing
Effective Java
0:00
-0:00
Now playing
Effective Java
0:00
-0:00
1x
Queue
Home
Swipe
Library
Get App
Try Full Access for 3 Days
Listen, bookmark, and more
Compare Features Free Pro
📖 Read Summaries
Read unlimited summaries. Free users get 3 per month
🎧 Listen to Summaries
Listen to unlimited summaries in 40 languages
❤️ Unlimited Bookmarks
Free users are limited to 4
📜 Unlimited History
Free users are limited to 4
📥 Unlimited Downloads
Free users are limited to 1
Risk-Free Timeline
Aujourd'hui : Accès immédiat
Écoutez les résumés complets de plus de 26 000 livres. Soit plus de 12 000 heures d'audio !
Jour 2 : Rappel d'essai
Nous vous enverrons une notification pour vous informer que votre essai se termine bientôt.
Jour 3 : Votre abonnement commence
Vous serez débité le Jun 11,
annulez à tout moment avant.
Consume 2.8× More Books
2.8× more books Listening Reading
Our users love us
600,000+ readers
Trustpilot Rating
TrustPilot
4.6 Excellent
This site is a total game-changer. I've been flying through book summaries like never before. Highly, highly recommend.
— Dave G
Worth my money and time, and really well made. I've never seen this quality of summaries on other websites. Very helpful!
— Em
Highly recommended!! Fantastic service. Perfect for those that want a little more than a teaser but not all the intricate details of a full audio book.
— Greg M
Save 62%
Yearly
$119.88 $44.99/year/yr
$3.75/mo
Monthly
$9.99/mo
Start a 3-Day Free Trial
3 days free, then $44.99/year. Cancel anytime.
Unlock a world of fiction & nonfiction books
26,000+ books for the price of 2 books
Read any book in 10 minutes
Discover new books like Tinder
Request any book if it's not summarized
Read more books than anyone you know
#1 app for book lovers
Lifelike & immersive summaries
30-day money-back guarantee
Download summaries in EPUBs or PDFs
Cancel anytime in a few clicks
Scanner
Find a barcode to scan

We have a special gift for you
Open
38% OFF
DISCOUNT FOR YOU
$79.99
$49.99/year
only $4.16 per month
Continue
2 taps to start, super easy to cancel
Settings
General
Widget
Loading...
We have a special gift for you
Open
38% OFF
DISCOUNT FOR YOU
$79.99
$49.99/year
only $4.16 per month
Continue
2 taps to start, super easy to cancel