{"id":447091,"date":"2024-02-24T10:17:39","date_gmt":"2024-02-24T09:17:39","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=447091"},"modified":"2025-09-17T11:36:59","modified_gmt":"2025-09-17T10:36:59","slug":"java-best-practices","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/idea\/2024\/02\/java-best-practices\/","title":{"rendered":"Java Best Practices"},"content":{"rendered":"\n<p>Good code follows certain rules, and knowing them increases your chances of success. We\u2019d like to share some Java best practices that will help you on your way. We&#8217;ll cover the must-know tips and tricks, from broad advice on software development to Java- and project-specific know-how. Let&#8217;s get started!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">General<\/h2>\n\n\n\n<p>Let\u2019s keep the following general rules about modern coding in mind.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Be clear, not clever<\/h3>\n\n\n\n<p>The primary purpose of code is to be understood and maintained, not to serve as a showcase of technical skills. Clear code leads to software that&#8217;s easier to debug, maintain, and extend, benefiting everyone involved in the project. Complexity isn&#8217;t a badge of honor \u2013 simplicity and readability are.<\/p>\n\n\n\n<p>Consider the following examples.<\/p>\n\n\n\n<ul>\n<li><strong>Clever:&nbsp;<\/strong><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/3Iunmb-I7GkBx119gey_37G_ik3T2PLeqLREXtgFcLNpgpHB_uyC9BgIN85kqbRYfrHDEJamv0rAVKINP-cgNg1So6TTiPWsIvS5RyAswNvhMkZY2y_Fj0tK0vQeNHhCqXXyDsLlhTdFLYOEr8K_rL0-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>This is an unconventional way to swap the values of variables `a` and `b`. Though it&#8217;s clever, it can be confusing to understand at first glance.<\/p>\n\n\n\n<ul>\n<li><strong>Clear:&nbsp;<\/strong><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/Ir3XdLdpAXqzvWGxEv6-9yZcHy39BvtsIV0YpkBPfKU3kpP9oEBqtZlsaPml3gw4csQILE4GYuKYppYfKptJMzXB-0FJsNLv1tMou-lcsud8o_K9kpb01GjqnZBLXCFLsi4iplTj31N28wHB-EX-bEk-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>This is a more common approach. Even though it requires an additional line of code, its straightforwardness makes it easier to understand for most programmers.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Keep it short<\/h3>\n\n\n\n<p>Make sure your methods and classes aren\u2019t too long. While there&#8217;s no strict rule regarding the exact number of lines or words for a class, it&#8217;s advisable to maintain a focused and cohesive structure. When it comes to methods, it&#8217;s generally suggested to aim for around 10 to 20 lines of code per method. If a method gets longer, it might be better to split it into smaller, more manageable parts.<\/p>\n\n\n\n<p>If you\u2019d like to practice recognizing methods that are too long, here is a <a href=\"https:\/\/www.youtube.com\/watch?v=eqkqDn21OMI\" target=\"_blank\" rel=\"noopener\">great video by technical coach Emily Bache<\/a>.&nbsp;<\/p>\n\n\n\n<p>IntelliJ IDEA can also help you get rid of long methods and classes by providing various refactoring options. For example, it allows you to extract methods to break up a long method into shorter ones.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Naming is hard, so do it with care<\/h3>\n\n\n\n<p>Proper names for methods and variables serve as direct, intuitive guides to understanding the purpose and function of your code, which is essential for effective communication. Here is what you need to know about the most crucial naming conventions.&nbsp;<\/p>\n\n\n\n<p>We advise staying away from single-letter variables, ensuring method names reflect their actions and aligning object and field names with the business domain to enhance clarity and communication. For instance, a method named calculateTotalPrice() instantly conveys its purpose, whereas a vague name like calculate() leaves its functionality ambiguous. Similarly, a variable named customerEmailAddress is clear right away, while an abbreviation like cea could refer to anything, leading to confusion.<\/p>\n\n\n\n<p>As another example, instead of naming a variable timeout, it&#8217;s helpful to specify the unit to which it relates. Use timeoutInMs or timeoutInMilliseconds to avoid confusion about the units.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Test, test, test&nbsp;<\/h3>\n\n\n\n<p>Testing your code is necessary to ensure your app works as expected and will continue to work as it changes. Tests help spot issues early, making fixes cheaper and easier. They also guide you on how the code should work and minimize the possibility of breaking it when updating it later.&nbsp;<\/p>\n\n\n\n<p>Good test names are important as they show what each test does and what it looks for. For example, a test called AlertWhenEmailIsMissing()checks for alerts when an email is missing, so you don&#8217;t need to dig into the details.&nbsp;<\/p>\n\n\n\n<p>You can read this <a href=\"https:\/\/maritvandijk.com\/use-testing-to-develop-better-software-faster\/\" target=\"_blank\" rel=\"noopener\">blog post by Marit van Dijk<\/a> for more information on tests.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Language-specific<\/h2>\n\n\n\n<p>The following tips and tricks will help you elevate your code by avoiding some common mistakes while writing in Java.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Use switch expressions instead of excessive If statements<\/h3>\n\n\n\n<p>Using switch expressions can make your code more readable and organized by consolidating multiple conditions into a single structure. This approach simplifies the code, making it easier to understand and maintain.&nbsp;<\/p>\n\n\n\n<p>Let&#8217;s consider the following example with different types of ice cream and their key ingredients.<\/p>\n\n\n\n<ul>\n<li><strong>Excessive <\/strong><strong>else-if<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In this example, the code uses a chain of else\u2013if statements to match an ice cream flavor with its key ingredient. As the number of flavors grows, the number of if statements can become unmanageable, making the code harder to read.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/O42bfLsz8V-xOKeumhwXKG84Kvy_PJfJNyn_V8g4l3ZN7xAphISTqTpbc23amF4FOHE_ENnu2ogasrPBSWJS_DYgPMLDUQsS0SF4k7hl7VqfArgixZL5DW2Mns_6iHRBKTxkZ_7V4dk87mVF7RwG8gg-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Switch<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In this alternative example, we achieve the same result using a switch expression instead of multiple if-else conditions. The switch expression is more compact, neater, and more easily understood when comparing a single variable against multiple constant values.<\/p>\n\n\n\n<p>IntelliJ IDEA offers a special inspection that can transform your if statements into switch expressions in a matter of seconds.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/mUrqN3V_bwvcaHeZD-Cs3UNLpr9ea9br-OCsRcVE5OSxH00wjEsJotORFeWOKnMJH5yAC7hDFokZKGxDQdXEDX7AyPBTzdAHUyKUJmLeRjh76FuAzZrr7ZBnLrKzH60o0I0Fam3xsBE8VeNGQOmHpg8-2.gif\" alt=\"\"\/><\/figure>\n\n\n\n<p>You can find more amazing examples of switch usage in a <a href=\"https:\/\/blog.jetbrains.com\/idea\/2024\/01\/evolution-of-the-switch-construct-in-java-why-should-you-care\/\">recent blog post<\/a> by Java Developer Advocate Mala Gupta.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Avoid empty catch blocks<\/h3>\n\n\n\n<p>Empty catch blocks in Java are catch clauses that don&#8217;t have any code inside them to handle exceptions. When an exception is caught by such a block, nothing happens and the program continues as if no error occurred. This can make it difficult to notice and debug issues.<\/p>\n\n\n\n<ul>\n<li><strong>Empty <\/strong><strong>Catch<\/strong><strong> Block<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In this scenario, we catch the exception but do nothing about it.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/TYmE_ZGuBswQM8uELHewS3uETGX5X5oKnzmCpXSfaTTcQT6rGSRuEHXMfefmvCOPy-2ztGf-X7UYGgg8T_j6McP4TlbhGODH3YQ-he1vLls07TTCdIPz7CgR-u5o9sAOwxk8v8ANLM9i5-lxA0J8M2g-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>IntelliJ IDEA highlights such cases with an inspection and offers solutions:&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/ytBSpIZYX4TPJdxB0uThGuMdvZ3K8rqCkY1_DRmGLwTvNcnARAdroSvojByJrXA1UhGdgxWCqPiA1kB6kiJ204TJqJ0zktt-HxB-l_Rue_O_RfSJhuEZRLmoVywYFh1skLf-GK_xQvJeoKnpotMjhZw-2.gif\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Logging the exception<\/strong><\/li>\n<\/ul>\n\n\n\n<p>One way of handling the exception is to log it with the help of e.printStackTrace(), which prints the stack trace to the console, helping us identify and debug potential issues.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/myXLeXZGaTNzVrpj4IYDPdJvJ6PsoZIs8QGymwDOafZpp0IPnPS-5QzVKfkEcask9cpihqN2YkW2Zs17h6DB2I4sJzKpdKz7buvG6ANIC9Wi_ph7Br6bfVqnm4zjsLZTg-3rzedEU6o8f9_IPAv5su0-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Logging the exception and rethrowing it<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In an ideal world, the catch block would identify IOException, then print an error message to the console and rethrow the exception to handle it later.&nbsp;<\/p>\n\n\n\n<p>This way, you get the full picture of what went wrong.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/jN6h0J1bfXeaWoAqdNDyVJmFZvXkqbH4PSCD5BefpNZbeVahEkhvjN1UDj1444hvqV8Ly31rsNYpnujkuBIEznnCHBQuqNI3k2M8tsmhXxiaSfMyn1ngbpryfVB7GbYWkQJtuOL-MD8k-Xgw08xZQn8-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Logging the exception and returning an alternate value<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Another way of solving the empty catch block issue is by logging the exception but returning a meaningful value.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/dbAWL1ZOLxfyOV-eQqkILKgvCGKX1P0ocwmLzJg6NBdlYpxmODP-svgsRt15ra__wGigDKoPRekSu4ie3dZr11n9-42C1UE1PYIUhGtysexNTnwelFiXE6afiiiRnppm5V0HcSDUkoXTDRqW7-lzkPE-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Choose collections over arrays for greater flexibility<\/h3>\n\n\n\n<p>While arrays in Java are efficient and easy to use, they are also fixed in size and offer limited operations, making them less adaptable for various data manipulations.&nbsp;<\/p>\n\n\n\n<p>Collections in Java provide far more flexibility and utilities, such as ArrayList or HashSet. For example, ArrayList offers dynamic resizing and many utility methods, and is easier to work with, especially with generics. Let\u2019s take a look at this through some code examples:&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>Arrays<\/strong><\/li>\n<\/ul>\n\n\n\n<p>We\u2019ve created an array of Strings. Since arrays in Java are fixed size, if we wanted to add an eleventh element, we&#8217;d have to create a new array and copy over all of the elements.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/PAeQzfw-tXDRj-Maer1DkTXlfgPe3iBlrlYgCd7yGAKLYgtMDDc4FG1zRea8VHP8RZQyzX2dR1uu04UrIrTfxNKyBUr8S18bd94pA9QI01Wxx5IelfgfDCP8T2Ipr9071TlxjsM8g3_UAzbzVRczI7s-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Collections<\/strong><\/li>\n<\/ul>\n\n\n\n<p>As an alternative to the previous code, we can use a collection class called ArrayList. Collections like ArrayList can grow and shrink at runtime, providing greater flexibility. They also come with powerful methods to manipulate data, such as .add(), .remove(), .contains(), .size(), and more.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/cSPL0AYbF1BkspUa5unzGol2oR0yToIOq74-61dkzXM50lsP0amzlikMRefVmMYv6xYqEKr0nP2lM8I9mdwly2SjBAL2780Yem4FFyZcs9FplHonrxDNAu_K2DFZk_I9AEngA08ZR_73KYt7sJ2-r7w-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Embrace immutability<\/h3>\n\n\n\n<p>Immutable objects are objects whose state cannot be changed after creation. They help to write safer and cleaner code by removing the complexities associated with tracking mutable state changes. This minimizes the risk of bugs and unintended side effects, ensures consistent behavior, and simplifies the process of debugging and maintaining the application. In Java, we achieve immutability using final.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>No <\/strong><strong>final<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In this example, we\u2019ll create a Car class and print its brand and model. After that, we\u2019ll change the car&#8217;s model and print it again. The console output will show that the state of the Car class has been changed, illustrating mutable behavior.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/xYr8bZtYQhJkFhE_G1F_uaJvN2-DJzdw5yari28i4YaMrbut4NbpqU3UwE7tdur2GsUa-5juGyZnaYmy9RgjLNonR81E4Iusfr8TvqwdfFl9MMqYpbnbbbPNjsmA2uitLCdMRQt5V3ZD90veQdi0As-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>With <\/strong><strong>final&nbsp;<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In the improved code below, you can see that we\u2019ve done the same, but we can&#8217;t change the car model or brand because we don&#8217;t have a setter method and the Car class is final. The console output will show that the state of the Car class remains the same, illustrating immutable behavior.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/pckS5OwMP5QiuXq7f3Rn7Di6h2OYuZdYga8-w9zl7B1GdKNP6E8e7bk6y9jpJ1RoXPKGJpLmQ7lSRp3cJtmpcTuG5UT3RK7b-JMkgEO15gjHI_k3Qu3J6PWQVN_uoWoXmgrN3lBx13Es8_vw51hAZcU-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Favor composition over inheritance<\/h3>\n\n\n\n<p>In Java, it&#8217;s usually better to use composition (having a reference or dependency on an object of another class) instead of inheritance (creating a subclass from a superclass). Composition makes the code more flexible and easier to test.<\/p>\n\n\n\n<ul>\n<li><strong>Inheritance<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In our example, GamingComputer inherits from BasicComputer. This can cause problems because if BasicComputer changes, it might break GamingComputer. Also, GamingComputer is locked into being a type of BasicComputer, limiting its flexibility. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1500\" height=\"530\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/02\/image6-2.png\" alt=\"\" class=\"wp-image-448583\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Composition&nbsp;<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In the second example, the Computer class is composed of Memory and Processor which are separate class instances that act as fields. Each of these classes defines its methods and behaviors independently. This approach is more flexible as you can swap different Memory or Processor types or change their behavior at runtime without changing the Computer class. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1500\" height=\"1430\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/02\/image4-1.png\" alt=\"\" class=\"wp-image-448594\"\/><\/figure>\n\n\n\n<p>For more examples, take a look at <a href=\"https:\/\/blog.jetbrains.com\/idea\/2024\/01\/easy-hacks-how-to-create-inheritance-in-java\/\">Easy Hacks: How to Create Inheritance in Java<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Streamline functional interfaces with lambdas<\/h3>\n\n\n\n<p>Functional interfaces in Java are a type of interface that has just one abstract method. Lambdas provide a sleek, expressive way to implement them without the boilerplate code of anonymous classes.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>Without lambdas<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Below we\u2019ll use an anonymous inner class to implement the Comparator interface for sorting. This is bulky and may become unreadable with more complex interfaces.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/t1KRobaEFNj4DeQDGxu3BdYq7A1aCGW-Rhep9fMMhEnwwLTs2FHyya6Q7xu7brzARuMIN0_sEC60tWRAa72KyeJmuxXmJgI0bcR_soCx815RD6Ae34cxm1hrytt3BfuSipKa74k-ZDllr-uV4dX-O4-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>With lambdas<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This code does the same as above, but we are using a lambda function instead of an anonymous class. This makes the code much more compact and intuitive.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/UBzRQ3Ff7P5gSIxxeODOPckuIrHH4sUR2p6yX5z-Ifh8WbOjD4PmfoXUCxMLcSbE4eUmzK9gdoOkqSUbnveMWUkif6Vsb55y1ivlXnuRJkOhDN3NyIQce_C76iJesU2xYaKqZXxGANSv5dsJM4OhmXo-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Use enhanced for loops or streams<\/h3>\n\n\n\n<p>Enhanced for loops (for-each loops) and streams in Java offer more readable and compact ways to iterate over collections or arrays compared to a traditional for loop.<\/p>\n\n\n\n<ul>\n<li><strong>Classic <\/strong><strong>for<\/strong><strong> loop&nbsp;<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In this code, we&#8217;re using a for loop to go over the list. It requires a counter, handling the element index, and defining the stopping condition \u2013 all of which add to the complexity.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/WI-GIKvCK4d-oRi0PzDBY6Qp6jBLQH1N5mXRtyXwFnkbRE8tq216avDEwZpu5SMTX9WoMw3Hwegig5QGMvToF8kKA2iWhmEi6D7maJye8zcyjJL6IVDO7QRP3pcDUsJDL1Uzwh4bz_cMcN5SSe8_4qg-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Enhanced <\/strong><strong>for<\/strong><strong> loop<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This loop (forEach) eliminates the need for counters and directly gives us each item in the list, simplifying code and reducing the potential for errors. You can apply it with the help of an inspection in IntelliJ IDEA.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/sWUaYw6oRg5VMJkWylh1Mxnutj6HY8kGlmtxZbl2n_IH3DWqUvSBOzRoNrmTqO_lQswN36X5GrmRz-TNRvajN0S1DvsEozVYIAFBSa6ZeAqAkrYf-p0jdiqqorvrXAhS3XH5p9hSPCAdoPDlw_8KUwM-2.gif\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Streams<\/strong><\/li>\n<\/ul>\n\n\n\n<p>The usage of streams gives us each item, like the enhanced for loop, but also allows us to do complex operations like filtering and mapping.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/nxMdkTQc2mF7juvmfX8RbOE8ETRYnLHzXYNvnhhLwYa2gTDRUlPrAacHfi4AD60AGREF6zaFsvvaBnOkkBTesnpeiK_T3UNXWcYdDYgCzcOfcubUnTV-LKsSnAe_LT2Bu6VA1zPovSuFO7EV4XcVn5Q-2.gif\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Safeguard resources with try-with-resources statements<\/h3>\n\n\n\n<p>Try-with-resources statements help you ensure that each resource is closed properly after use. Not closing resources in a try block can cause memory issues and application errors, impacting performance and reliability.<\/p>\n\n\n\n<ul>\n<li><strong>Closing resources manually<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In the example below, we handle the system resource FileInputStream manually, which may lead to a resource leak and other problems if an exception is thrown while closing.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/x49U3KI5p86ZQbUPY6JpfZC1jYIjKP4Z3uBP07jV_U4YLmAQtjsrdVWnJPXfKP3OpHRHc87qTvfzjaKl6WEEiFmrmHKzwLweYHNYFfCNWXfWyPEQbaUlF5KWlkhGkA-KR4ZFOVgQV4Lky_CQIsKzEUw-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Using <\/strong>try<strong>-with-resources statements<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In the improved version, declaring FileInputStream inside the try block means Java will automatically close it, regardless of whether we leave the try block normally or with an exception.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/HbGUZq71hznydgsQuT2yatcXPy0OtMnYY5-cY5Ca4Kf1qU8223aAEgWMI27nZtEGR-OyOhYSedugGDZnKXFojGsdhDDVFGxaQGxEZeOVNVGxXVoQD_qUjO75wE_bNW82mUoF6v0bNPvDhaklx7NEFe0-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Untangle deeply nested code<\/h3>\n\n\n\n<p>Deeply nested code highlights logical issues that can be difficult to notice initially. This often comes from using lots of conditionals, which are the coding essentials, so we can&#8217;t just get rid of them. However, we do need to find ways to simplify the code.<\/p>\n\n\n\n<ul>\n<li><strong>Numerous conditionals<\/strong><\/li>\n<\/ul>\n\n\n\n<p>You can see how strange abundant nested conditionals look.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/iaeo30p4MAEfEjJ0h6rgNuINiqQ3JqxuSciRhPXOCePdyzBBjHm0OI1l6fFBFGKEL6M_rTvhQMfI_BJyxeuylemzgFNL0byHe1OAYIBDcvaP2THPEyTTenpuMjMTwNYKE197mQA7qKA6iuZGIpxXAIg-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li><strong>Refactored code<\/strong><\/li>\n<\/ul>\n\n\n\n<p>We&#8217;ve used a \u201cguard clauses\u201d technique to eliminate nested conditionals. By quickly exiting the function when certain conditions are met, we preserve the same logic with cleaner-looking code.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/E2o0prXGO0Fn1eqD8iXlAY6OZ2F5dcACV9mBESHTZ3AViQe7rVCGXPYsfV9wVNYKN8uOEcDgJ7MkpQ1Nx-eeVVhPirARWfK1K1gIkm88EtcXQviXTTYsezLYodgGGd8vHFlIbu7R5dBuI0x55Yw_C_0-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Project-specific&nbsp;<\/h2>\n\n\n\n<p>We also have some helpful dos and don\u2019ts for working on projects that contain multiple dependencies.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Keep dependencies up to date&nbsp;<\/h3>\n\n\n\n<p>Remember to keep your project&#8217;s dependencies updated to enhance security, introduce new features, and fix bugs. Regular updates ensure your project runs smoothly and remains compatible with other tools.&nbsp;<\/p>\n\n\n\n<p>IntelliJ IDEA can help you keep your dependencies up to date. First, install the Package Search plugin from JetBrains Marketplace via <em>Preferences\/Settings | Plugins<\/em>. Then navigate to the <em>Dependencies<\/em> tool window to see all of the existing dependencies in your project and click the <em>Upgrade<\/em> link next to them.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/v7a_sygKJBUH46YdX72jda6_U82VCtfZ_kAV9_dVvAX96OypLlreOEV72rxX-rcqaItPN_ym94q9zL_XGTc5xGkLpLIhfXE6FQPqlln-Sii76FdyF9kgtFDY9UYnYfNUKgi94hI9TEI5fccmCMhf1VU-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Check for vulnerable dependencies and APIs<\/h3>\n\n\n\n<p>Regularly scanning your project for weak spots in dependencies and APIs helps you minimize security risks, stick to predefined rules, and keep things running smoothly. Addressing these vulnerabilities quickly helps protect your project and its users from potential threats.<\/p>\n\n\n\n<p>To find vulnerable dependencies in IntelliJ IDEA, navigate to <em>Code | Analyze Code<\/em> and select <em>Show Vulnerable Dependencies<\/em>. The findings will appear in the <em>Vulnerable Dependencies<\/em> tab of the <em>Problems<\/em> tool window.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/c629wfGRdXWE_RNuEzc3UpRmalBuLps21aQ80EXyztqzCY-Heu96WM7GUHjKoi4MclMul7V1AP2WlWAMcx5kkHpaFrxMlB_-mGhaXTtouAK7_BrAK3J4AJH89mWADU-ZJiUCm3kv_PInMnfYVj9B_ZE-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>You can also right-click a folder or file, like pom.xml or<em> <\/em>build.gradle, in the <em>Project<\/em> tool window and choose <em>Analyze Code | Show Vulnerable Dependencies<\/em> from the context menu.&nbsp;<\/p>\n\n\n\n<p>Even without explicitly checking for vulnerabilities, IntelliJ IDEA will highlight vulnerabilities in pom.xml or<em> <\/em>build.gradle.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/3gRj9n587wvDfr_pf1q0rB66cNqndiEZtxsmVdEnuCo0qUhhSA5NsvuXCgwAkePqOSW9_dgOUxIEIp2A4n4yKD8a79kuixHfYK1UMshpHPhav5XI0j5OfLHtDkYAivyIbMtzeBUzZfWz2sTjikEN0-s-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Avoid circular dependencies&nbsp;<\/h3>\n\n\n\n<p>Circular dependencies happen when parts of your project rely on each other in a loop. For example, part A needs something from part B, but part B also needs something from part A. This can make your project messy and hard to work on because it&#8217;s tough to figure out where one part starts and another ends. It&#8217;s best to avoid these loops to keep things clear and easy to manage.<\/p>\n\n\n\n<p>To avoid circular dependencies, you can <a href=\"https:\/\/www.jetbrains.com\/guide\/java\/tutorials\/dependency-matrix\/\" target=\"_blank\" rel=\"noopener\">use the Dependency Matrix<\/a>. It helps you visualize dependencies between components in your projects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion&nbsp;<\/h2>\n\n\n\n<p>We hope that our advice simplifies your daily tasks and encourages you to write simple, clear, and professional code, inspiring you to become a more efficient developer.&nbsp;<\/p>\n\n\n\n<p>IntelliJ IDEA will help you find many of the items discussed in this blog post and provide automatic fixes. Give it a try and let us know what you think!<\/p>\n","protected":false},"author":1138,"featured_media":447116,"comment_status":"closed","ping_status":"closed","template":"","categories":[4759,5088,601],"tags":[227,40,155,743,357],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/447091"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/users\/1138"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/comments?post=447091"}],"version-history":[{"count":9,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/447091\/revisions"}],"predecessor-version":[{"id":620120,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/447091\/revisions\/620120"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media\/447116"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media?parent=447091"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/categories?post=447091"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/tags?post=447091"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/cross-post-tag?post=447091"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}