├── .editorconfig ├── .gitignore ├── LICENSE.txt ├── README.md ├── README.pdf ├── live.js └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Custom files 2 | *.yaml 3 | *.html 4 | .npmrc 5 | ## -------------------- 6 | 7 | # Created by https://www.gitignore.io/api/java,gradle,windows,intellij+all,visualstudiocode 8 | # Edit at https://www.gitignore.io/?templates=java,gradle,windows,intellij+all,visualstudiocode 9 | 10 | ### Intellij+all ### 11 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 12 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 13 | 14 | # User-specific stuff 15 | .idea/**/workspace.xml 16 | .idea/**/tasks.xml 17 | .idea/**/usage.statistics.xml 18 | .idea/**/dictionaries 19 | .idea/**/shelf 20 | 21 | # Generated files 22 | .idea/**/contentModel.xml 23 | 24 | # Sensitive or high-churn files 25 | .idea/**/dataSources/ 26 | .idea/**/dataSources.ids 27 | .idea/**/dataSources.local.xml 28 | .idea/**/sqlDataSources.xml 29 | .idea/**/dynamic.xml 30 | .idea/**/uiDesigner.xml 31 | .idea/**/dbnavigator.xml 32 | 33 | # Gradle 34 | .idea/**/gradle.xml 35 | .idea/**/libraries 36 | 37 | # Gradle and Maven with auto-import 38 | # When using Gradle or Maven with auto-import, you should exclude module files, 39 | # since they will be recreated, and may cause churn. Uncomment if using 40 | # auto-import. 41 | # .idea/modules.xml 42 | # .idea/*.iml 43 | # .idea/modules 44 | # *.iml 45 | # *.ipr 46 | 47 | # CMake 48 | cmake-build-*/ 49 | 50 | # Mongo Explorer plugin 51 | .idea/**/mongoSettings.xml 52 | 53 | # File-based project format 54 | *.iws 55 | 56 | # IntelliJ 57 | out/ 58 | 59 | # mpeltonen/sbt-idea plugin 60 | .idea_modules/ 61 | 62 | # JIRA plugin 63 | atlassian-ide-plugin.xml 64 | 65 | # Cursive Clojure plugin 66 | .idea/replstate.xml 67 | 68 | # Crashlytics plugin (for Android Studio and IntelliJ) 69 | com_crashlytics_export_strings.xml 70 | crashlytics.properties 71 | crashlytics-build.properties 72 | fabric.properties 73 | 74 | # Editor-based Rest Client 75 | .idea/httpRequests 76 | 77 | # Android studio 3.1+ serialized cache file 78 | .idea/caches/build_file_checksums.ser 79 | 80 | ### Intellij+all Patch ### 81 | # Ignores the whole .idea folder and all .iml files 82 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 83 | 84 | .idea/ 85 | 86 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 87 | 88 | *.iml 89 | modules.xml 90 | .idea/misc.xml 91 | *.ipr 92 | 93 | # Sonarlint plugin 94 | .idea/sonarlint 95 | 96 | ### Java ### 97 | # Compiled class file 98 | *.class 99 | 100 | # Log file 101 | *.log 102 | 103 | # BlueJ files 104 | *.ctxt 105 | 106 | # Mobile Tools for Java (J2ME) 107 | .mtj.tmp/ 108 | 109 | # Package Files # 110 | *.jar 111 | *.war 112 | *.nar 113 | *.ear 114 | *.zip 115 | *.tar.gz 116 | *.rar 117 | 118 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 119 | hs_err_pid* 120 | 121 | ### VisualStudioCode ### 122 | .vscode/* 123 | !.vscode/settings.json 124 | !.vscode/tasks.json 125 | !.vscode/launch.json 126 | !.vscode/extensions.json 127 | 128 | ### VisualStudioCode Patch ### 129 | # Ignore all local history of files 130 | .history 131 | 132 | ### Windows ### 133 | # Windows thumbnail cache files 134 | Thumbs.db 135 | Thumbs.db:encryptable 136 | ehthumbs.db 137 | ehthumbs_vista.db 138 | 139 | # Dump file 140 | *.stackdump 141 | 142 | # Folder config file 143 | [Dd]esktop.ini 144 | 145 | # Recycle Bin used on file shares 146 | $RECYCLE.BIN/ 147 | 148 | # Windows Installer files 149 | *.cab 150 | *.msi 151 | *.msix 152 | *.msm 153 | *.msp 154 | 155 | # Windows shortcuts 156 | *.lnk 157 | 158 | ### Gradle ### 159 | .gradle 160 | build/ 161 | 162 | # Ignore Gradle GUI config 163 | gradle-app.setting 164 | 165 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 166 | !gradle-wrapper.jar 167 | 168 | # Cache of project 169 | .gradletasknamecache 170 | 171 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 172 | # gradle/wrapper/gradle-wrapper.properties 173 | 174 | ### Gradle Patch ### 175 | **/build/ 176 | 177 | # End of https://www.gitignore.io/api/java,gradle,windows,intellij+all,visualstudiocode 178 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Attribution-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-ShareAlike 4.0 International Public 58 | License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-ShareAlike 4.0 International Public License ("Public 63 | License"). To the extent this Public License may be interpreted as a 64 | contract, You are granted the Licensed Rights in consideration of Your 65 | acceptance of these terms and conditions, and the Licensor grants You 66 | such rights in consideration of benefits the Licensor receives from 67 | making the Licensed Material available under these terms and 68 | conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. Share means to provide material to the public by any means or 126 | process that requires permission under the Licensed Rights, such 127 | as reproduction, public display, public performance, distribution, 128 | dissemination, communication, or importation, and to make material 129 | available to the public including in ways that members of the 130 | public may access the material from a place and at a time 131 | individually chosen by them. 132 | 133 | l. Sui Generis Database Rights means rights other than copyright 134 | resulting from Directive 96/9/EC of the European Parliament and of 135 | the Council of 11 March 1996 on the legal protection of databases, 136 | as amended and/or succeeded, as well as other essentially 137 | equivalent rights anywhere in the world. 138 | 139 | m. You means the individual or entity exercising the Licensed Rights 140 | under this Public License. Your has a corresponding meaning. 141 | 142 | 143 | Section 2 -- Scope. 144 | 145 | a. License grant. 146 | 147 | 1. Subject to the terms and conditions of this Public License, 148 | the Licensor hereby grants You a worldwide, royalty-free, 149 | non-sublicensable, non-exclusive, irrevocable license to 150 | exercise the Licensed Rights in the Licensed Material to: 151 | 152 | a. reproduce and Share the Licensed Material, in whole or 153 | in part; and 154 | 155 | b. produce, reproduce, and Share Adapted Material. 156 | 157 | 2. Exceptions and Limitations. For the avoidance of doubt, where 158 | Exceptions and Limitations apply to Your use, this Public 159 | License does not apply, and You do not need to comply with 160 | its terms and conditions. 161 | 162 | 3. Term. The term of this Public License is specified in Section 163 | 6(a). 164 | 165 | 4. Media and formats; technical modifications allowed. The 166 | Licensor authorizes You to exercise the Licensed Rights in 167 | all media and formats whether now known or hereafter created, 168 | and to make technical modifications necessary to do so. The 169 | Licensor waives and/or agrees not to assert any right or 170 | authority to forbid You from making technical modifications 171 | necessary to exercise the Licensed Rights, including 172 | technical modifications necessary to circumvent Effective 173 | Technological Measures. For purposes of this Public License, 174 | simply making modifications authorized by this Section 2(a) 175 | (4) never produces Adapted Material. 176 | 177 | 5. Downstream recipients. 178 | 179 | a. Offer from the Licensor -- Licensed Material. Every 180 | recipient of the Licensed Material automatically 181 | receives an offer from the Licensor to exercise the 182 | Licensed Rights under the terms and conditions of this 183 | Public License. 184 | 185 | b. Additional offer from the Licensor -- Adapted Material. 186 | Every recipient of Adapted Material from You 187 | automatically receives an offer from the Licensor to 188 | exercise the Licensed Rights in the Adapted Material 189 | under the conditions of the Adapter's License You apply. 190 | 191 | c. No downstream restrictions. You may not offer or impose 192 | any additional or different terms or conditions on, or 193 | apply any Effective Technological Measures to, the 194 | Licensed Material if doing so restricts exercise of the 195 | Licensed Rights by any recipient of the Licensed 196 | Material. 197 | 198 | 6. No endorsement. Nothing in this Public License constitutes or 199 | may be construed as permission to assert or imply that You 200 | are, or that Your use of the Licensed Material is, connected 201 | with, or sponsored, endorsed, or granted official status by, 202 | the Licensor or others designated to receive attribution as 203 | provided in Section 3(a)(1)(A)(i). 204 | 205 | b. Other rights. 206 | 207 | 1. Moral rights, such as the right of integrity, are not 208 | licensed under this Public License, nor are publicity, 209 | privacy, and/or other similar personality rights; however, to 210 | the extent possible, the Licensor waives and/or agrees not to 211 | assert any such rights held by the Licensor to the limited 212 | extent necessary to allow You to exercise the Licensed 213 | Rights, but not otherwise. 214 | 215 | 2. Patent and trademark rights are not licensed under this 216 | Public License. 217 | 218 | 3. To the extent possible, the Licensor waives any right to 219 | collect royalties from You for the exercise of the Licensed 220 | Rights, whether directly or through a collecting society 221 | under any voluntary or waivable statutory or compulsory 222 | licensing scheme. In all other cases the Licensor expressly 223 | reserves any right to collect such royalties. 224 | 225 | 226 | Section 3 -- License Conditions. 227 | 228 | Your exercise of the Licensed Rights is expressly made subject to the 229 | following conditions. 230 | 231 | a. Attribution. 232 | 233 | 1. If You Share the Licensed Material (including in modified 234 | form), You must: 235 | 236 | a. retain the following if it is supplied by the Licensor 237 | with the Licensed Material: 238 | 239 | i. identification of the creator(s) of the Licensed 240 | Material and any others designated to receive 241 | attribution, in any reasonable manner requested by 242 | the Licensor (including by pseudonym if 243 | designated); 244 | 245 | ii. a copyright notice; 246 | 247 | iii. a notice that refers to this Public License; 248 | 249 | iv. a notice that refers to the disclaimer of 250 | warranties; 251 | 252 | v. a URI or hyperlink to the Licensed Material to the 253 | extent reasonably practicable; 254 | 255 | b. indicate if You modified the Licensed Material and 256 | retain an indication of any previous modifications; and 257 | 258 | c. indicate the Licensed Material is licensed under this 259 | Public License, and include the text of, or the URI or 260 | hyperlink to, this Public License. 261 | 262 | 2. You may satisfy the conditions in Section 3(a)(1) in any 263 | reasonable manner based on the medium, means, and context in 264 | which You Share the Licensed Material. For example, it may be 265 | reasonable to satisfy the conditions by providing a URI or 266 | hyperlink to a resource that includes the required 267 | information. 268 | 269 | 3. If requested by the Licensor, You must remove any of the 270 | information required by Section 3(a)(1)(A) to the extent 271 | reasonably practicable. 272 | 273 | b. ShareAlike. 274 | 275 | In addition to the conditions in Section 3(a), if You Share 276 | Adapted Material You produce, the following conditions also apply. 277 | 278 | 1. The Adapter's License You apply must be a Creative Commons 279 | license with the same License Elements, this version or 280 | later, or a BY-SA Compatible License. 281 | 282 | 2. You must include the text of, or the URI or hyperlink to, the 283 | Adapter's License You apply. You may satisfy this condition 284 | in any reasonable manner based on the medium, means, and 285 | context in which You Share Adapted Material. 286 | 287 | 3. You may not offer or impose any additional or different terms 288 | or conditions on, or apply any Effective Technological 289 | Measures to, Adapted Material that restrict exercise of the 290 | rights granted under the Adapter's License You apply. 291 | 292 | 293 | Section 4 -- Sui Generis Database Rights. 294 | 295 | Where the Licensed Rights include Sui Generis Database Rights that 296 | apply to Your use of the Licensed Material: 297 | 298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 299 | to extract, reuse, reproduce, and Share all or a substantial 300 | portion of the contents of the database; 301 | 302 | b. if You include all or a substantial portion of the database 303 | contents in a database in which You have Sui Generis Database 304 | Rights, then the database in which You have Sui Generis Database 305 | Rights (but not its individual contents) is Adapted Material, 306 | 307 | including for purposes of Section 3(b); and 308 | c. You must comply with the conditions in Section 3(a) if You Share 309 | all or a substantial portion of the contents of the database. 310 | 311 | For the avoidance of doubt, this Section 4 supplements and does not 312 | replace Your obligations under this Public License where the Licensed 313 | Rights include other Copyright and Similar Rights. 314 | 315 | 316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 317 | 318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 328 | 329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 338 | 339 | c. The disclaimer of warranties and limitation of liability provided 340 | above shall be interpreted in a manner that, to the extent 341 | possible, most closely approximates an absolute disclaimer and 342 | waiver of all liability. 343 | 344 | 345 | Section 6 -- Term and Termination. 346 | 347 | a. This Public License applies for the term of the Copyright and 348 | Similar Rights licensed here. However, if You fail to comply with 349 | this Public License, then Your rights under this Public License 350 | terminate automatically. 351 | 352 | b. Where Your right to use the Licensed Material has terminated under 353 | Section 6(a), it reinstates: 354 | 355 | 1. automatically as of the date the violation is cured, provided 356 | it is cured within 30 days of Your discovery of the 357 | violation; or 358 | 359 | 2. upon express reinstatement by the Licensor. 360 | 361 | For the avoidance of doubt, this Section 6(b) does not affect any 362 | right the Licensor may have to seek remedies for Your violations 363 | of this Public License. 364 | 365 | c. For the avoidance of doubt, the Licensor may also offer the 366 | Licensed Material under separate terms or conditions or stop 367 | distributing the Licensed Material at any time; however, doing so 368 | will not terminate this Public License. 369 | 370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 371 | License. 372 | 373 | 374 | Section 7 -- Other Terms and Conditions. 375 | 376 | a. The Licensor shall not be bound by any additional or different 377 | terms or conditions communicated by You unless expressly agreed. 378 | 379 | b. Any arrangements, understandings, or agreements regarding the 380 | Licensed Material not stated herein are separate from and 381 | independent of the terms and conditions of this Public License. 382 | 383 | 384 | Section 8 -- Interpretation. 385 | 386 | a. For the avoidance of doubt, this Public License does not, and 387 | shall not be interpreted to, reduce, limit, restrict, or impose 388 | conditions on any use of the Licensed Material that could lawfully 389 | be made without permission under this Public License. 390 | 391 | b. To the extent possible, if any provision of this Public License is 392 | deemed unenforceable, it shall be automatically reformed to the 393 | minimum extent necessary to make it enforceable. If the provision 394 | cannot be reformed, it shall be severed from this Public License 395 | without affecting the enforceability of the remaining terms and 396 | conditions. 397 | 398 | c. No term or condition of this Public License will be waived and no 399 | failure to comply consented to unless expressly agreed to by the 400 | Licensor. 401 | 402 | d. Nothing in this Public License constitutes or may be interpreted 403 | as a limitation upon, or waiver of, any privileges and immunities 404 | that apply to the Licensor or You, including from the legal 405 | processes of any jurisdiction or authority. 406 | 407 | 408 | ======================================================================= 409 | 410 | Creative Commons is not a party to its public licenses. 411 | Notwithstanding, Creative Commons may elect to apply one of its public 412 | licenses to material it publishes and in those instances will be 413 | considered the “Licensor.” The text of the Creative Commons public 414 | licenses is dedicated to the public domain under the CC0 Public Domain 415 | Dedication. Except for the limited purpose of indicating that material 416 | is shared under a Creative Commons public license or as otherwise 417 | permitted by the Creative Commons policies published at 418 | creativecommons.org/policies, Creative Commons does not authorize the 419 | use of the trademark "Creative Commons" or any other trademark or logo 420 | of Creative Commons without its prior written consent including, 421 | without limitation, in connection with any unauthorized modifications 422 | to any of its public licenses or any other arrangements, 423 | understandings, or agreements concerning use of licensed material. For 424 | the avoidance of doubt, this paragraph does not form part of the public 425 | licenses. 426 | 427 | Creative Commons may be contacted at creativecommons.org. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java 2 | 3 | ## Introducción 4 | 5 | Java es un **lenguaje orientado a objetos**. En la década de los 60 nació la programación estructurada impulsada por lenguajes como Pascal o C. Con el aumento de la complejidad de los programas se adoptó un nuevo enfoque como es la programación orientada a objetos o POO. 6 | 7 | Java fue desarrollado por James Gosling, Patrick Naughton, Chris Warth, Ed Frank y Mike Sheridan en Sun Microsystems en 1991. Inicialmente, el lenguaje se denominó _Oak_ aunque se rebautizó como **Java** en 1995. La concepción de Java se basa en C y C++. 8 | 9 | Su objetivo inicial era crear un lenguaje independiente y portátil capaz de ser ejecutado en diferentes plataformas y con diferentes CPUs. La clave está en que el resultado de la compilación de código Java no es código ejecutable, sino código de bytes o _bytecode_. Es un conjunto optimizado de instrucciones diseñadas para ejecutarse sobre la JVM o _Java Virtual Machine_. Esta máquina virtual es la que interpreta el _bytecode_. De esta forma sólo es necesario implementar la JVM para cada plataforma. 10 | 11 | Desde un punto de vista general, un programa se puede organizar de dos formas: sobre su código (lo que sucede) y sobre sus datos (lo que se ve afectado). En la programación estructurada se organiza sobre el código pero en la programación orientada a objetos el programa se estructura alrededor de los datos, definiendo estos datos y las rutinas que permiten actuar sobre los mismos. 12 | 13 | Para complementar los principios de la programación orientada a objetos, se aplican los conceptos de **encapsulación, herencia y polimorfismo**. 14 | 15 | - La **encapsulación** es un mecanismo que combina el código con los datos que manipula, al tiempo que los protege de interferencias externas. La unidad básica de encapsulación es la **clase**. La clase define la forma de un objeto y especifica los datos y el código que actúa sobre ellos. Los objetos son instancias de una clase. 16 | 17 | - El **polimorfismo** es la propiedad que permite a una interfaz acceder a una clase general de acciones. Este concepto suele expresarse como "una interfaz, múltiples métodos". El compilador en tiempo de ejecución será el encargado de seleccionar el método correcto a invocar. 18 | 19 | - La **herencia** es el proceso mediante el cual un objeto puede adquirir las propiedades de otro. Gracias a la herencia un objeto solo tiene que definir los atributos que lo hacen único dentro de la clase y heredar los atributos generales. 20 | 21 | ## Comandos de Java 22 | 23 | ```sh 24 | # Compilar código Java en bytecode 25 | $ javac filename.java 26 | 27 | # Ejecutar aplicación Java 28 | $ java filename 29 | 30 | # Generar páginas HTML de documentación de la API 31 | $ javadoc 32 | 33 | # Inicia el intérprete de comandos 34 | $ jshell 35 | 36 | # Iniciar una consola gráfica para monitorear y gestionar aplicaciones Java 37 | $ jconsole 38 | ``` 39 | 40 | - [Java® Development Kit Version 22 Tool Specifications](https://docs.oracle.com/en/java/javase/22/docs/specs/man/index.html) 41 | 42 | ## Sintaxis básica 43 | 44 | ### Comentarios 45 | 46 | ```java 47 | // Comentarios de una sóla línea 48 | 49 | /* 50 | Comentarios multilínea 51 | */ 52 | 53 | /** 54 | * Los comentarios JavaDoc suelen describir la clase, 55 | * y información sobre el autor, fecha de creación, ... 56 | */ 57 | public class Sample { 58 | // ... 59 | } 60 | ``` 61 | 62 | ### Identificadores 63 | 64 | En Java, un **identificador** es un nombre asignado a un método, variable u otro elemento definido por el usuario. Pueden tener uno o varios caracteres de longitud. 65 | 66 | Los nombres de variable deben cumplir ciertas restricciones: 67 | 68 | - Pueden empezar por **cualquier letra, guión bajo(`_`) o el símbolo `$`**. 69 | 70 | - El siguiente carácter puede ser **cualquier letra, dígito, guión bajo(`_`) o el símbolo `$`**. 71 | 72 | - Por lo tanto no pueden empezar con un dígito. 73 | 74 | - Tampoco se pueden utilizar [palabras clave de Java](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html). 75 | 76 | - No pueden incluir espacios ni caracteres especiales distintos de `_` y `$`. 77 | 78 | > **No es recomendable usar el símbolo `$` en nombres de variables comunes**, ya que generalmente está reservado para usos internos o generados automáticamente por el compilador. 79 | 80 | Java es **_"case sensitive"_** lo que significa que Java distingue entre mayúsculas y minúsculas. 81 | 82 | En Java, las convenciones de nombres más comunes incluyen: 83 | 84 | - **camelCase**: se utiliza para nombres de variables y métodos, como `edadDelCapitan`, `nombreUsuario`, `calcularTotal()`. 85 | 86 | - **PascalCase**: similar a la anterior, pero la primera letra también es mayúscula. Se usa para nombres de clases y interfaces, como `Persona`, `CuentaBancaria`. 87 | 88 | - **UPPER_SNAKE_CASE**: se utiliza para las constantes, es decir, variables que son `static final`. En esta convención todas las letras son mayúsculas y se separan con guiones bajos, como `MAX_VALUE`, `PI` o `DAYS_OF_WEEK`. 89 | 90 | ### Variables y tipos 91 | 92 | Los tipos de datos son especialmente importantes en Java por tratarse de un lenguaje de **tipado fuerte**. Es decir, el compilador comprueba la compatibilidad de los tipos en todas las operaciones. Para realizar la comprobación de tipos, todas las variables, expresiones y valores tienen un tipo. 93 | 94 | Al determinar el tipo para una variable, estamos indicando cuál es la información que vamos a poder almacenar en esta variable y las operaciones que podremos efectuar con ella. 95 | 96 | En Java se declara una variable usando ` `. Es necesario declarar la variable antes de poder hacer referencia a ella. Una vez se ha declarado ya se puede utilizar, nunca antes. 97 | 98 | ```java 99 | int contador; 100 | double precio; 101 | String nombre; 102 | ``` 103 | 104 | Por lo general, debe asignar un valor a una variable antes de poder usarla aunque en determinados casos Java puede inicializar el valor de las variables, como por ejemplo en **variables de instancia**. 105 | 106 | - **Variables locales**: se declaran dentro de un método, constructor o bloque, y solo están accesibles dentro de ese contexto. No tienen un valor por defecto, por lo que deben ser inicializadas antes de usarse. 107 | 108 | - **Variables de instancia**: se declaran dentro de una clase pero fuera de cualquier método, constructor o bloque. Cada objeto de la clase tiene su propia copia de estas variables. Si no se inicializan explícitamente, las variables de instancia reciben un [valor por defecto](#valores-por-defecto) basado en su tipo. 109 | 110 | - **Variables de clase (o estáticas)**: se declaran con la palabra clave `static`. Solo hay una copia de estas variables que es compartida por todas las instancias de la clase. Se almacenan en memoria cuando la clase es cargada por el `ClassLoader`. 111 | 112 | Existe una **notación abreviada** para declarar (e inicializar) múltiples variables del mismo tipo, aunque no se aconseja su uso por motivos de legibilidad: 113 | 114 | ```java 115 | // Declarar las tres variables del mismo tipo 116 | int x, y, z; 117 | 118 | // Declarar e inicializar las variables 119 | int i1 = 1, i2 = 2; 120 | 121 | // El símbolo '=' retorna el valor de su derecha 122 | int a = b = c = 100; 123 | ``` 124 | 125 | #### Valores por defecto 126 | 127 | En el caso de las **variables de instancia**, si no se inicializan de forma explícita, el compilador establecerá un valor basado en su tipo: 128 | 129 | - Tipos primitivos: 130 | 131 | - `int`, `short`, `byte`, `long`: 0 132 | 133 | - `float`: 0.0f 134 | 135 | - `double`: 0.0d 136 | 137 | - `char`: `'\u0000'` (carácter nulo) 138 | 139 | - `boolean`: false 140 | 141 | - Objetos y referencias (como `String` o cualquier objeto): `null` 142 | 143 | > Sin embargo, confiar en estos valores predeterminados generalmente se considera una **práctica poco recomendable**. Aunque estos valores por defecto evitan errores de compilación, la inicialización explícita mejora la legibilidad y evita posibles errores sobre el estado inicial de una variable. 144 | 145 | ### Tipos primitivos 146 | 147 | Los tipos primitivos en Java tienen **rangos definidos**, y al intentar asignar directamente un valor fuera del rango, el compilador **generará un error**. Sin embargo, para los tipos primitivos numéricos, si una operación aritmética excede el rango permitido, se producirá un **desbordamiento**, resultando en un valor inesperado, pero sin generar un error de compilación. 148 | 149 | > El desbordamiento ocurre en **tiempo de ejecución** y puede llevar a resultados incorrectos sin advertencias del compilador. 150 | 151 | Java no tiene tipos sin signo (excepto `int` y `long` con métodos específicos introducidos en Java SE 8), por lo que todos los tipos numéricos tienen signo. 152 | 153 | - ["Primitive Data Types - The Java Tutorials"](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html) 154 | 155 | #### byte 156 | 157 | El tipo primitivo `byte` es un entero de complemento de dos con signo de 8 bits. Es una opción eficiente para ahorrar memoria en grandes colecciones de datos numéricos pequeños. También se utiliza frecuentemente en la manipulación de datos binarios y en aplicaciones que requieren optimización de memoria. 158 | 159 | ```java 160 | // (-128 <= byte <= 127) 161 | byte foo = 100; 162 | ``` 163 | 164 | > El rango de valores permitidos para `byte` es de **-128** a **127** (ambos inclusive). Si se intenta asignar un valor fuera de este rango, el compilador generará un error. 165 | 166 | #### short 167 | 168 | El tipo primitivo `short` es un entero de complemento de dos con signo de 16 bits. Es una opción intermedia entre `byte` e `int` para almacenar números pequeños en aplicaciones que requieren optimización de memoria. 169 | 170 | java 171 | 172 | ```java 173 | // (-32,768 <= short <= 32,767) 174 | short foo = 10000; 175 | ``` 176 | 177 | > El rango de valores permitidos para `short` es de **-32,768** a **32,767** (ambos inclusive). Si se intenta asignar un valor fuera de este rango, el compilador generará un error. 178 | 179 | #### int 180 | 181 | El tipo primitivo `int` es un entero de complemento de dos con signo de 32 bits. Es el tipo predeterminado para los literales enteros. 182 | 183 | ```java 184 | // (-2,147,483,648 <= int <= 2,147,483,647) 185 | int foo = 1; 186 | ``` 187 | 188 | A partir de Java SE 8, es posible trabajar con enteros sin signo utilizando métodos especiales, aunque el tipo subyacente sigue siendo `int`. Un entero sin signo de 32 bits tiene un valor mínimo de 0 y un valor máximo de 2^32-1. 189 | 190 | Para trabajar con enteros sin signo usamos el método estático `Integer.parseUnsignedInt(String s)` y el método `Integer.toUnsignedString(int i)`: 191 | 192 | ```java 193 | int distancia = Integer.parseUnsignedInt("3000000000"); 194 | System.out.println(distancia); // Imprime un número negativo debido a la representación interna del int 195 | System.out.println(Integer.toUnsignedString(distancia)); // Imprime 3000000000 196 | ``` 197 | 198 | > El rango de valores permitidos para `int` es de **-2^31** a **2^31-1** (ambos inclusive). Si se intenta asignar un valor fuera de este rango, el compilador generará un error. 199 | 200 | #### long 201 | 202 | El tipo primitivo `long` es un entero de complemento de dos con signo de 64 bits. 203 | 204 | A partir de Java SE 8, se puede utilizar este tipo para representar un entero de 64 bits sin signo, que tiene un valor mínimo de 0 y un valor máximo de 2^64-1. 205 | 206 | ```java 207 | // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) 208 | long foo = 100000L; 209 | ``` 210 | 211 | El sufijo 'L' o 'l' (recomendable en mayúsculas por claridad) se utiliza para indicar que el valor literal asignado a la variable es de tipo `long`. Cualquier literal sin este sufijo se considera un entero por defecto (tipo `int`). 212 | 213 | > El rango de valores permitidos para `long` es de **-2^63** a **2^63-1** (ambos inclusive). Si se intenta asignar un valor fuera de este rango, el compilador generará un error. 214 | 215 | #### float 216 | 217 | El tipo primitivo `float` es un número de coma flotante IEEE 754 de precisión simple de 32 bits. Puede consultarse el rango de valores en la [documentación oficial](https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3). 218 | 219 | ```java 220 | float foo = 234.5f; 221 | ``` 222 | 223 | El sufijo 'f' o 'F' se utiliza para indicar que el valor literal asignado a la variable es de tipo `float`. Cualquier literal sin este sufijo se considerará como un `double` por defecto. 224 | 225 | > Este tipo de dato nunca debe utilizarse para valores que requieran alta precisión, como la moneda. Para estos casos, es recomendable utilizar el tipo `java.math.BigDecimal` en su lugar. 226 | 227 | #### double 228 | 229 | El tipo primitivo `double` es un número de coma flotante IEEE 754 de precisión doble de 64 bits. Para los valores decimales, este tipo de datos es la opción predeterminada. 230 | 231 | Puede consultarse el rango de valores en la [documentación oficial](https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3). 232 | 233 | ```java 234 | double foo = 123.4; 235 | ``` 236 | 237 | El sufijo 'd' o 'D' es opcional ya que cualquier literal sin este sufijo se considerará como un `double` por defecto. 238 | 239 | #### boolean 240 | 241 | Este tipo de dato sólo admite dos valores posibles: `true` o `false`. 242 | 243 | El tipo de dato `boolean` en Java sólo admite dos valores posibles: `true` o `false`. Los valores booleanos se utilizan comúnmente en condiciones y estructuras de control. 244 | 245 | ```java 246 | boolean foo = true; 247 | boolean bar = false; 248 | 249 | boolean baz = !foo; // baz será false 250 | ``` 251 | 252 | Además, se pueden combinar expresiones booleanas utilizando operadores lógicos: 253 | 254 | ```java 255 | boolean condition1 = (foo && bar); // AND: será false 256 | boolean condition2 = (foo || bar); // OR: será true 257 | ``` 258 | 259 | #### char 260 | 261 | El tipo primitivo `char` representa un **único carácter sin signo de 16 bits**. Esto permite realizar operaciones aritméticas sobre valores de tipo `char`. Este tipo está basado en la codificación UTF-16, lo que le permite representar una amplia variedad de caracteres, incluyendo caracteres especiales mediante secuencias de escape. 262 | 263 | ```java 264 | char fooChar = 'A'; 265 | fooChar++; // now fooChar == 'B' 266 | ``` 267 | 268 | Las constantes de carácter se incluyen entre comillas simples. 269 | 270 | A continuación, se presentan algunas de las secuencias de escape más comunes: 271 | 272 | - `\'` - Comilla simple 273 | - `\"` - Comilla doble 274 | - `\\` - Barra invertida 275 | - `\r` - Retorno de carro 276 | - `\n` - Nueva línea 277 | - `\f` - Salto de formulario 278 | - `\t` - Tabulación horizontal 279 | - `\b` - Retroceso 280 | - `\ddd` - Constante octal (donde 'ddd' es una constante octal) 281 | - `\uxxxx` - Constante hexadecimal (donde 'xxxx' es una constante hexadecimal) 282 | 283 | ### Valores literales 284 | 285 | En Java, un literal es un valor fijo representado en un formato legible para los humanos. Por ejemplo, el número 100 es un literal. Los literales también suelen denominarse constantes. 286 | 287 | Por defecto, los literales enteros son de tipo `int` y los literales de coma flotante son de tipo `double`. 288 | 289 | Los literales de carácter se incluyen entre comillas simples, mientras que los literales de cadena son conjuntos de caracteres que se encierran entre comillas dobles. 290 | 291 | ```java 292 | int a = 100; 293 | long b = 100L; 294 | double c = 100.5; 295 | float d = 100.5f; 296 | char f = 'f'; 297 | String str = "Literal de cadena"; 298 | 299 | int hexadecimal = 0xFF; // Formato hexadecimal que corresponde a 255 en decimal 300 | int octal = 011; // Formato octal que corresponde a 9 en decimal 301 | ``` 302 | 303 | A partir de JDK 7, se pueden emplear guiones bajos para mejorar la legibilidad de literales enteros o flotantes: 304 | 305 | ```java 306 | int x = 123_456_789; 307 | double z = 123_456_789.5; 308 | ``` 309 | 310 | ### Constantes 311 | 312 | La palabra clave `final` se utiliza para hacer que las variables sean **inmutable**. Por convención, el nombre de la variable se declara en mayúsculas: 313 | 314 | ```java 315 | final int HORAS_QUE_TRABAJO_POR_SEMANA = 40; 316 | ``` 317 | 318 | > Es obligatorio inicializar la constante en el momento de su declaración. 319 | 320 | El valor de una constante se puede calcular a partir del valor de otra constante: 321 | 322 | ```java 323 | final int HORAS_POR_DIA = HORAS_QUE_TRABAJO_POR_SEMANA / 5; 324 | ``` 325 | 326 | ### Autoboxing y unboxing 327 | 328 | En Java, los tipos primitivos no forman parte de la jerarquía de objetos por motivos de eficiencia. Sin embargo, existen **_clases envoltorio_** (_'wrapper classes'_) que encapsulan estos tipos primitivos, permitiendo tratarlos como objetos. Estas clases envoltorio son `Float`, `Double`, `Byte`, `Short`, `Integer`, `Long`, `Character` y `Boolean`. 329 | 330 | Todos los envoltorios de tipos numéricos heredan de la clase abstracta [`Number`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Number.html), lo que les otorga métodos útiles para convertir entre tipos o realizar operaciones. 331 | 332 | El proceso de encapsular un tipo primitivo en su clase envoltorio se denomina **_'boxing'_**, mientras que **_'autoboxing'_** es cuando el compilador realiza esta conversión automáticamente. El proceso inverso, llamado **_'auto-unboxing'_**, convierte automáticamente un objeto envoltorio a su tipo primitivo. 333 | 334 | ```java 335 | // Boxing explícito (sin autoboxing) 336 | Integer num = Integer.valueOf(100); 337 | 338 | // Autoboxing (el compilador convierte automáticamente 'int' a 'Integer') 339 | Integer iOb = 100; 340 | 341 | // Auto-unboxing (el compilador convierte automáticamente 'Integer' a 'int') 342 | int i = iOb; 343 | ``` 344 | 345 | La clase abstracta [`Number`](https://docs.oracle.com/javase/8/docs/api/java/lang/Number.html) también proporciona métodos como `intValue()` o `floatValue()` para realizar la conversión, teniendo en cuenta que puede haber **redondeo** o **truncamiento** si se cambia de tipo: 346 | 347 | ```java 348 | Float foo = 123.56F; 349 | // Conversión de 'Float' a 'float' 350 | float bar = foo.floatValue(); 351 | ``` 352 | 353 | Aunque el **_'autoboxing'_** simplifica el código, puede generar una sobrecarga de trabajo extra innecesaria en determinadas situaciones, donde se podría trabajar perfectamente con un tipo primitivo: 354 | 355 | ```java 356 | Integer sum = 0; 357 | for (int i = 0; i < 1000000; i++) { 358 | sum += i; // Se produce autoboxing y unboxing en cada iteración 359 | } 360 | ``` 361 | 362 | Al realizar **_'auto-unboxing'_**, si el objeto envoltorio no se ha inicializado y es `null`, se lanzará una excepción `NullPointerException`: 363 | 364 | ```java 365 | Integer iOb = null; 366 | int i = iOb; // NullPointerException, ya que iOb es null 367 | ``` 368 | 369 | Los objetos envoltorio no deben compararse usando `==`, ya que esto comparará las referencias de los objetos y no sus valores. Se recomienda usar el método `.equals()` para comparar objetos: 370 | 371 | ```java 372 | Integer a = 1000; 373 | Integer b = 1000; 374 | 375 | System.out.println(a == b); // false, ya que compara las referencias 376 | System.out.println(a.equals(b)); // true, ya que compara los valores 377 | ``` 378 | 379 | - ["Autoboxing and Unboxing - The Java Tutorials"](https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) 380 | 381 | ### Conversión de tipos 382 | 383 | En Java, es posible realizar conversiones entre tipos primitivos de manera explícita o implícita. 384 | 385 | La **conversión implícita** ocurre cuando el tipo de destino tiene un rango mayor que el tipo de origen y, por tanto, no habrá pérdida de precisión. 386 | 387 | ```java 388 | int a = 10; 389 | double b = a; // Conversión implícita de int a double 390 | ``` 391 | 392 | La **conversión explícita** (también llamada _'casting'_) es necesaria cuando se desea convertir un tipo más grande a un tipo más pequeño, con el posible riesgo de pérdida de datos. 393 | 394 | ```java 395 | double x = 10.5; 396 | int y = (int) x; // Conversión explícita de double a int (truncado) 397 | System.out.println(y); // Imprime 10 398 | ``` 399 | 400 | La clase abstracta [`Number`](https://docs.oracle.com/javase/8/docs/api/java/lang/Number.html) también proporciona métodos como `intValue()` o `floatValue()` para realizar la conversión, teniendo en cuenta que puede haber **redondeo** o **truncamiento** si se cambia de tipo: 401 | 402 | ```java 403 | Float foo = 123.56F; 404 | // Conversión de 'Float' a 'float' 405 | float bar = foo.floatValue(); 406 | // Cambio de tipo de 'Float' a 'int' 407 | int baz = foo.intValue();// Truncamiento de decimales 408 | ``` 409 | 410 | - ["Converting Between Numbers and Strings - The Java Tutorials"](https://docs.oracle.com/javase/tutorial/java/data/converting.html) 411 | 412 | #### Conversión de Strings a Numbers 413 | 414 | Las clases envoltorio (`Integer`, `Double`, etc.) que son subclases de `Number`, disponen de métodos `valueOf()`, que permiten convertir una cadena en un objeto de ese tipo. Si no se puede realizar la conversión de lanza un `NumberFormatException`: 415 | 416 | ```java 417 | String foo = "12345"; 418 | // Conversión de 'String' a 'Integer' 419 | Integer bar = Integer.valueOf(foo); 420 | ``` 421 | 422 | Además, estas clases que son subclases de `Number` proveen métodos `parseXXXXX()` como `parseInt()` para convertir cadenas en tipos primitivos numéricos: 423 | 424 | ```java 425 | String foo = "12345"; 426 | // Conversión de 'String' a 'Integer' 427 | int bar = Integer.parseInt(foo); 428 | ``` 429 | 430 | #### Conversión de Numbers a Strings 431 | 432 | Para convertir tipos primitivos numéricos a cadenas de caracteres, la clase [`String`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html) de Java ofrece el método sobrecargado `valueOf()`: 433 | 434 | ```java 435 | // Conversión explícita mediante 'valueOf()' 436 | String foo = String.valueOf(100); 437 | ``` 438 | 439 | También puedes utilizar la concatenación automática para realizar una conversión implícita: 440 | 441 | ```java 442 | String bar = "El importe del pedido es " + 56.75; // Convierte 'double' a 'String' 443 | ``` 444 | 445 | Las clases envoltorio (`Integer`, `Double`, etc.) que son subclases de `Number`, también disponen de métodos `toString()`, que permiten convertir un valor numérico a su representación en cadena: 446 | 447 | ```java 448 | Integer foo = 12345; 449 | String bar = foo.toString(); // Convierte 'Integer' a 'String' 450 | ``` 451 | 452 | ### Bloques 453 | 454 | Un **bloque de código es un grupo de dos o más instrucciones definidas entre llaves (`{}`)**. Al crear un bloque de código, se convierte en una unidad lógica que se puede usar como si fuera una instrucción independiente. 455 | 456 | Un bloque de código define un **ámbito**. Las variables definidas dentro de un ámbito o bloque de código no son accesibles fuera de ese ámbito. Cada vez que se accede a un bloque, las variables contenidas en ese bloque se inicializan, y cuando el bloque finaliza, se destruyen. 457 | 458 | Una variable está disponible a partir de su definición. Por lo tanto, si se define una variable al final de un bloque, no se podrá utilizar (y tampoco tiene sentido). 459 | 460 | Los **bloques se pueden anidar**, lo que significa que un bloque de código puede contener a otro bloque de código. Desde un bloque interior se puede acceder a las variables definidas en el bloque exterior, pero el bloque exterior no puede acceder a las variables definidas en el bloque interior. 461 | 462 | ```java 463 | public class Bloques { 464 | public static void main(String ... args) { 465 | String exterior = "Bloque exterior"; 466 | 467 | { 468 | String interior = "Bloque interior"; 469 | System.out.println(interior); // Correcto 470 | System.out.println(exterior); // Correcto 471 | } 472 | 473 | System.out.println(exterior); // Correcto 474 | // System.out.printf(interior); // Error ya que 'interior' no es accesible 475 | } 476 | } 477 | ``` 478 | 479 | ### Operadores 480 | 481 | Java ofrece una variedad de [operadores](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html) que permiten realizar diferentes tipos de operaciones. 482 | 483 | El operador más básico es el **operador de asignación (`=`)**, que permite asignar un valor a una variable: 484 | 485 | ```java 486 | int cadence = 0; 487 | int speed = 0; 488 | int gear = 1; 489 | ``` 490 | 491 | Los **operadores aritméticos** realizan operaciones matemáticas básicas: 492 | 493 | ```java 494 | int suma = 4 + 5; // => 9 495 | int resta = 8 - 5; // => 3 496 | int multiplicacion = 4 * 3; // => 12 497 | int division = 11 / 3; // => 3 498 | int modulo = 11 % 3; // => 2 499 | ``` 500 | 501 | Los **operadores de comparación** comparan dos valores y devuelven un resultado booleano: 502 | 503 | ```java 504 | boolean igualdad = 3 == 2; // => false 505 | boolean desiguladad = 3 != 2; // => true 506 | boolean superior = 3 > 2; // => true 507 | boolean inferior = 3 < 2; // => false 508 | boolean superiorIgual = 2 <= 2; // => true 509 | boolean inferiorIgual = 2 >= 2; // => true 510 | ``` 511 | 512 | Los **operadores de asignación abreviada** combinan la operación de asignación con otros operadores: 513 | 514 | ```java 515 | int x = 10; 516 | x += 10; // x = x + 10; 517 | x -= 10; // x = x - 10; 518 | x *= 10; // x = x - 10; 519 | x /= 10; // x = x / 10; 520 | x %= 10; // x = x % 10; 521 | 522 | boolean bool = true; 523 | bool &= true; // bool = bool & true; 524 | bool |= true; // bool = bool | true; 525 | bool ^= true; // bool = bool ^ true; 526 | ``` 527 | 528 | Los **operadores de incremento y decremento** permiten aumentar o disminuir el valor de una variable: 529 | 530 | ```java 531 | int y, x = 10; 532 | 533 | y = x++; // y = 10. Primero se asigna el valor y luego se aumenta 534 | y = ++x; // y = 11. Primero se aumenta y luego se asigna 535 | y = x--; // y = 10. Primero se asigna el valor y luego se resta 536 | y = --x; // y = 9. Primero se resta y luego se asigna 537 | ``` 538 | 539 | Los **operadores lógicos** son fundamentales para realizar evaluaciones condicionales y tomar decisiones en el flujo de un programa. 540 | 541 | Estos operadores permiten combinar o modificar expresiones booleanas, que son aquellas que pueden evaluarse como verdaderas o falsas: 542 | 543 | | `A` | `B` | `A|B` | `A&B` | `A^B` | `!A` | 544 | | :-------: | :-------: | :------: | :-------: | :-------: | :-------: | 545 | | False | False | False | False | False | True | 546 | | True | False | True | False | True | False | 547 | | False | True | True | False | True | True | 548 | | True | True | True | True | False | False | 549 | 550 | Los operadores lógicos _'AND'_ (`&&`) y _'OR'_ (`||`) pueden funcionar **en modo cortocircuito**. En este modo se evalúa el primer operando y si fuera necesario, se evaluaría el segundo. 551 | 552 | ### Cadenas 553 | 554 | En Java, una cadena de caracteres se representa con el tipo `String`, que es una clase **inmutable**, lo que significa que una vez creada, no se puede modificar. Si se realiza alguna operación que parece modificar la cadena, en realidad se está creando una nueva instancia de `String`. 555 | 556 | ```java 557 | String foo = "¡Mi String está aquí!"; 558 | 559 | // \n es un carácter escapado que inicia una nueva línea 560 | String bar = "¿Imprimiendo en una nueva linea?\n¡Ningun problema!"; 561 | 562 | // \t es un carácter escapado que añade un carácter tab 563 | String baz = "¿Quieres añadir un 'tab'?\t¡Ningun problema!"; 564 | 565 | // Escapar las comillas dobles 566 | String quoteString = "Alguien dijo: \"Java es genial\"."; 567 | ``` 568 | 569 | Las cadenas se pueden concatenar utilizando el operador `+`, lo que también crea una nueva cadena: 570 | 571 | ```java 572 | String name = "Juan"; 573 | String greeting = "Hola, " + name + "!"; 574 | System.out.println(greeting); // Imprime: Hola, Juan! 575 | ``` 576 | 577 | La clase `String` proporciona varios métodos útiles para manipular y trabajar con cadenas, como: 578 | 579 | - `length()` – Devuelve la longitud de la cadena. 580 | 581 | - `charAt(int index)` – Devuelve el carácter en la posición especificada. 582 | 583 | - `substring(int beginIndex, int endIndex)` – Devuelve una subcadena de la cadena original. 584 | 585 | - `toUpperCase()` y `toLowerCase()` – Devuelven la cadena en mayúsculas o minúsculas, respectivamente. 586 | 587 | - `indexOf(String str)` – Devuelve la posición de la primera aparición de la subcadena especificada. 588 | 589 | La clase `String` también permite la comparación de cadenas mediante el método `equals()` y `equalsIgnoreCase()` para comparaciones sin distinción entre mayúsculas y minúsculas: 590 | 591 | ```java 592 | String str1 = "Java"; 593 | String str2 = "java"; 594 | System.out.println(str1.equals(str2)); // false 595 | System.out.println(str1.equalsIgnoreCase(str2)); // true 596 | ``` 597 | 598 | La clase `StringBuilder` se utiliza para crear y manipular cadenas de caracteres de manera más eficiente que la clase `String`, especialmente cuando se realizan múltiples operaciones de concatenación o modificación. A diferencia de `String`, los objetos de `StringBuilder` son **mutables**, lo que significa que se puede modificar su contenido sin crear nuevas instancias. 599 | 600 | ```java 601 | StringBuilder sbWithContent = new StringBuilder("¡Hola, mundo!"); // Crea un StringBuilder con contenido inicial 602 | 603 | StringBuilder sb = new StringBuilder(); // Crea un StringBuilder vacío 604 | sb.append("Hola"); 605 | sb.append(", "); 606 | sb.append("mundo!"); 607 | String result = sb.toString(); // result es "Hola, mundo!" 608 | System.out.println(result); 609 | ``` 610 | 611 | - ["Strings - The Java Tutorials"](https://docs.oracle.com/javase/tutorial/java/data/strings.html) 612 | 613 | ### Control de flujo 614 | 615 | El **control de flujo** en Java permite alterar el orden en que se ejecutan las instrucciones de un programa basándose en condiciones lógicas. 616 | 617 | Las **estructuras condicionales** mediante instrucciones `if-else` evalúa una condición booleana para decidir qué bloque de código ejecutar: 618 | 619 | ```java 620 | if (condición) { 621 | // Bloque de instrucciones si la condición es verdadera 622 | } else if (otraCondición) { 623 | // Bloque si se cumple otra condición 624 | } else { 625 | // Bloque si no se cumplen las condiciones anteriores 626 | } 627 | ``` 628 | 629 | Los **bucles** permiten ejecutar repetidamente un bloque de código mientras una condición sea verdadera: 630 | 631 | ```java 632 | while (condición) { 633 | // Bloque de instrucciones que se repiten mientras la condición sea verdadera 634 | } 635 | ``` 636 | 637 | En el bucle `do-while`, el bloque de código se ejecuta al menos una vez, ya que la condición se evalúa después: 638 | 639 | ```java 640 | do { 641 | // Bloque de instrucciones 642 | } while (condición); 643 | ``` 644 | 645 | El bucle `for` proporciona una forma compacta de iterar: 646 | 647 | ```java 648 | for(int i=1; i<11; i++){ 649 | System.out.println("Count is: " + i); 650 | } 651 | ``` 652 | 653 | En Java, el cuerpo asociado a un bucle `for` o de otro tipo puede estar vacío ya que una instrucción vacía es sintácticamente válida. Puede ser útil en algunos casos: 654 | 655 | ```java 656 | int sum = 0; 657 | for(int i = 1; i<= 5; sum += i++); 658 | // Se usa el bucle for para incrementar la variable sum 659 | ``` 660 | 661 | Las tres expresiones de un bucle `for` son opcionales, de forma que se puede crear un bucle infinito: 662 | 663 | ```java 664 | // infinite loop 665 | for ( ; ; ) { 666 | // your code goes here 667 | } 668 | ``` 669 | 670 | En la versión de Java JDK 5 se añadió los bucles `for-each` que permiten iterar por matrices, clases del paquete 'Collections', etc... 671 | 672 | ```java 673 | int[] numbers = {1,2,3,4,5,6,7,8,9,10}; 674 | for (int item : numbers) { 675 | System.out.println("Count is: " + item); 676 | } 677 | ``` 678 | 679 | La estructura `switch` funciona con tipos numéricos simples como `byte`, `short`, `char` e `int`. También funciona con tipos enumerados, la clase `String` y unas pocas clases especiales que envuelven tipos primitivos: `Character`, `Byte`, `Short` e `Integer`. 680 | 681 | ```java 682 | int mes = 3; 683 | switch (mes) { 684 | case 1: 685 | System.out.println("Enero"); 686 | break; 687 | case 2: 688 | System.out.println("Febrero"); 689 | break; 690 | case 3: 691 | System.out.println("Marzo"); 692 | break; 693 | default: 694 | break; 695 | } 696 | ``` 697 | 698 | - ["Control Flow Statements - The Java Tutorials"](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html) 699 | 700 | #### Break 701 | 702 | Por medio de la instrucción `break` se puede forzar la salida inmediata de un bucle e ignorar el código restante del cuerpo y la prueba condicional. El control del programa se pasa a la siguiente instrucción después del bucle. 703 | 704 | #### Continue 705 | 706 | Con la instrucción `continue` se fuerza una iteración del bucle, es decir, se ignora el código comprendido entre esta instrucción y la expresión condicional que controla el bucle. 707 | 708 | Tanto `break` como `continue` pueden funcionar junto a una etiqueta permitiendo dirigir el control del programa al bloque de código indicado por la etiqueta. Un `break` o `continue` etiquetados se declaran con `break {etiqueta}` y `continue {etiqueta}`. El único requisito es que el bloque de código con la etiqueta debe contener la instrucción `break` o `continue`. Es decir, no se puede utilizar un `break` como si fuera una instrucción `goto`. 709 | 710 | ```java 711 | public class Sample{ 712 | public static void main(String ... args){ 713 | for (int i = 0; i < 4; i++) { 714 | one: { 715 | two: { 716 | if(i == 1) break one; 717 | if(i == 2) break two; 718 | } 719 | System.out.println("After two"); 720 | } 721 | System.out.println("After one"); 722 | } 723 | } 724 | } 725 | ``` 726 | 727 | ### Paquetes 728 | 729 | **Todas las clases en Java pertenecen a un paquete**. Si no se especifica uno se usa el paquete predeterminado (o global). 730 | 731 | Al definir una clase en un paquete, se añade el nombre de dicho paquete a cada clase, lo que evita colisiones de nombres con otras clases. El paquete debe coincidir con la jerarquía de directorios. Los nombres de paquetes se escriben en minúsculas para evitar conflictos con los nombres de clases o interfaces. 732 | 733 | Para definir un paquete se utiliza la palabra clave `package`: 734 | 735 | ```java 736 | package paquete1.paquete2....paqueteN; 737 | ``` 738 | 739 | ### Importación 740 | 741 | Cuando se usa una clase de otro paquete, se debe cualificar su nombre con el nombre de su paquete, como por ejemplo `java.util.ArrayList`. 742 | 743 | Sin embargo, podemos usar la palabra clave `import` para importar uno o varios miembros de un paquete. El paquete `java.lang` es exclusivo ya que se importa automáticamente en todos los programas Java. 744 | 745 | Por tanto se puede importar una **clase concreta** o importar **todas las clases** de un paquete con el astericos (`*`). 746 | 747 | La sentencia `import` se utiliza después de la sentencia `package` si existe. 748 | 749 | ```java 750 | package com.example; 751 | 752 | //import java.lang.*; // importación automática por defecto 753 | import java.util.HashMap; 754 | 755 | public class example { 756 | public static void main(String[] args) { 757 | // Al no realizar la importación hay que cualificar el nombre 758 | java.util.ArrayList aList = new java.util.ArrayList(); 759 | 760 | // Al realizar la importación podemos usar 'HashMap' 761 | HashMap hMap = new HashMap<>(); 762 | } 763 | } 764 | ``` 765 | 766 | #### Importación estática 767 | 768 | Java admite la importación de campos estáticos finales (constantes) y de métodos estáticos usando la forma `import static`. Al usar este tipo de importación, se puede hacer referencia directamente a miembros estáticos por sus nombres, sin necesidad de calificarlos con el nombre de su clase. 769 | 770 | ```java 771 | import static java.lang.Math.sqrt; 772 | // import static java.lang.Math.pow; 773 | // import static java.lang.Math.*; // importa todos los miembros estáticos 774 | 775 | void operation () { 776 | sqrt(9); // con importación estática 777 | Math.pow(5, 8); // sin importación estática 778 | } 779 | ``` 780 | 781 | ## Arrays 782 | 783 | Un array en Java es una **estructura de datos** que almacena múltiples elementos del mismo tipo. 784 | 785 | Notación para la declaración de un array (el tamaño del array debe decidirse en la declaración): 786 | 787 | - ` [] = new [];` 788 | 789 | ```java 790 | int[] sample = new int[10]; 791 | int sample[] = new int[5]; 792 | String[] sample = new String[1]; 793 | boolean[] sample = new boolean[100]; 794 | int[] sample1, sample2, sample3; 795 | ``` 796 | 797 | Notación para la declaración e inicialización de un array en una sola línea: 798 | 799 | - ` [] = {value, value, ...};` 800 | 801 | ```java 802 | int[] sample = {2015, 2016, 2017}; 803 | ``` 804 | 805 | Los arrays **comienzan su indexación en cero** y son **mutables**, lo que significa que se pueden cambiar los valores de sus elementos: 806 | 807 | ```java 808 | sample[1] = 2018; 809 | System.out.println("Year: " + sample[1]); // => 2018 810 | ``` 811 | 812 | Acceder un elemento dentro de un array (un intento de acceso fuera de los límites del array lanza un `ArrayIndexOutOfBoundsException`): 813 | 814 | ```java 815 | int[] arr = {1, 2, 3}; 816 | System.out.println(arr[3]); // Lanza ArrayIndexOutOfBoundsException 817 | ``` 818 | 819 | Al asignar una referencia de una matriz a otra referencia no se crea una copia de la matriz ni se copian los contenidos. Sólo se crea una referencia a la misma matriz, al igual que sucede con cualquier otro objeto. Por lo tanto, a partir de ambas referencias se accede a la **misma instancia de array**: 820 | 821 | ```java 822 | int[] nums = {1, 2, 3}; 823 | int[] other = nums; // Ahora 'other' apunta a la misma matriz que 'nums'. 824 | ``` 825 | 826 | Java también soporta **arrays multidimensionales**, que son arrays cuyos elementos son a su vez arrays. El tipo más común es el array bidimensional, que puede visualizarse como una tabla con filas y columnas. 827 | 828 | ```java 829 | int[][] matrix = new int[3][3]; // Array bidimensional de 3x3 830 | 831 | // Declaración e inicialización en una sola línea 832 | int[][] matrix = { 833 | {1, 2, 3}, 834 | {4, 5, 6}, 835 | {7, 8, 9} 836 | }; 837 | ``` 838 | 839 | La **complejidad temporal** de un algoritmo mide cuánto tiempo tarda en ejecutarse en función del tamaño de la entrada. En el caso de los arrays, el tamaño de la entrada suele ser el número de elementos que contiene. Esta complejidad se denota como **notación O grande** o **_("Big O")_**. 840 | 841 | **Acceder a un elemento** en un array utilizando su índice es una operación de complejidad `O(1)`, también conocida como tiempo constante. Esto significa que el tiempo necesario para acceder a un elemento no depende del tamaño del array. 842 | 843 | ```java 844 | int element = myArray[5]; // O(1) 845 | ``` 846 | 847 | La **búsqueda de un elemento** en un array sin un orden específico (búsqueda lineal), la complejidad es `O(n)`, donde n es el número de elementos en el array. En el peor de los casos, podrías necesitar revisar todos los elementos. 848 | 849 | ```java 850 | for (int i = 0; i < myArray.length; i++) { 851 | if (myArray[i] == target) { 852 | // Elemento encontrado 853 | } 854 | } // O(n) 855 | ``` 856 | 857 | La **inserción de un elemento** al final de un array (suponiendo que ya existe espacio), es una operación de complejidad `O(1)`. Sin embargo, si necesitas insertar en una posición específica, tendrás que mover los elementos, lo que resulta en una complejidad de `O(n)`. 858 | 859 | ```java 860 | // Inserción al final 861 | myArray[myArray.length - 1] = newElement; // O(1) 862 | 863 | // Inserción en una posición específica 864 | for (int i = myArray.length - 1; i > index; i--) { 865 | myArray[i] = myArray[i - 1]; // O(n) 866 | } 867 | ``` 868 | 869 | La **eliminación de un elemento** de un array, también debes mover los elementos restantes para llenar el hueco, lo que resulta en una complejidad de `O(n)`. 870 | 871 | ```java 872 | for (int i = index; i < myArray.length - 1; i++) { 873 | myArray[i] = myArray[i + 1]; // O(n) 874 | } 875 | ``` 876 | 877 | La clase [`Arrays`](https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html) de Java es una clase de utilidad que proporciona varios métodos estáticos para trabajar con arrays. Esta clase es parte del paquete `java.util` y no se puede instanciar, ya que todos sus métodos son estáticos. Tiene métodos para la ordenación (`Arrays.sort()`), búsqueda (`Arrays.binarySearch()`), comparación (`Arrays.equals()`) o copiado (`Arrays.copyOf()`). 878 | 879 | - [Arrays - The Java Tutorials](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html) 880 | 881 | ## Clases y objetos 882 | 883 | Una definición de clase crea un **nuevo tipo de datos**: 884 | 885 | ```java 886 | class Bicicleta { 887 | 888 | // Campos o variables de instancia 889 | public String nombre; // Puede ser accedido desde cualquier parte 890 | private double precio; // Accesible sólo desde esta clase 891 | protected int velocidad; // Accesible desde esta clase, sus subclases o el mismo paquete 892 | int numMarchas; // default: Sólo accesible desde este paquete 893 | 894 | // Constructores son la manera de crear clases 895 | // Este es un constructor por defecto 896 | public Bicicleta() { 897 | numMarchas = 18; 898 | precio = 2495.99; 899 | velocidad = 45; 900 | nombre = "Bontrager"; 901 | } 902 | 903 | // Este es un constructor específico (contiene argumentos) 904 | public Bicicleta(String nombre) { 905 | super(); // llamada al constructor sin parámetros 'Bicicleta()'; 906 | this.nombre = nombre; 907 | } 908 | 909 | // Este es un constructor específico (contiene argumentos) 910 | public Bicicleta(String nombre, double precio) { 911 | this(nombre); // llamada al constructor 'Bicicleta(String nombre)'; 912 | this.precio = precio; 913 | } 914 | 915 | // Sintaxis de método: 916 | // () 917 | 918 | // Las clases de Java usualmente implementan métodos 'get' (obtener) 919 | // y 'set' (establecer) para sus campos 920 | 921 | // Sintaxis de declaración de métodos 922 | // () 923 | public double getPrecio() { 924 | return precio; 925 | } 926 | 927 | public void setPrecio(double precio) { 928 | this.precio = precio; 929 | } 930 | 931 | // .... 932 | 933 | //Método para mostrar los valores de los atributos de este objeto. 934 | @Override 935 | public String toString() { 936 | return "Bicicleta{" + 937 | "nombre='" + nombre + '\'' + 938 | ", precio=" + precio + 939 | ", velocidad=" + velocidad + 940 | ", numMarchas=" + numMarchas + 941 | '}'; 942 | } 943 | } 944 | ``` 945 | 946 | Todas las clases tienen al menos un constructor predeterminado ya que Java ofrece automáticamente un constructor que inicializa todas las variables miembro en sus valores predeterminados que son **cero(0), 'null' y 'false'**. Cuando se crea un constructor el predeterminado deja de usarse. 947 | 948 | Hay otra forma de `this` que permite que un constructor invoque a otro dentro de la misma clase. Cuando se ejecuta `this(lista-args)`, el constructor sobrecargado que encaja con la lista de parámetros especificada se ejecutará y se **ejecutará primero**. Por tanto no se puede usar `this()` y `super()` al mismo tiempo ya que ambos deben ser la primera instrucción. 949 | 950 | El operador `new` asigna dinámicamente, es decir, en tiempo de ejecución, memoria para un objeto y devuelve una referencia al mismo. Esta referencia es, ni más ni menos, que la dirección en memoria del objeto asignado por `new`, que después se almacena en una variable para poder ser utilizada posteriormente. 951 | 952 | ```java 953 | Bicicleta bicicleta = new Bicicleta(); 954 | Bicicleta bicicleta2 = bicicleta; // Ambas variables hacen referencia al mismo objeto 955 | ``` 956 | 957 | ### Clases anidadas 958 | 959 | La clases anidadas no estáticas también se denominan [**clases internas**](https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html). Una clase interna no existe independientemente de su clase contenedora, ya que el ámbito de una clase interna lo define la clase externa. También se pueden definir clases que sean locales de un bloque. 960 | 961 | Una clase interna tiene acceso a todas las variables y métodos de su clase externa y puede hacer referencia a los mismos directamente como hacen otros miembros no estáticos de la clase externa. 962 | 963 | ```java 964 | class Outern { 965 | int a = 5; 966 | int b = 10; 967 | 968 | void sum() { 969 | Intern intern = new Intern(); 970 | System.out.println(intern.operation()); 971 | } 972 | 973 | class Intern { 974 | int operation() { 975 | return a + b; 976 | } 977 | } 978 | } 979 | ``` 980 | 981 | ## Métodos 982 | 983 | Notación para la definición de un método: 984 | 985 | - ` ()` 986 | 987 | Los **parámetros** aparecen en la definición del método. Cuando un método tiene parámetros la parte de su definición que los especifica se denomina 'lista de parámetros'. 988 | 989 | La **firma** de un método se compone del **nombre del método y la lista de parámetros**. 990 | 991 | Hablamos de **argumentos** cuando usamos valores concretos para realizar la llamada al método. El valor concreto pasado a un método es el argumento. Dentro del método, la variable que recibe el argumento es el parámetro. 992 | 993 | ```java 994 | int sum(int a, int b) { // lista de parámetros del método. Junto con el nombre forman la firma 995 | return a + b; 996 | } 997 | 998 | sum(10, 20); // Llamada al método usando dos argumentos o valores 999 | ``` 1000 | 1001 | Para la devolución de un valor en un método se utiliza la palabra clave `return`. La sentencia `return` tiene dos formas: una forma sirve para devolver un valor y la otra sirve para salir de un método cuando retorna `void`: 1002 | 1003 | ```java 1004 | int sum(int a, int b) { 1005 | return a + b; 1006 | } 1007 | 1008 | void isEven(int num) { 1009 | if(num % 2 == 0) 1010 | return; 1011 | else 1012 | System.out.println("Num is odd"); 1013 | } 1014 | ``` 1015 | 1016 | En Java, cuando se pasa como argumento un tipo primitivo se pasa **por valor**, lo que significa que se crea una copia del valor original y los cambios realizados dentro del método no afectan a la variable original fuera del método. 1017 | 1018 | En cambio, cuando se pasa un objeto, lo que se pasa es una **copia de la referencia al objeto**, no el propio objeto en sí. Esto implica que los cambios realizados en los atributos del objeto dentro del método afectarán al objeto original, pero no se puede reasignar la referencia para que apunte a otro objeto. 1019 | 1020 | Es posible declarar un parámetro como `final`, lo que evitará que la referencia se reasigne dentro del método. Sin embargo, esto no impide modificar los atributos del objeto referenciado: 1021 | 1022 | ```java 1023 | class Car { 1024 | public int speed; 1025 | 1026 | public Car(int speed) { 1027 | this.speed = speed; 1028 | } 1029 | } 1030 | 1031 | class Main { 1032 | public static void main(String[] args) { 1033 | Car car = new Car(100); 1034 | System.out.println("Speed: " + car.speed); // Prints '100' 1035 | bicycle = incrementSpeed(bicycle); 1036 | System.out.println("Speed: " + car.speed); // Prints '125' 1037 | 1038 | } 1039 | 1040 | public static Bicycle incrementSpeed(final Bicycle bicycle) { 1041 | bicycle.speed = 125; // Podemos asignar nuevos valores a los atributos del objeto 1042 | // bicycle = new Bicycle(125); // ERROR! La variable 'bicycle es una variable final 1043 | return bicycle; 1044 | } 1045 | } 1046 | 1047 | ``` 1048 | 1049 | ### Sobrecarga de métodos 1050 | 1051 | La sobrecarga de métodos es una de las técnicas de Java para implementar el **polimorfismo**. En Java, dos o más métodos de la misma clase pueden compartir el mismo nombre siempre y cuando su **firma sea diferente**. Por tanto, para sobrecargar un método, basta con declarar métodos con distinta firma. En Java, la firma de un método es el **nombre del método más su lista de parámetros**, sin incluir el tipo devuelto. Por tanto, la sobrecarga de métodos son métodos con el mismo nombre pero distinta lista de parámetros, sin tener en cuenta el tipo de devolución. 1052 | 1053 | Por ejemplo, en la clase `java.lang.Math` se utiliza la sobrecarga de métodos para disponer de varios métodos que realizan la misma operación sobre tipos diferentes: 1054 | 1055 | ```java 1056 | public static double abs(double a) 1057 | public static float abs(float a) 1058 | public static long abs(long a) 1059 | public static int abs(int a) 1060 | ``` 1061 | 1062 | ### Argumentos de longitud variable: `varargs` 1063 | 1064 | En ocasiones será necesario métodos que acepten una número variable de argumentos. Se define con el símbolo (`...`). 1065 | 1066 | La firma de un método con argumentos de longitud variable es: 1067 | 1068 | - `tipo método(tipo ... var) {}` 1069 | 1070 | Dentro del método esta variable se utiliza como una array. Por lo tanto, para acceder a los parámetros se emplea la misma notación que se emplea en un array. Un método puede tener parámetros normales además de parámetros de longitud variable. En ese caso, **los parámetros normales van delante y por último el parámetro de longitud variable**. 1071 | 1072 | ## Modificador `static` 1073 | 1074 | Se pueden definir como `static` tanto variables como métodos. Las variables declarados como `static` son básicamente **variables globales**. Todas las instancias de la clase comparten la misma variable. 1075 | 1076 | Los métodos `static` tienen ciertas restricciones: 1077 | 1078 | - Sólo pueden invocar directamente otros métodos `static` 1079 | - Sólo pueden acceder directamente a datos `static` 1080 | - Carecen de una referencia `this` 1081 | 1082 | ### Bloque `static` 1083 | 1084 | Cuando una clase requiere de cierta inicialización antes de que pueda crear objetos se puede usar un bloque `static` que se ejecuta al cargar la clase por primera vez: 1085 | 1086 | ```java 1087 | class staticBlock { 1088 | static int a; 1089 | static int b; 1090 | 1091 | // Este bloque se ejecuta al cargar la clase por primera vez 1092 | // y antes que cualquier otro método 'static' 1093 | static { 1094 | a = 5; 1095 | b = 10; 1096 | } 1097 | } 1098 | ``` 1099 | 1100 | ## Herencia 1101 | 1102 | La **herencia** es uno de los tres principios fundamentales de la programación orientada a objetos ya que permite crear clasificaciones jerárquicas. 1103 | 1104 | Se invoca al constructor de la superclase con `super(lista-parámetros)`. Esta instrucción debe ser **siempre la primera instrucción** ejecutada dentro del constructor de la subclase. El constructor de la superclase inicializa la parte de la superclase y el constructor de la subclase la parte de la subclase. En una jerarquía de clases, los constructores se invocan en orden de derivación, de **superclase a subclase**. 1105 | 1106 | Con `super.miembro` en donde miembro puede ser un método o una variable de instancia, podemos hacer referencia a métodos o variables de la superclase desde una subclase. 1107 | 1108 | Java es un lenguaje de **tipado fuerte**. Por lo tanto una variable de tipo sólo puede hacer referencia a objetos de ese tipo. Sin embargo, existe una excepción cuando aplicamos la herencia. Se puede asignar a una variable de referencia de una superclase una referencia a un objeto de cualquier subclase derivada de dicha superclase. Es decir, una referencia de superclase puede hacer referencia a un objeto de subclase. 1109 | 1110 | Hay que tener en cuenta que cuando se asigna una referencia de un objeto de subclase a una variable de referencia de superclase **sólo** se tiene acceso a las partes del objeto que defina la superclase. 1111 | 1112 | ```java 1113 | class Vehicle { 1114 | void echo() {} 1115 | } 1116 | 1117 | class Car extends Vehicle { 1118 | void gamma(){} 1119 | 1120 | void sample() { 1121 | // El tipo 'Car' es una subclase de 'Vehicle' 1122 | Vehicle vehicle = new Car(); 1123 | vehicle.echo(); // Correcto 1124 | // vehicle.gamma(); // Incorrecto. 1125 | // Sólo tenemos acceso a las partes que definen la superclase. 1126 | } 1127 | } 1128 | ``` 1129 | 1130 | ### Sobreescritura de métodos 1131 | 1132 | En una jerarquía de clases, cuando un método de una subclase tiene el mismo tipo de devolución y firma (nombre y parámetros) que un método de su superclase, el método de la subclase reemplaza o sobreescribe al de la superclase. 1133 | 1134 | **Si la firma no es exacta, ya no hablamos de sobreescritura de métodos sino de sobrecarga de métodos**. 1135 | 1136 | La sobreescritura de métodos es importante porque es la forma de implementar el **polimorfismo** en Java. El compilador, en tiempo de ejecución, será el encargado de invocar el método adecuado. 1137 | 1138 | Si usamos la anotación `@Override` en un método le estamos indicando al compilador que es un método sobreescrito y por tanto puede realizar las comprobaciones pertinentes en tiempo de compilación, como por ejemplo que el método original sigue existiendo en la superclase o que no ha sido modificado. 1139 | 1140 | ```java 1141 | class Vehicle { 1142 | void show() {} 1143 | } 1144 | 1145 | class Car extends Vehicle { 1146 | @Override 1147 | void show() {} 1148 | } 1149 | 1150 | class Motocycle extends Vehicle { 1151 | @Override 1152 | void show() { 1153 | super.show(); // Podemos invocar al método 'show()' de la superclase 1154 | } 1155 | } 1156 | 1157 | public class Sample { 1158 | public static void main(String ... args) { 1159 | Vehicle vehicle1 = new Car(); 1160 | Vehicle vehicle2 = new Motocycle(); 1161 | vehicle1.show(); // El compilador invoca el método 'show()' de 'Car' 1162 | vehicle2.show(); // El compilador invoca el método 'show()' de 'Motocycle' 1163 | 1164 | } 1165 | } 1166 | ``` 1167 | 1168 | ### Clases abstractas 1169 | 1170 | Una clase que defina uno o varios métodos abstractos debe definirse como `abstract`. Un método abstracto carece de cuerpo y debe ser implementado en una subclase. Si la subclase no lo implementa, también deberá marcarse como `abstract`. No se pueden crear objetos de una clase marcada como abstracta. 1171 | 1172 | El modificador `abstract` sólo se puede usar en métodos normales, no se puede aplicar ni en métodos estáticos ni en constructores. 1173 | 1174 | Una clase definida como `abstract` puede tener variables y métodos normales con implementación como cualquier otra clase. 1175 | 1176 | ```java 1177 | abstract class Vehicle { 1178 | void show(); 1179 | } 1180 | 1181 | class Car extends Vehicle { 1182 | @Override 1183 | void show() {} 1184 | } 1185 | ``` 1186 | 1187 | ### Modificador `final` 1188 | 1189 | Para evitar que un método se reemplace, se especifica `final` como modificador al inicio de su declaración. También se puede evitar que una clase se herede si se precede su declaración como `final`. De esta forma, todos sus métodos son final de forma implícita. 1190 | 1191 | Los modificadores `abstract` y `final` son incompatibles ya que una clase `abstract` debe ser heredada para proporcionar una implementación completa y el modificador `final` no permite la herencia. 1192 | 1193 | Una variable miembro con el modificador `final` es como una constante ya que el valor inicial asignado no se puede cambiar mientras dure el programa. 1194 | 1195 | ```java 1196 | final class Vehicle {} 1197 | 1198 | class SuperCar { 1199 | final int MIN_POWER = 545; // Este valor no cambia mientras dure el programa 1200 | 1201 | void show() {} 1202 | final void price() {} 1203 | } 1204 | 1205 | // class Moto extends Vehicle {} // Una clase final no puede ser heredada 1206 | 1207 | class Car extends SuperCar { 1208 | @Override 1209 | void show() {} // Correcto 1210 | 1211 | void price() {} // Incorrecto. No se puede sobreescribir un método 'final' 1212 | } 1213 | ``` 1214 | 1215 | ## Visibilidad 1216 | 1217 | ### Visibilidad de clases 1218 | 1219 | Visibilidad permitidas para las clases: 1220 | 1221 | - `default` (sin modificador) -> Sólo será visible por otras clases **dentro del mismo paquete**. 1222 | - `public` -> Una clase pública es **visible desde cualquier lugar**. 1223 | 1224 | > :warning: Una clase declarada como `public` debe encontrarse en **un archivo con el mismo nombre**. 1225 | 1226 | ```java 1227 | class Vehicle {} // clase 'default' (sin modificador) 1228 | public class Car {} // clase 'public' y en un fichero con el nombre 'Car.java' 1229 | ``` 1230 | 1231 | ### Visibilidad de una interfaz 1232 | 1233 | Visibilidad permitida para las interfaces: 1234 | 1235 | - `default` (sin modificador) -> Una interfaz sin modificador sólo será visible por otras clases o interfaces **dentro del mismo paquete**. 1236 | - `public` -> Una interfaz pública es visible **desde cualquier lugar**. 1237 | 1238 | > :warning: Una interfaz declarada como `public` debe encontrarse en **un archivo con el mismo nombre**. 1239 | 1240 | ```java 1241 | interface Vehicle {} // interfaz 'default' (sin modificador) 1242 | public interface Car {} // interfaz 'public' y en un fichero con el nombre 'Car.java' 1243 | ``` 1244 | 1245 | ### Visibilidad de variables y miembros de instancia 1246 | 1247 | | | Private | Default | Protected | Public | 1248 | | :----------------------------------------------------- | :-----: | :-----: | :-------: | :-----: | 1249 | | Visible desde la misma clase | Sí | Sí | Sí | Sí | 1250 | | Visible desde el mismo paquete por una subclase | No | Sí | Sí | Sí | 1251 | | Visible desde el mismo paquete por una no subclase | No | Sí | Sí | Sí | 1252 | | Visible desde un paquete diferente por una subclase | No | No | Sí | Sí | 1253 | | Visible desde un paquete diferente por una no subclase | No | No | No | Sí | 1254 | 1255 | ## Interfaces 1256 | 1257 | Las interfaces son sintácticamente similares a las clases abstractas con la diferencia que **en una interfaz todos los métodos carecen de cuerpo**. Una clase puede implementar todas las interfaces que desee pero tiene que implementar todos los métodos descritos en la interfaz. Por tanto, el código que conozca la interfaz puede usar objetos de cualquier clase que implemente dicha interfaz. Si una clase no implementa todos los métodos de una interfaz deberá declarase como `abstract`. 1258 | 1259 | Antes de JDK 8 una interfaz no podía definir ninguna implementación pero a partir de JDK 8 se puede añadir una implementación predeterminada a un método de interfaz. La clase o clases que implementen la interfaz podrán **definir su propia implementación o usar la predeterminada**. Un método predeterminado se precede con la palabra clave `default`. Ahora también admite métodos estáticos y, a partir de JDK 9, una interfaz puede incluir métodos `private`. 1260 | 1261 | Una interfaz puede ser `public` (y en un fichero del mismo nombre) o `default` (sin modificador). Los métodos son implícitamente `public` y las variables declaradas en un interfaz no son variables de instancia, sino que son `public`, `final` y `static` y deben inicializarse. Por tanto son constantes. 1262 | 1263 | Cuando una clase implementa varias interfaces, éstas se separan mediante comas. En caso de que una clase implemente una interfaz y que herede de una clase primero se coloca `extends` y luego `implements`. 1264 | 1265 | > :exclamation: Como hemos dicho en una interfaz los métodos son implícitamente `public`. Cuando una clase implementa dicha interfaz y codifica los métodos de la interfaz, si no indica visibilidad los miembros de la clase son `default` de forma implícita, lo cual genera un error ya que `default` es más restrictivo que `public`. Por tanto, **tenemos que indicar explícitamente como `public` los métodos implementados en la clase**. 1266 | 1267 | ```java 1268 | (public) interface Vehicle { 1269 | public static final String UNITS = "Km/h"; 1270 | 1271 | // Método implícitamente 'public' que será codificado por la clase/s que implementan la interfaz 1272 | void getWheels(); 1273 | 1274 | // Método con una implementación por defecto. 1275 | (public) default boolean start() { 1276 | return true; 1277 | } 1278 | } 1279 | 1280 | // Si una clase implementa varias interfaces, estas se separan mediante comas. 1281 | class Car extends Superclass implements Vehicle { 1282 | public void getWheels() {} // Es necesario indicar 'public' o se genera un error. 1283 | } 1284 | 1285 | class Sample { 1286 | public static void main (String ... args) { 1287 | //Se declara una variable de referencia de un tipo de interfaz. 1288 | Vehicle car = new Car(); 1289 | 1290 | // Se ejecutará la versión implementada por el objeto. 1291 | // Sólo se tiene acceso a los métodos definidos en la interfaz y 1292 | // no a otros métodos que puedan estar definidos en la clase. 1293 | car.getWheels(); 1294 | } 1295 | } 1296 | ``` 1297 | 1298 | Una interfaz puede heredar a otra interfaz por medio de la palabra reservada `extends`. Cuando una clase implementa una interfaz que hereda de otra interfaz debe proporcionar implementaciones de todos los métodos definidos en la cadena de herencia. 1299 | 1300 | ```java 1301 | interface Vehicle { 1302 | int getWheels(); 1303 | } 1304 | 1305 | interface Car extends Vehicle { 1306 | int getPassengers(); 1307 | } 1308 | 1309 | class MyCar implements Car { 1310 | public int getWheels() { return 4; } // se implementan los métodos de ambas interfaces 1311 | public int getPassengers() { return 5; } 1312 | } 1313 | ``` 1314 | 1315 | La inclusión de los métodos predeterminados no varia un aspecto clave de los interfaces, y es que no admiten variables de instancia. Por tanto sigue habiendo una diferencia entre interfaces y una clase normal o abstracta. **Una clase puede mantener información de estado mediante sus variables de instancia mientras que una interfaz no puede**. Por tanto una interfaz sigue siendo útil para definir lo que debe hacer una clase y no como lo debe hacer. 1316 | 1317 | Si una clase hereda de dos interfaces que implementan un método predeterminado con el mismo nombre, la clase está **obligada** a implementar dicho método ya que si no lo hace el compilador genera un error. La versión implementada en la clase tiene preferencia sobre las versiones implementadas en las interfaces. 1318 | 1319 | JDK 8 añade a las interfaces la capacidad de tener uno o varios métodos estáticos. Como sucede con una clase, un método estático definido por una interfaz se puede invocar de forma independiente a cualquier objeto. 1320 | 1321 | ```java 1322 | interface Vehicle { 1323 | static void start() { System.out.println("Starting..."); } 1324 | } 1325 | 1326 | public class Sample { 1327 | public static void main (String ... args) { 1328 | Vehicle.start(); 1329 | } 1330 | } 1331 | ``` 1332 | 1333 | A partir de JDK 9 una interfaz puede incluir un método `private` que solo puede invocarse mediante un método predeterminado u otro método `private` definido por la misma interfaz. Dado que es `private` este código no puede usarse fuera de la interfaz en la que esté definido. 1334 | 1335 | ## Excepciones 1336 | 1337 | Una excepción es **un error producido en tiempo de ejecución**. En Java, todas las excepciones se representan por medio de clases. Todas las clases de excepción se derivan de [`Throwable`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Throwable.html). Esta clase tiene dos subclases directas: [`Exception`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Exception.html) y [`Error`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Error.html). 1338 | 1339 | Las excepciones tipo `Error` son errores producidos en la propia máquina virtual y no se deben controlar. Los programas sólo deben controlar aquellas excepciones de tipo `Exception`. 1340 | 1341 | Mediante la palabra reservada `throw` se pueden lanzar manualmente una excepción. 1342 | 1343 | Las excepciones se tratan en un bloque `try-catch-finally` (`finally` es opcional): 1344 | 1345 | ```java 1346 | try { 1347 | // bloque de código que puede lanzar la excepción 1348 | } catch (TipoException exception) { 1349 | // bloque de código para TipoException 1350 | } catch (Tipo2Exception exception) { 1351 | // bloque de código para Tipo2Exception 1352 | } catch (Exception exception) { 1353 | // Captura del resto de excepciones no capturadas anteriormente 1354 | } finally { 1355 | // Código que se ejecutará siempre, tanto si 1356 | // se produce una excepción como si no se produce. 1357 | } 1358 | ``` 1359 | 1360 | Si un método genera una excepción que no se va a controlar, debemos declarar dicha excepción en una cláusula `throws`. Con esta cláusula podemos 'relanzar' tanto excepciones de Java como excepciones personalizadas. Una vez lanzada esta excepción deberá ser capturada en un bloque `try-catch` superior o por la JVM: 1361 | 1362 | ```java 1363 | int divide(int a, int b) throws ArithmeticException, MyException { 1364 | if (b == 0) { 1365 | throw new ArithmeticException(); 1366 | } else { 1367 | throw new MyException("Message"); 1368 | } 1369 | } 1370 | 1371 | class MyException extends Exception { } 1372 | ``` 1373 | 1374 | En **JDK 7** se amplió el mecanismo de excepciones al permitir la **captura múltiple**. Con la captura múltiple se permite la captura de dos o más excepciones dentro de la misma cláusula `catch`. Cada tipo de excepción de la lista se separa con el operador `| ('OR')`. Cada parámetro es `final` de forma implícita. 1375 | 1376 | ```java 1377 | try { 1378 | // código 1379 | } catch (final ArithmeticException | ArrayIndexOutOfBoundsException e) { 1380 | // Controlador 1381 | } 1382 | ``` 1383 | 1384 | En **JDK 7** se añadió otro mecanismo denominado `try-with-resources` o **_try con administración automática de recursos_**. Es un tipo de `try` que evita situaciones en que un archivo (u otro recurso como bases de datos, etc..) no se libera después de ser utilizado. Un `try-with-resources` de este tipo también puede incluir cláusulas `catch` o `finally`. 1385 | 1386 | Los recursos que se pueden emplear con este tipo de `try-with-resources` son recursos que implementen la interfaz [`AutoCloseable`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/AutoCloseable.html) que a su vez hereda de `Closeable`. La interfaz `AutoCloseable` define el método `close()`. Además, el recurso declarado en la instrucción `try` es **'final'** de forma implícita, de forma que no puede ser asignado ni modificado una vez creado y su ámbito se limita al propio `try`. 1387 | 1388 | ```java 1389 | /* 1390 | - El siguiente código usa un 'try con recursos' para abrir un archivo 1391 | - y después cerrarlo automáticamente al salir del bloque 'try'. 1392 | - Por tanto ya no es necesario invocar a 'close()' 1393 | */ 1394 | try (FileInputStream fin = New FileInputStream(args[0])) { 1395 | // bloque de código 1396 | } catch (IOException e) { 1397 | // Controlador 1398 | } 1399 | ``` 1400 | 1401 | Se pueden gestionar más de un recurso que estarán separados por un punto y coma ';': 1402 | 1403 | ```java 1404 | try (FileInputStream fin = New FileInputStream(args[0]); FileOutputStream fout = New FileOutputStream(args[1])) { 1405 | // bloque de código 1406 | } catch (IOException e) { 1407 | // Controlador 1408 | } 1409 | ``` 1410 | 1411 | ## Entrada/Salida (E/S) 1412 | 1413 | En Java el sistema E/S se define en dos sistemas completos: uno para **E/S de bytes** y otro para **E/S de caracteres**. En el nivel inferior toda la E/S sigue orientada a bytes. La E/S de caracteres es una especialización y una forma más cómoda de trabajar con caracteres. 1414 | 1415 | Los programas en Java realizan la E/S a través de **flujos** (_'streams'_). 1416 | 1417 | Todos los programas de Java importan automáticamente el paquete `java.lang` que define la clase `System`. Esta clase contiene, entre otros elementos, tres variables de flujo predefinidos: 1418 | 1419 | - `System.in` - hace referencia al flujo estándar de entrada, que es el teclado. 1420 | - `System.out` - hace referencia al flujo estándar de salida, que es la consola. 1421 | - `System.err` - hace referencia al flujo de error estándar que también es la consola de forma predeterminada. 1422 | 1423 | ### Flujos de bytes 1424 | 1425 | Los flujos de bytes se definen en dos jerarquías de clases. En la parte superior hay dos clases abstractas que definen las características comunes: `InputStream` y `OutputStream`. 1426 | 1427 | A partir de estas clases se crean subclases concretas con distinta funcionalidad: 1428 | 1429 | - InputStream: 1430 | - `BufferedInputStream` - Flujo de entrada en búfer 1431 | - `ByteArrayInputStream` - Flujo de entrada desde una matriz de bytes 1432 | - `DataInputStream` - Flujo de entrada que contiene métodos para leer los tipos de datos estándar de Java 1433 | - `FileInputStream` - Flujo de entrada que lee desde un archivo 1434 | - `FilterInputStream` - Implementa 'InputStream' 1435 | - `ObjectInputStream` - Flujo de entrada de objetos 1436 | - `PipedInputStream` - Conducción de entrada 1437 | - `PushbackInputStream` - Flujo de entrada que permite devolver bytes al flujo 1438 | - `SequenceInputStream` - Flujo de entrada que combina dos o más flujos de entrada que se leen secuencialmente, uno tras otro 1439 | 1440 | - OutputStream: 1441 | - `BufferedOutputStream` - Flujo de salida en búfer 1442 | - `ByteArrayOutputStream` - Flujo de salida que escribe en una matriz de bytes 1443 | - `DataOutputStream` - Flujo de salida que contiene métodos para escribir los tipos de datos estándar de Java 1444 | - `FileOutputStream` - Flujo de salida que escribe en un archivo 1445 | - `FilterOutputStream` - Implementa 'OutputStream' 1446 | - `ObjectOutputStream` - Flujo de salida para objetos 1447 | - `PipedOutputStream` - Conducción de salida 1448 | - `PrintStream` - Flujo de salida que contiene `print()` y `println()` 1449 | 1450 | #### Leer entradas de consola 1451 | 1452 | Aunque usar el flujo de caracteres para leer de consola es preferible debido a la internacionalización y al mantenimiento de programas, la lectura de flujo de bytes sigue siendo usado: 1453 | 1454 | ```java 1455 | // Leer una matriz de bytes desde el teclado 1456 | import java.io.*; 1457 | 1458 | class ReadBytes { 1459 | public static void main(String args[]) throws IOException { 1460 | byte[] data = new byte[10]; 1461 | System.out.println("Enter some characters:"); 1462 | System.in.read(data); // leer una matriz de bytes desde el teclado 1463 | System.out.print("You entered: "); 1464 | for(int i = 0; i < data.length; i++) { 1465 | System.out.print((char)data[i]); 1466 | } 1467 | } 1468 | } 1469 | ``` 1470 | 1471 | #### Escribir la salida en la consola con `PrintStream` 1472 | 1473 | Para escribir en consola se utiliza `print()` o `println()` que se definen en `PrintStream` aunque también tiene métodos como `write()` 1474 | 1475 | ```java 1476 | class WriteDemo { 1477 | public static void main(String args[]) { 1478 | int b = 'X'; 1479 | System.out.write(b); // Escribir un byte en la pantalla 1480 | System.out.write('\n'); 1481 | } 1482 | } 1483 | ``` 1484 | 1485 | #### Leer archivos con `FileInputStream` 1486 | 1487 | ```java 1488 | /* Display a text file. 1489 | To use this program, specify the name 1490 | of the file that you want to see. 1491 | For example, to see a file called TEST.TXT, 1492 | use the following command line. 1493 | java ShowFile TEST.TXT 1494 | */ 1495 | import java.io.*; 1496 | 1497 | class ShowFile { 1498 | public static void main(String args[]) { 1499 | int i; 1500 | FileInputStream fin = null; 1501 | try { 1502 | fin = new FileInputStream(args[0]); 1503 | do { 1504 | i = fin.read(); 1505 | if (i != -1) 1506 | System.out.print((char) i); 1507 | } while (i != -1); 1508 | } catch (IOException e) { 1509 | System.out.println("I/O Error: " + e); 1510 | } finally { 1511 | // Close file in all cases. 1512 | try { 1513 | if (fin != null) 1514 | fin.close(); 1515 | } catch (IOException e) { 1516 | System.out.println("Error Closing File"); 1517 | } 1518 | } 1519 | } 1520 | } 1521 | ``` 1522 | 1523 | #### Escribir archivos con `FileOutputStream` 1524 | 1525 | ```java 1526 | 1527 | /* Copy a file. 1528 | To use this program, specify the name 1529 | of the source file and the destination file. 1530 | For example, to copy a file called FIRST.TXT 1531 | to a file called SECOND.TXT, use the following 1532 | command line. 1533 | java CopyFile FIRST.TXT SECOND.TXT 1534 | */ 1535 | import java.io.*; 1536 | 1537 | class CopyFile { 1538 | public static void main(String args[]) throws IOException { 1539 | int i; 1540 | FileInputStream fin = null; 1541 | FileOutputStream fout = null; 1542 | // First, confirm that both files have been specified. 1543 | if (args.length != 2) { 1544 | System.out.println("Usage: CopyFile from to"); 1545 | return; 1546 | } 1547 | // Copy a File. 1548 | try { 1549 | // Attempt to open the files. 1550 | fin = new FileInputStream(args[0]); 1551 | fout = new FileOutputStream(args[1]); 1552 | do { 1553 | i = fin.read(); 1554 | if (i != -1) 1555 | fout.write(i); 1556 | } while (i != -1); 1557 | } catch (IOException e) { 1558 | System.out.println("I/O Error: " + e); 1559 | } finally { 1560 | try { 1561 | if (fin != null) 1562 | fin.close(); 1563 | } catch (IOException e2) { 1564 | System.out.println("Error Closing Input File"); 1565 | } 1566 | try { 1567 | if (fout != null) 1568 | fout.close(); 1569 | } catch (IOException e2) { 1570 | System.out.println("Error Closing Output File"); 1571 | } 1572 | } 1573 | } 1574 | } 1575 | ``` 1576 | 1577 | ### Flujos de caracteres 1578 | 1579 | Los flujos de caracteres se definen en dos jerarquías de clases. En la parte superior hay dos clases abstractas que definen las características comunes: `Reader` y `Writer`. Las clases concretas derivadas de estas clases operan en flujos de caracteres _Unicode_. 1580 | 1581 | A partir de estas clases se crean subclases concretas con distinta funcionalidad: 1582 | 1583 | - Reader: 1584 | - `BufferedReader` - Flujo de caracteres entrada en búfer 1585 | - `CharArrayReader` - Flujo de entrada que lee desde una matriz de caracteres 1586 | - `FileReader` - Flujo de entrada que lee desde un archivo 1587 | - `FilterReader` - Lector filtrado 1588 | - `InputStreamReader` - Flujo de entrada que traduce bytes en caracteres 1589 | - `LineNumberReader` - Flujo de entrada que cuenta líneas 1590 | - `PipedReader` - Conducción de entrada 1591 | - `PushbackReader` - Flujo de caracteres que permite devolver caracteres al flujo de entrada 1592 | - `StringReader` - Flujo de entrada que lee desde una cadena 1593 | 1594 | - Writer: 1595 | - `BufferedWriter` - Flujo de caracteres de salida en búfer 1596 | - `CharArrayWriter` - Flujo de salida que escribe en una matriz de caracteres 1597 | - `FileWriter` - Flujo de salida que escribe en un archivo 1598 | - `FilterWriter` - Escritor filtrado 1599 | - `OutputStreamWriter` - Flujo de salida que traduce caracteres en bytes 1600 | - `PipedWriter` - Conducción de salida 1601 | - `PrintWriter` - Flujo de salida que contiene `print()` y `println()` 1602 | - `StringWriter` - Flujo de salida que escribe en una cadena 1603 | 1604 | #### Leer caracteres desde la consola con `BufferedReader` 1605 | 1606 | Como `System.in` es un flujo de bytes, se convierte en flujo de caracteres mediante un `InputStreamReader`. Este `InputStreamReader` se pasa a `BufferedReader`, que es una clase óptima que admite un flujo de entrada en búfer. 1607 | 1608 | ```java 1609 | // Use a 'BufferedReader' to read characters from the console. 1610 | import java.io.*; 1611 | 1612 | class BRRead { 1613 | public static void main(String args[]) throws IOException { 1614 | char c; 1615 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 1616 | System.out.println("Enter characters, 'q' to quit."); 1617 | // read characters 1618 | do { 1619 | c = (char) br.read(); 1620 | System.out.println(c); 1621 | } while (c != 'q'); 1622 | } 1623 | } 1624 | ``` 1625 | 1626 | #### Leer cadenas desde la consola con `BufferedReader` 1627 | 1628 | ```java 1629 | // Read a string from console using a 'BufferedReader'. 1630 | import java.io.*; 1631 | 1632 | class BRReadLines { 1633 | public static void main(String args[]) throws IOException { 1634 | // create a 'BufferedReader' using 'System.in' 1635 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 1636 | String str; 1637 | System.out.println("Enter lines of text."); 1638 | System.out.println("Enter 'stop' to quit."); 1639 | do { 1640 | str = br.readLine(); 1641 | System.out.println(str); 1642 | } while (!str.equals("stop")); 1643 | } 1644 | } 1645 | ``` 1646 | 1647 | #### Salida en consola con `PrintWriter` 1648 | 1649 | Aunque para programas pequeños y tareas de depuración se puede utilizar `System.out`, en programas reales es recomendable usar un flujo `PrintWriter`: 1650 | 1651 | ```java 1652 | // Demonstrate 'PrintWriter' 1653 | import java.io.*; 1654 | 1655 | public class PrintWriterDemo { 1656 | public static void main(String args[]) { 1657 | PrintWriter pw = new PrintWriter(System.out, true); 1658 | pw.println("This is a string"); 1659 | int i = -7; 1660 | pw.println(i); 1661 | double d = 4.5e-7; 1662 | pw.println(d); 1663 | } 1664 | } 1665 | ``` 1666 | 1667 | #### Escribir en un fichero con `FileWriter` 1668 | 1669 | ```java 1670 | // Demonstrate 'FileWriter'. 1671 | // This program uses 'try-with-resources'. It requires JDK 7 or later. 1672 | import java.io.*; 1673 | 1674 | class FileWriterDemo { 1675 | public static void main(String args[]) throws IOException { 1676 | String source = "Now is the time for all good men\n" + " to come to the aid of their country\n" 1677 | + " and pay their due taxes."; 1678 | char buffer[] = new char[source.length()]; 1679 | source.getChars(0, source.length(), buffer, 0); 1680 | try (FileWriter f0 = new FileWriter("file1.txt"); 1681 | FileWriter f1 = new FileWriter("file2.txt"); 1682 | FileWriter f2 = new FileWriter("file3.txt")) { 1683 | // write to first file 1684 | for (int i = 0; i < buffer.length; i += 2) { 1685 | f0.write(buffer[i]); 1686 | } 1687 | // write to second file 1688 | f1.write(buffer); 1689 | // write to third file 1690 | f2.write(buffer, buffer.length - buffer.length / 4, buffer.length / 4); 1691 | } catch (IOException e) { 1692 | System.out.println("An I/O Error Occurred"); 1693 | } 1694 | } 1695 | } 1696 | ``` 1697 | 1698 | #### Leer de un fichero con `FileReader` 1699 | 1700 | ```java 1701 | // Demonstrate 'FileReader'. 1702 | // This program uses 'try-with-resources'. It requires JDK 7 or later. 1703 | import java.io.*; 1704 | 1705 | class FileReaderDemo { 1706 | public static void main(String args[]) { 1707 | try (FileReader fr = new FileReader("FileReaderDemo.java")) { 1708 | int c; 1709 | // Read and display the file. 1710 | while ((c = fr.read()) != -1) 1711 | System.out.print((char) c); 1712 | } catch (IOException e) { 1713 | System.out.println("I/O Error: " + e); 1714 | } 1715 | } 1716 | } 1717 | ``` 1718 | 1719 | ## Manipular ficheros y directorios 1720 | 1721 | Con el paquete `java.io` se trabaja con _streams_, leyendo y escribiendo ficheros a bajo nivel. 1722 | 1723 | Existe otra forma de manipular ficheros a más alto nivel gracias a las utilidades del paquete `java.nio`. 1724 | 1725 | El primer paso es obtener una referencia al fichero o directorio mediante la clase `Path`: 1726 | 1727 | ```java 1728 | // Obtener una referencia mediante la clase de ayuda 'java.nio.file.Paths' 1729 | Path path = Paths.get("/home/test.txt"); // Sistemas UNIX 1730 | 1731 | Path path2 = Paths.get("c:\\home\\test.txt"); // Sistemas Windows 1732 | ``` 1733 | 1734 | Para operar con ficheros o directorios es necesario utilizar la clase `Files`: 1735 | 1736 | ```java 1737 | // Verificar si existe el fichero 1738 | Path path = Paths.get("/home/test.txt"); 1739 | 1740 | Files.exists(path); // Devuelve 'true' si existe 1741 | 1742 | // Verificar su accesibilidad 1743 | Files.isReadable(path); 1744 | Files.isWritable(path); 1745 | Files.isExecutable(path); 1746 | 1747 | // Copiar ficheros (o directorios) 1748 | Files.copy(path, Paths.get("copy.txt")); 1749 | 1750 | // Borrar fichero (o directorio, que deberán estar VACÍOS) 1751 | Files.delete(Paths.get("copy.txt")); 1752 | ``` 1753 | 1754 | ## Trabajar con fechas 1755 | 1756 | Hasta Java 8, para trabajar con fechas se utilizaban las clases `Date` y `GregorianCalendar`. 1757 | 1758 | Las nuevas herramientas para trabajar con fechas a partir de Java 8 se encuentran en el paquete [`java.time`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/time/package-summary.html): 1759 | 1760 | ```java 1761 | import java.time.LocalDate; 1762 | import java.time.format.DateTimeFormatter; 1763 | 1764 | LocalDate fechaActual = LocalDate.now(); 1765 | System.out.println(fechaActual); // Imprime '2024-01-19' 1766 | 1767 | DateTimeFormatter dtF1 = DateTimeFormatter.ofPattern("dd-MM-yyyy"); 1768 | System.out.println(dtF1.format(fechaActual)); // Imprime '19-01-2024' 1769 | ``` 1770 | 1771 | ## Programación de subprocesamiento múltiple 1772 | 1773 | Existen dos tipos de multitarea: la basada en **procesos** y la basada en **subprocesos**. 1774 | 1775 | Un proceso es básicamente un programa que se ejecuta. Por tanto la multitarea basada en procesos permite al equipo ejecutar dos o más programas a la vez. En un entorno multitarea basado en subprocesos, el subproceso es la unidad de código menor que se entrega, lo que significa que un mismo programa puede realizar dos o más tareas al mismo tiempo. 1776 | 1777 | Java no controla la multitarea basada en procesos pero **sí controla la basada en subprocesos**. 1778 | 1779 | Una ventaja del subprocesamiento múltiple es que permite programas más eficaces ya que se utiliza el tiempo de inactividad en la mayoría de programas. En sistemas de un sólo núcleo, los subprocesos de ejecución simultánea comparten la CPU y cada subproceso recibe una porción de tiempo de CPU. En sistemas multinúcleo, dos o más subprocesos se pueden ejecutar simultáneamente. 1780 | 1781 | Un subproceso puede estar en varios estados, como por ejemplo en ejecución o puede estar bloqueado a la espera de un recurso, etc... 1782 | 1783 | Junto a la multitarea basada en subprocesos surge la necesidad de una función especial denominada **sincronización**, que permite coordinar la ejecución de subprocesos de determinadas formas. 1784 | 1785 | El sistema de subprocesamiento múltiple de Java se base en la clase `Thread` y en su interfaz `Runnable`, ambas de `java.lang`. Para crear un nuevo subproceso, su programa debe ampliar `Thread` o implemetar la interfaz `Runnable`. 1786 | 1787 | ```java 1788 | // Create a second thread. 1789 | class NewThread implements Runnable { 1790 | Thread thread; 1791 | 1792 | NewThread() { 1793 | // Create a new, second thread 1794 | thread = new Thread(this, "Demo Thread"); 1795 | System.out.println("Child thread: " + thread); 1796 | thread.start(); // Start the thread 1797 | } 1798 | 1799 | // This is the entry point for the second thread. 1800 | public void run() { 1801 | try { 1802 | for (int i = 5; i > 0; i--) { 1803 | System.out.println("Child Thread: " + i); 1804 | Thread.sleep(500); 1805 | } 1806 | } catch (InterruptedException e) { 1807 | System.out.println("Child interrupted."); 1808 | } 1809 | System.out.println("Exiting child thread."); 1810 | } 1811 | } 1812 | 1813 | class ThreadDemo { 1814 | public static void main(String args[]) { 1815 | new NewThread(); // create a new thread 1816 | try { 1817 | for (int i = 5; i > 0; i--) { 1818 | System.out.println("Main Thread: " + i); 1819 | Thread.sleep(1000); 1820 | } 1821 | } catch (InterruptedException e) { 1822 | System.out.println("Main thread interrupted."); 1823 | } 1824 | System.out.println("Main thread exiting."); 1825 | } 1826 | } 1827 | ``` 1828 | 1829 | ```java 1830 | // Controlling the main Thread. 1831 | class CurrentThreadDemo { 1832 | public static void main(String args[]) { 1833 | Thread t = Thread.currentThread(); 1834 | System.out.println("Current thread: " + t); 1835 | // change the name of the thread 1836 | t.setName("My Thread"); 1837 | System.out.println("After name change: " + t); 1838 | try { 1839 | for (int n = 5; n > 0; n--) { 1840 | System.out.println(n); 1841 | Thread.sleep(1000); 1842 | } 1843 | } catch (InterruptedException e) { 1844 | System.out.println("Main thread interrupted"); 1845 | } 1846 | } 1847 | } 1848 | ``` 1849 | 1850 | `Thread` ofrece dos formas para saber si un subproceso ha finalizado. Por un lado se puede invocar `isAlive()` en el subproceso, que devolverá 'true' si el subproceso en el que se invoca sigue en ejecución. 1851 | 1852 | ```java 1853 | do { 1854 | // code 1855 | } while (thread.isAlive()) 1856 | ``` 1857 | 1858 | Otra forma de esperar a que un subproceso termine consiste en invocar `join()`. Este método espera a que termine el subproceso en el que se invoca. Su nombre proviene del concepto del subproceso invocador esperando a que se le una el subproceso especificado. 1859 | 1860 | ### Métodos sincronizados 1861 | 1862 | Al usar varios subprocesos en ocasiones será necesario sincronizar las actividades de los subprocesos para que no accedan a la vez a un mismo recurso. Esto se consigue con la palabra clave `synchronized`. 1863 | 1864 | Al invocar un método sincronizado, el subproceso invocador accede al monitor del objeto, que lo bloquea. Mientras está bloqueado, ningún otro subproceso puede acceder al método ni a otro método sincronizado definido por la clase del objeto. 1865 | 1866 | ```java 1867 | class SumArray { 1868 | private int sum; 1869 | 1870 | /* Este método está sincronizado. 1871 | Cuando sea invocado por un subproceso quedará bloqueado al resto de subprocesos, 1872 | que deberán esperar a que sea desbloqueado. 1873 | No podrán acceder ni a éste ni a ningún otro método sincronizado de esta clase */ 1874 | synchronized int sumArray(int nums[]) { 1875 | // code.... 1876 | } 1877 | } 1878 | ``` 1879 | 1880 | ### Bloque sincronizado 1881 | 1882 | No sólo se puede sincronizar métodos si no que Java proporciona un **bloque sincronizado**. Tras entrar en un bloque `synchronized`, ningún otro subproceso puede invocar un método sincronizado en el objeto al que hace referencia la variable pasada como parámetro hasta que se salga del bloque. 1883 | 1884 | ```java 1885 | synchronized(refObj) { // 'refObj' es una referencia al objeto sincronizado 1886 | // instrucciones que sincronizar 1887 | } 1888 | ``` 1889 | 1890 | ```java 1891 | // This program uses a synchronized block. 1892 | class Callme { 1893 | void call(String msg) { 1894 | 1895 | System.out.print("[" + msg); 1896 | try { 1897 | Thread.sleep(1000); 1898 | } catch (InterruptedException e) { 1899 | System.out.println("Interrupted"); 1900 | } 1901 | System.out.println("]"); 1902 | } 1903 | } 1904 | 1905 | class Caller implements Runnable { 1906 | String msg; 1907 | Callme target; 1908 | Thread t; 1909 | 1910 | public Caller(Callme targ, String s) { 1911 | target = targ; 1912 | msg = s; 1913 | t = new Thread(this); 1914 | t.start(); 1915 | } 1916 | 1917 | // synchronize calls to call() 1918 | public void run() { 1919 | synchronized (target) { // synchronized block 1920 | target.call(msg); 1921 | } 1922 | } 1923 | } 1924 | 1925 | class Sample { 1926 | public static void main(String args[]) { 1927 | Callme target = new Callme(); 1928 | Caller ob1 = new Caller(target, "Hello"); 1929 | Caller ob2 = new Caller(target, "Synchronized"); 1930 | Caller ob3 = new Caller(target, "World"); 1931 | // wait for threads to end 1932 | try { 1933 | ob1.t.join(); 1934 | ob2.t.join(); 1935 | ob3.t.join(); 1936 | } catch (InterruptedException e) { 1937 | System.out.println("Interrupted"); 1938 | } 1939 | } 1940 | } 1941 | ``` 1942 | 1943 | ## Enumeraciones 1944 | 1945 | Básicamente, una enumeración es una **lista de constantes con nombre** que define un nuevo tipo de datos. Un objeto de un tipo de enumeración solo puede albergar los valores definidos por esta lista. De este modo, las enumeraciones permiten definir con precisión un nuevo tipo de datos con un número fijo de valores. 1946 | 1947 | Desde una perspectiva de programación, las enumeraciones son muy útiles cuando se necesita definir un grupo de valores que representan una colección de elementos. Es importante entender que una **constante de enumeración es un objeto de su tipo de enumeración**. Una enumeración se crea con la palabra clave `enum`. 1948 | 1949 | Las constantes de la enumeración son `public` y `static` de forma implícita. 1950 | 1951 | ```java 1952 | enum Transport { 1953 | CAR, TRUCK, AIRPLANE, TRAIN, BOAT // constantes de enumeración 1954 | } 1955 | ``` 1956 | 1957 | Estas constantes tienen el tipo de la enumeración que las contiene. Una vez definida la enumeración, para crear una variable de este tipo no es necesario usar `new` como con una clase. Las enumeraciones se declaran y usan como si fueran tipos primitivos. 1958 | 1959 | Java implementa **las enumeraciones como si fueran clases**, permitiendo que tengan constructores, métodos y variables de instancia. Incluso pueden **implementar interfaces**. Sin embargo, presentan dos limitaciones clave que las diferencian de las clases tradicionales de Java: 1960 | 1961 | - Una enumeración no puede heredar de otra clase. 1962 | 1963 | - Una enumeración no puede actuar como superclase de otra clase. 1964 | 1965 | ```java 1966 | // Las constantes, al ser 'static' se invocan de esta forma: 'Enumeration.constante' 1967 | Transport transport = Transport.TRUCK; 1968 | 1969 | if (transport == Transport.TRUCK) { // Comparar la igualdad de dos constantes de enumeración 1970 | System.out.println(transport) // => TRUCK 1971 | } 1972 | 1973 | //Podemos usar una enumeración para controlar una instrucción 'switch' 1974 | switch (transport) { 1975 | // No es necesario usar 'Transport.CAR' ya que implícitamente ya se especifica 1976 | case CAR: 1977 | // code .... 1978 | break; 1979 | case TRUCK: 1980 | // code .... 1981 | break; 1982 | default: 1983 | // code... 1984 | break; 1985 | } 1986 | ``` 1987 | 1988 | Las enumeraciones heredan de la clase [`java.lang.Enum`](https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html). Cuentan con dos métodos predefinidos importantes: 1989 | 1990 | - `public static tipo-enum[] values()` ➜ devuelve un array que contiene una lista de las constantes de enumeración 1991 | 1992 | - `public static tipo-enum valueOf(String cadena)` ➜ devuelve las constantes de enumeración cuyo valor se corresponde a la cadena pasada como argumento. 1993 | 1994 | ```java 1995 | // Uso de values() en un for-each 1996 | for (Transport transport : Transport.values()) { 1997 | System.out.println(transport); 1998 | } 1999 | ``` 2000 | 2001 | Al definir un constructor en una enumeración, éste se invoca al crear cada una de las constantes de enumeración. Además, cada constante puede invocar todos los métodos definidos por la enumeración. Cada constante dispone de su propia copia de las variables de instancia definidas por la enumeración. 2002 | 2003 | ```java 2004 | // Transport.java 2005 | public enum Transport { 2006 | /* Valores de inicialización. 2007 | A destacar el ';' necesario cuando se definen variables, constructores, etc.. */ 2008 | CAR(66), TRUCK(12), AIRPLANE(600), BOAT(12); 2009 | 2010 | private int speed; // variable de instancia. Cada constante dispone de su propia copia 2011 | 2012 | Transport(int s) { // constructor. Es invocado por cada constante 2013 | speed = s; 2014 | } 2015 | 2016 | int getSpeed() { // método de instancia. Se invocaría con Transport.CAR.getSpeed(); 2017 | return speed; 2018 | } 2019 | } 2020 | ``` 2021 | 2022 | Las enumeraciones tienen un método llamado `ordinal()` que devuelve un valor que indica la posición de la constante dentro de la enumeración. Los valores ordinales empiezan en 0: 2023 | 2024 | ```java 2025 | enum Transport { 2026 | CAR, AIRPLANE, TRUCK, BOAT 2027 | } 2028 | 2029 | System.out.println(Transport.TRUCK.ordinal()); // Print 3 2030 | ``` 2031 | 2032 | La declaración de una enumeración se puede hace en una clase pero habrá que prefijar el nombre de la clase al nombre de la enumeración. Para que la enumeración sea autónoma, basta con declararla en su propio fichero. 2033 | 2034 | - ["Enum Types - The Java Tutorials"](https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html) 2035 | 2036 | ## Genéricos 2037 | 2038 | El término **"genérico"** significa tipo con parámetros. Los tipos con parámetros permiten crear clases, interfaces y métodos en los que los tipos de datos se especifican como parámetros. Cuando una clase utiliza genéricos se denomina **"clase genérica"**. 2039 | 2040 | ```java 2041 | /* Uso de genéricos en una clase. 2042 | 'T' es un parámetro de tipo que se sustituye por un tipo real al crear un objeto de la clase */ 2043 | class Gen { 2044 | T ob; // Declarar un objeto de tipo 'T'. 2045 | 2046 | Gen(T o) { // Pasar al constructor una referencia a un objeto de tipo 'T' 2047 | ob = o; 2048 | } 2049 | 2050 | T getOb() { // retorna 'ob' de tipo 'T' 2051 | return ob; 2052 | } 2053 | 2054 | void showType() { 2055 | System.out.println("Type of T is " + ob.getClass().getName()); 2056 | } 2057 | } 2058 | 2059 | class GenDemo { 2060 | public static void main(String ... args) { 2061 | Gen iOb; // Crear una referencia 2062 | 2063 | // Crear un objeto Gen y asignar la referencia a 'iOb'. 2064 | // Uso de autoboxing para encapsular el valor entero en un objeto 'Integer' 2065 | iOb = new Gen(80); 2066 | iOb.showType(); 2067 | 2068 | /* Esta asignación generaría un error en tiempo de compilación. 2069 | Es una de la ventajas del uso de genéricos */ 2070 | // iOB = new Gen(88.0) // Error 2071 | 2072 | Gen strOb = new Gen("Generic"); 2073 | strOb.showType(); 2074 | } 2075 | } 2076 | ``` 2077 | 2078 | El compilador no crea diferentes versiones de la clase genérica en función del tipo pasado sino que usa la misma versión. Lo que hace es sustituir el genérico por el tipo real y realiza las conversiones necesarias para que el código se comporte como si hubiera sido escrito con ese tipo. 2079 | 2080 | Al declarar una instancia de un tipo genérico, el argumento de tipo pasado al parámetro de tipo debe ser un tipo de referencia. No se puede usar un tipo primitivo como `int` o `char`. 2081 | 2082 | Destacar sobre los tipos genéricos es que una referencia a una versión concreta de un tipo genérico no es compatible en cuanto a tipo se refiere con otra versión del mismo tipo genérico. 2083 | 2084 | ```java 2085 | /* No se puede asignar una referencia de Gen a una referencia Gen 2086 | aunque ambas usen la misma clase genérica Get */ 2087 | iOb = strOb; // Error 2088 | ``` 2089 | 2090 | Se puede declarar más de un parámetro de tipo en un tipo genérico. Basta con usar una lista separada por comas: 2091 | 2092 | ```java 2093 | class Gen { 2094 | T ob1; 2095 | V ob2; 2096 | 2097 | Gen(T o1, V o2) { 2098 | ob1 = o1; 2099 | ob2 = o2; 2100 | } 2101 | } 2102 | 2103 | // Podemos usar tipos diferentes () o tipos iguales () 2104 | Gen sample = new Gen(0, ""); 2105 | Gen sample1 = new Gen(0, 0); 2106 | ``` 2107 | 2108 | ### Tipos vinculados (o limitados) 2109 | 2110 | Java ofrece los **'tipos vinculados'** que permite, al especificar un parámetro de tipo, crear un vínculo superior que declare la superclase de la que deben derivarse todos los argumentos de tipo. Por ejemplo, podemos limitar los parámetros de tipo a únicamente tipos numéricos, evitando que pasemos parámetros de tipo `String`. 2111 | 2112 | Para ello usamos la cláusula `extends` al especificar los parámetros de tipo: 2113 | 2114 | - `` 2115 | 2116 | Esto especifica que 'T' solo se puede reemplazar por _'superclass'_ o subclases de _'superclass'_. Por tanto _'superclass'_ define un **límite superior e inclusivo**. 2117 | 2118 | > :warning: Todos los tipos numéricos heredan de la clase abstracta `Number`. 2119 | 2120 | ```java 2121 | class GenNumeric { // De esta forma limitamos 'T' a tipos numéricos 2122 | T num; 2123 | 2124 | GenNumeric(T n) { 2125 | num = n; 2126 | } 2127 | 2128 | double fraction() { 2129 | // Como hemos limitado el tipo a tipos numéricos podemos emplear métodos de la clase 'Number' 2130 | return num.doubleValue() - num.intValue(); 2131 | } 2132 | } 2133 | ``` 2134 | 2135 | Los tipos vinculados resultan especialmente útiles para garantizar que un parámetro sea compatible con otro: 2136 | 2137 | ```java 2138 | class Pair { // 'V' debe tener el mismo tipo que 'T' o ser una subclase de 'T' 2139 | // code .... 2140 | } 2141 | 2142 | Pair x = new Pair(); // Correcto 2143 | Pair y = new Pair(); // Correcto, Integer es una subclase de Number 2144 | Pair z = new Pair(); // ¡¡INCORRECTO!!, String no es una subclase de Integer 2145 | ``` 2146 | 2147 | ### Argumentos comodín 2148 | 2149 | Un argumento comodín se representa mediante '?' y representa un tipo desconocido. Destacar que el comodín '?' no afecta al tipo de parámetros. La limitación se crea con la cláusula `extends`. El comodín simplemente equivale a cualquier tipo válido. Por ejemplo, `` limita a tipos numéricos y por tanto el comodín equivale a utilizar cualquier tipo numérico válido. La limitación a tipos numéricos se ha creado con la cláusula `extends`. 2150 | 2151 | ```java 2152 | class Gen { 2153 | T num; 2154 | // code... 2155 | } 2156 | 2157 | class Sample { 2158 | boolean absEqual(Gen a, Gen b) { 2159 | return Math.abs(a.num.doubleValue()) == Math.abs(b.num.intValue()); 2160 | } 2161 | } 2162 | ``` 2163 | 2164 | Los argumentos comodín se pueden vincular con cualquier parámetro de tipo. Un comodín vinculado es especialmente importante para crear un método que solo deba operar en objetos que sean subclases de una superclase concreta. Se especifica con la forma: 2165 | 2166 | - `` 2167 | 2168 | ```java 2169 | void sample(Gen a) { // Tipos que sean 'Number' o subclases de 'Number' 2170 | // code... 2171 | } 2172 | ``` 2173 | 2174 | Se puede especificar un límite inferior con la forma ``. En este caso es un **límite no inclusivo**. Por tanto '?' equivale a superclases de subclase pero no incluye a la propia subclase. 2175 | 2176 | ### Métodos genéricos 2177 | 2178 | Los métodos de una clase genérica pueden usar el parámetro del tipo de una clase y por tanto son genéricos de forma automática. Sin embargo también podemos declarar métodos genéricos dentro de clases no genéricas. 2179 | 2180 | Los parámetros de tipo en un método se declaran antes que el tipo devuelto del método. Los métodos genéricos puede ser estáticos o no estáticos. 2181 | 2182 | ```java 2183 | class Sample { 2184 | static void sample(T x) { /* code... */ } 2185 | boolean sample(T x, V y) { /* code... */ } 2186 | int sample(T x, V y) { /* code... */ } 2187 | static , V extends T> boolean sample(T x, V y) { /* code... */ } 2188 | } 2189 | ``` 2190 | 2191 | Un constructor puede ser genérico aunque su clase no lo sea: 2192 | 2193 | ```java 2194 | class Sample { 2195 | // variables de instancia 2196 | 2197 | Sample(T arg) { // Constructor genérico 2198 | // code... 2199 | } 2200 | } 2201 | ``` 2202 | 2203 | ### Interfaces genéricas 2204 | 2205 | Las interfaces genéricas se especifican como una clase genérica. Cualquier clase que implemente una interfaz genérica también debe ser una clase genérica. Si se especifica el tipo entonces no es necesario que sea genérica. 2206 | 2207 | Los parámetros de tipo especificado en una interfaz también se pueden vincular (limitar) con los tipos vinculados. Las clases que implementen dicha interfaz deberán pasarle un argumento de tipo que tenga la misma vinculación. 2208 | 2209 | ```java 2210 | // Interfaz genérica 2211 | interface ISample { 2212 | boolean contains(T arg); 2213 | } 2214 | 2215 | // Interfaz genérica con tipos vinculados (limitados) por la superclase 'Number' 2216 | interface ISample2 { 2217 | // ... 2218 | } 2219 | 2220 | // Clase genérica obligada que implementa una interfaz genérica 2221 | class Sample implements ISample { 2222 | // ... 2223 | } 2224 | 2225 | // Clase no necesariamente genérica que implementa una interfaz con un tipo concreto 2226 | class Sample implements ISample { 2227 | // ... 2228 | } 2229 | 2230 | // Clase con parámetros de tipo vinculados 2231 | class Sample2 implements ISample2 { 2232 | // .... 2233 | } 2234 | 2235 | /* No es necesario volver a indicarla en ISample2 */ 2236 | // class Sample2 implements ISample2 {} // ¡¡INCORRECTO!!. 2237 | ``` 2238 | 2239 | ### Genéricos y código legado 2240 | 2241 | Antes de la JDK 5 no existían los genéricos. Por tanto, para asegurar la compatibilidad con código legado Java permite usar una clase génerica sin argumetos de tipo. En estos casos se convierte en un tipo sin procesar. 2242 | 2243 | ```java 2244 | class Gen { 2245 | // ... 2246 | } 2247 | 2248 | Gen iOb = new Gen(0); // Objeto 'Gen' para enteros 2249 | Gen strOb = new Gen(""); // Objeto 'Gen' para Strings 2250 | Gen legacyOb = new Gen(new Double(0.0)); // Objeto 'legacy' con tipo sin procesar 2251 | 2252 | // Dado que el compilador desconoce el tipo sin procesar se producen situaciones potencialmente erróneas 2253 | strOb = legacyOb; // Asignación que no produce error de compilación pero insegura 2254 | //iOb = strOb; // Asignación errónea que detecta el compilador 2255 | ``` 2256 | 2257 | ### Inferencia de tipos 2258 | 2259 | A partir de la JDK 7 es posible reducir la sintaxis a la hora de crear una instancia de un tipo genérico. Para la creación de una instancia se emplea una lista vacía de argumentos (`<>`) que indica al compilador que infiera los argumentos de tipo que necesita el constructor. En caso de que sea necesario mantener la compatibilidad con código legado se puede emplear la forma completa: 2260 | 2261 | ```java 2262 | class Gent { 2263 | // code... 2264 | } 2265 | 2266 | Gen iOb = new Gen(); // Forma completa 2267 | Gen iOb = new Gent<>(); // Sintaxis reducida para la JDK 7 y posteriores 2268 | ``` 2269 | 2270 | ### Restricciones y ambigüedad 2271 | 2272 | El uso de genéricos puede crear situaciones de ambigüedad, sobretodo en casos de sobrecarga de métodos: 2273 | 2274 | ```java 2275 | class Gen { 2276 | /* Estos dos métodos se sobrecargan pero dado que T y V pueden ser del mismo tipo, se generarían 2277 | dos métodos iguales por lo que el compilador genera un error y este código no compila. */ 2278 | void get(T ob) {} 2279 | 2280 | void get(V ob) {} 2281 | } 2282 | ``` 2283 | 2284 | Una restricción importante es que los parámetros de tipo no se pueden utilizar como si fueran tipos normales ni tampoco declarar variables estáticas de parámetros de tipo: 2285 | 2286 | ```java 2287 | class Gen { 2288 | T ob; 2289 | static V ob; // ¡¡INCORRECTO!!, no hay variables estáticas de 'T' 2290 | 2291 | void sample() { 2292 | ob = new T(); // ¡¡INCORRECTO!!, no se puede crear instancias de un parámetro de tipo 2293 | } 2294 | 2295 | static T sample () {} // ¡¡INCORRECTO!!, no se puede usar un tipo 'T' como tipo de devolución 2296 | 2297 | static boolean sample () // Correcto 2298 | } 2299 | ``` 2300 | 2301 | ## Expresiones lambda 2302 | 2303 | Básicamente **una expresión lambda es un método anónimo**. Sin embargo, este método no se ejecuta por sí solo, sino que se usa para implementar un método definido por una **interfaz funcional**. Estas interfaces funcionales anteriormente se conocían por SAM (_Single Abstract Method_). 2304 | 2305 | Las expresiones lambda también suele denominarse _'closure'_. 2306 | 2307 | **Una interfaz funcional es una interfaz que únicamente contiene un método abstracto**. Por lo tanto, una interfaz funcional suele representar una única acción. 2308 | 2309 | Una interfaz funcional puede incluir métodos predeterminados y/o métodos estáticos pero en todos los casos solo puede haber **un solo método abstracto** para que la interfaz sea considerada interfaz funcional. Como los métodos de interfaz no predeterminados y no estáticos son implícitamente abstractos, no es necesario utilizar la palabra clave `abstract`. 2310 | 2311 | ```java 2312 | interface Sample { // interfaz funcional 2313 | double getValue(); // método ímplícitamente abstracto 2314 | } 2315 | ``` 2316 | 2317 | ### Fundamentos 2318 | 2319 | El nuevo operador para las expresiones lambda se denomina **operador lambda** y tiene la forma de flecha `->`. Divide la expresión lambda en dos partes: la parte izquierda especifica los parámetros necesarios y la parte derecha contiene el cuerpo de la expresión. 2320 | 2321 | Este cuerpo puede estar compuesto por una única expresión o puede ser un bloque de código. Cuando es una única expresión se denomina **lambda de expresión** y cuando es un bloque de código se denomina **lambda de bloque**. 2322 | 2323 | ```java 2324 | () -> 98.6; // Expresión lambda sin parámetros que evalúa un valor constante 2325 | 2326 | (int n) -> 100 - n: // Expresión lambda con un parámetro 2327 | 2328 | (n) -> 100 - n; // Expresión lambda con un parámetro cuyo tipo es inferido 2329 | 2330 | n -> 100 - n; // Cuando sólo hay un parámetro los paréntesis son opcionales 2331 | ``` 2332 | 2333 | Una expresión lambda no se ejecuta por sí misma, sino que forma la **implementación del método abstracto** definido por la interfaz funcional que especifica su tipo de destino. Como resultado, una expresión lambda solo se puede especificar en un contexto en el que se haya definido un tipo de destino. Uno de estos contextos se crea al asignar una expresión lambda a una referencia de interfaz funcional. Otros contextos de tipo de destino son la inicialización de variables, las instrucciones `return` y los argumentos de métodos por ejemplo. 2334 | 2335 | ```java 2336 | interface IFuncional { // interfaz funcional 2337 | double getValue(); // método abstracto 2338 | } 2339 | 2340 | // Referencia a una interfaz funcional 2341 | IFuncional sample; 2342 | 2343 | // Usar una expresión lambda en un contexto de asignación a una referencia de interfaz funcional 2344 | sample = () -> 98.6; 2345 | ``` 2346 | 2347 | Al invocar el método de la interfaz funcional se ejecuta la implementación de la expresión lambda. 2348 | 2349 | ```java 2350 | // Usamos la referencia para invocar el método de la interfaz y que ha sido implementado por la expresión lambda. 2351 | sample.getValue(); 2352 | ``` 2353 | 2354 | Por lo general, el tipo del método abstracto definido por la interfaz funcional y el tipo de la expresión lambda deben ser compatibles. Esto es, **el tipo de devolución y la firma del método de la interfaz funcional deben ser iguales o compatibles con la expresión lambda** 2355 | 2356 | ```java 2357 | // Interfaz funcional con un método que acepta dos parámetros y devuelve un booleano 2358 | interface IFuncional { 2359 | boolean areEquals(int a, int b); 2360 | } 2361 | 2362 | IFuncional sample = (n, m) -> n == m; 2363 | 2364 | // Forma opcional porque el compilador puede inferir los tipos de n y m por el contexto 2365 | // IFuncional sample = (int n, int m) -> n == m; 2366 | 2367 | sample.areEquals(10, 15); // Invocar el método. 2368 | ``` 2369 | 2370 | ### Bloques de expresión lambda 2371 | 2372 | Para crear una lambda de bloque basta encerrar las instrucciones entre llaves. La lambda de bloque funciona igual que las lambda de expresión con la salvedad que hay que incluir en una lambda de bloque una instrucción `return` para devolver un valor. 2373 | 2374 | En una lambda de bloque podemos declarar variables, utilizar bucles, instrucciones `switch`, etc.. Una lambda de bloque funciona como un método. 2375 | 2376 | ### Interfaces funcionales genéricas 2377 | 2378 | La interfaz funcional asociada a una expresión (o bloque) lambda puede ser genérica. En este caso, el tipo de destino de la expresión lambda se determina, en parte, por el tipo de argumento o argumentos especificados al declarar la interfaz funcional. 2379 | 2380 | ```java 2381 | // Interfaz funcional usando genéricos 2382 | interface IFuncional { 2383 | boolean areEquals(T a, V b); 2384 | } 2385 | 2386 | IFuncional iSample = (int n, int m) -> n == m; // Expresión lambda usando enteros 2387 | iSample.areEquals(10, 20); 2388 | 2389 | IFuncional strSample = (String n, String m) -> n.equals(m); // Expresión lambda usando Strings 2390 | strSample.areEquals("cad", "cad"); 2391 | ``` 2392 | 2393 | ### Expresiones lambda como argumento de función 2394 | 2395 | Una operación muy habitual es usar las expresiones lambda como argumento de una función. 2396 | 2397 | ```java 2398 | // Interfaz funcional 2399 | interface IFuncional { 2400 | boolean areEquals(int a, int b); 2401 | } 2402 | 2403 | class LambdaArgumentDemo { 2404 | // Método estático que acepta una interfaz funcional de tipo IFuncional como primer parámetro. 2405 | static boolean operation(IFuncional sample, int a, int b) { 2406 | return sample.areEquals(a, b); 2407 | } 2408 | 2409 | public static void main(String...args) { 2410 | IFuncional sample = (int n, int m) -> n == m; 2411 | 2412 | // Se pasa un referencia una instancia de la interfaz IFuncional creada con una expresión lambda. 2413 | LambdaArgumentDemo.operation(sample, 10, 15); 2414 | 2415 | // También es posible pasar la expresión lambda directamente a la función 2416 | LambdaArgumentDemo.operation((n, m) -> n == m, 10, 15); 2417 | } 2418 | } 2419 | ``` 2420 | 2421 | ### Expresiones lambda y captura de variables 2422 | 2423 | Las variables definidas por el ámbito contenedor de una expresión lambda son accesibles desde la propia expresión lambda, como por ejemplo variables de instancia o una variable `static` definida por su clase contenedora. Una expresión lambda también tiene acceso a `this`, lo que hace referencia a la instancia de invocación de la clase contenedora de la expresión lambda. 2424 | 2425 | Sin embargo, cuando una expresión lambda usa una variable local desde su ámbito contenedor, se crea una situación especial denominada **captura de variables**. En ese caso, la expresión lambda puede usar únicamente variables locales que sean **eficazmente finales**. 2426 | 2427 | **Una variable eficazmente final es aquella cuyo valor no cambia una vez asignada**. No es necesario declararla explícitamente como final. 2428 | 2429 | ```java 2430 | // Interfaz funcional 2431 | interface IFuncional { 2432 | int func(int a); 2433 | } 2434 | 2435 | class VarCapture { 2436 | public static void main(String...args) { 2437 | int num = 10; // variable local a capturar en la expresión lambda 2438 | 2439 | IFuncional sample = (n) -> { 2440 | int v = n + num; // Uso correcto. La variable 'num' no se modifica 2441 | 2442 | /* Uso incorrecto ya que la variable 'num' se modifica dentro de la expresión 2443 | y por tanto ya no es una variable eficazmente final */ 2444 | // num++ 2445 | 2446 | return v; 2447 | }; 2448 | 2449 | sample.func(100); // Uso de la expresión lambda. 2450 | } 2451 | } 2452 | ``` 2453 | 2454 | ### Generar una excepción desde una expresión lambda 2455 | 2456 | Una expresión lambda puede generar una excepción. No obstante, si genera una excepción comprobada, esta tendrá que ser compatible con la excepción (o excepciones) indicadas en la cláusula `throws` del método abstracto de la interfaz funcional. 2457 | 2458 | ```java 2459 | interface IFuncional { 2460 | boolean ioAction(Reader rdr) throws IOException; 2461 | } 2462 | 2463 | class LambdaExceptionDemo { 2464 | public static void main(String...args){ 2465 | IFuncional sample = (rdr) -> { 2466 | // Como la invocación a 'read()' generaría una IOException, el método 'ioAction()' 2467 | // de la interfaz funcional debe incluir IOException en una cláusula 'throws' 2468 | int ch = rdr.read(); 2469 | 2470 | return true; 2471 | }; 2472 | } 2473 | } 2474 | ``` 2475 | 2476 | ### Referencias de métodos 'static' y métodos de instancia 2477 | 2478 | Una referencia de método permite hacer referencia a un método sin ejecutarlo. Al evaluar una referencia de método también se crea una instancia de una interfaz funcional. 2479 | 2480 | El nombre de la clase se separa del método mediante un par de puntos `::`, un nuevo separador añadido a Java en la JDK 8: 2481 | 2482 | - Sintaxis para métodos estáticos: `NombreClase::nombreMétodo` 2483 | - Sintaxis para métodos de instancia: `refObj::nombreMétodo` 2484 | 2485 | Si es un método genérico la sintaxis es `NombreClase::nombreMétodo` o `refObj::nombreMétodo` 2486 | 2487 | ```java 2488 | interface IntPredicate { 2489 | boolean areEquals(int n, int m); 2490 | } 2491 | 2492 | public class Sample { 2493 | // Método estático que recibe dos parámetros de tipo int y los compara entre sí 2494 | static boolean compare(int a, int b) { 2495 | return a == b; 2496 | } 2497 | 2498 | // Método miembro 2499 | boolean compare2(int a, int b) { 2500 | return a == b; 2501 | } 2502 | 2503 | // Este método tiene una interfaz funcional como tipo en su primer parámetro 2504 | static boolean numTest(IntPredicate p, int a, int b) { 2505 | return p.areEquals(a, b); 2506 | } 2507 | 2508 | public static void main(String...args) { 2509 | // Pasamos a numTest() una referencia de método estático 2510 | System.out.println(Sample.numTest(Sample::compare, 10, 10)); // => true 2511 | 2512 | Sample sample = new Sample(); 2513 | 2514 | IntPredicate p = sample::compare2; // Se crea una referencia de método 2515 | 2516 | System.out.println(Sample.numTest(p, 10, 15)); // => false 2517 | System.out.println(Sample.numTest(sample::compare2, 15, 15)); // => true 2518 | } 2519 | } 2520 | ``` 2521 | 2522 | ### Referencias de constructor 2523 | 2524 | Al igual que se crean referencias de método, se pueden crear referencias a constructores. La sintaxis es `NombreClase::new`. Si es una clase con genéricos la sintaxis es `NombreClase::new`. En el caso de una matriz tiene la sintaxis `tipo[]::new` 2525 | 2526 | ```java 2527 | interface IntPredicate { // Interfaz funcional 2528 | MyClass create(String n); // Método abstracto que recibe un 'String' como parámetro y retorna 'MyClass' 2529 | } 2530 | 2531 | class MyClass { 2532 | String name; 2533 | 2534 | MyClass(String n) { 2535 | name = n; 2536 | } 2537 | 2538 | MyClass() { 2539 | name = ""; 2540 | } 2541 | } 2542 | 2543 | public class Sample { 2544 | public static void main(String...args) { 2545 | IntPredicate p = MyClass::new; // Una referencia de constructor 2546 | 2547 | MyClass c = p.create("MyClass"); 2548 | 2549 | System.out.println(c.name); 2550 | } 2551 | } 2552 | ``` 2553 | 2554 | ### Interfaces funcionales predefinidas 2555 | 2556 | En Java 8 apareció el paquete `java.util.function` que proporciona una serie de **interfaces funcionales predefinidas** preparadas para utilizar: 2557 | 2558 | - **`Consumer`**: Representa una operación que acepta un solo argumento de entrada y no devuelve ningún resultado. 2559 | - **`BiConsumer`**: Representa una operación que acepta dos argumentos de entrada y no devuelve ningún resultado. 2560 | - **`Function`**: Representa una función que acepta un argumento y produce un resultado. 2561 | - **`BiFunction`**: Representa una función que acepta dos argumentos y produce un resultado. 2562 | - **`UnaryOperator`**: Representa una operación en un solo operando que produce el mismo tipo que su operando. 2563 | - **`BinaryOperator`**: Representa una operación sobre dos operandos del mismo tipo, produciendo un resultado del mismo tipo que los operandos. 2564 | - **`Supplier`**: Representa una función que no acepta argumentos y devuelve un resultado. 2565 | - **`Predicate`**: Representa un predicado (función que se evalua de forma booleana) de un argumento. 2566 | 2567 | ```java 2568 | import java.util.function.Predicate; // Importar la interfaz 'Predicate' 2569 | 2570 | public class Sample { 2571 | public static void main(String...args) { 2572 | Predicate isEven = n -> (n % 2) == 0; 2573 | 2574 | System.out.println("4 es par? " + isEven.test(4)); 2575 | } 2576 | } 2577 | ``` 2578 | 2579 | [Más información](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/function/package-summary.html) 2580 | 2581 | ## Stream API 2582 | 2583 | La API _Stream_, introducida en la [versión 1.8](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/package-summary.html), es un juego de utilidades para la manipulación de grandes agrupaciones de objetos en memoria. 2584 | 2585 | Este mecanismo explota las capacidades de las expresiones lambda. La API _Stream_ no es un nuevo tipo de colección sino más bien un envoltorio que facilita su manipulación. 2586 | 2587 | Esta API ofrece dos tipos de operaciones: 2588 | 2589 | - **Operaciones intermedias**: son aquellas que producen o retornan un nuevo _stream_, pudiéndose concatenar unas con otras como por ejemplo: 2590 | - **distinct**: retorna un nuevo _stream_ con los elementos diferentes entre sí 2591 | - **filter**: retorna un nuevo _stream_ de acuerdo con la expresión pasada como parámetro 2592 | - **limit**: retorna un nuevo _stream_ con el número máximo de elementos pasado como parámetro 2593 | - **of**: retorna un _stream_ a partir de un array 2594 | - **sorted**: retorna un nuevo _stream_ ordenado 2595 | - **Operaciones finales**: son aquellas que no producen un _stream_, como por ejemplo: 2596 | - **count**: retorna el número de elementos 2597 | - **findFirst**: retorna el primer elemento 2598 | - **forEach**: realiza una acción sobre cada uno de los elementos 2599 | - **max/min**: retorna el máximo/mínimo elemento 2600 | 2601 | [Más información](https://dev.java/learn/api/streams/) 2602 | 2603 | ### Crear un stream 2604 | 2605 | Todas las clases de tipo `Stream` tienen un método `of()` que recibe como parámetro un **array de objetos**. La clase `java.util.Arrays` también dispone del método `stream()` con el mismo objetivo: 2606 | 2607 | ```java 2608 | int[] enteros = new int[]{1, 2, 3, 4, 5}; 2609 | 2610 | IntStream strEnt = IntStream.of(enteros); 2611 | IntStream strEnt3 = IntStream.of(4, 5, 6); 2612 | IntStream strEnt2 = Arrays.stream(enteros); 2613 | ``` 2614 | 2615 | La mayoría de las clases del **framework de colecciones** disponen de un método `stream()` para crear un _stream_: 2616 | 2617 | ```java 2618 | List empleados = getListaEmpleados(); 2619 | 2620 | Stream strEmp = Stream.of(empleados); 2621 | Stream strEmp2 = empleados.stream(); 2622 | Stream strEmp3 = empleados.parallelStream(); 2623 | ``` 2624 | 2625 | ### Recorrer un stream 2626 | 2627 | Recorrer un _stream_ se considera una **operación final**. 2628 | 2629 | Para recorrer o ejecutar una acción sobre cada uno de los elementos de un _stream_ se utiliza el método `forEach()` junto con una expresión lambda que representará la implementación de una interfaz funcional de tipo `java.util.function.Consumer`: 2630 | 2631 | ```java 2632 | IntStream.of(1, 2, 3, 4, 5, 6).forEach(e -> System.out.println("Entero: " + e)); 2633 | 2634 | empleados.stream().forEach(emp -> System.out.println("Nombre: " + emp.getNombre())); 2635 | ``` 2636 | 2637 | ### Operaciones de filtrado 2638 | 2639 | Filtrar un _stream_ se considera una **operación intermedia**. 2640 | 2641 | Las operaciones de filtrado se realizarán a través del método `filter()` empleando una expresión lambda que representará la implementación de una interfaz funcional de tipo `java.util.function.Predicate` y establecerá las condiciones de filtrado: 2642 | 2643 | ```java 2644 | IntStream.of(5, 20, 32, 8, 14, 24) // se crea el stream 2645 | .filter(e -> e > 10) // retorna un nuevo stream filtrado 2646 | .forEach(e -> System.out.println( e + " es mayor que 10")); // recorrer el stream 2647 | ``` 2648 | 2649 | ### Operaciones de ordenación 2650 | 2651 | Ordenar un _stream_ se considera una **operación intermedia**. 2652 | 2653 | Las operaciones de ordenación de tipos primitivos serán automáticas con el método `sorted()` mientras que para la ordenación de objetos se realiza con la implementación de la interfaz `java.util.Comparator`: 2654 | 2655 | ```java 2656 | IntStream.of(5, 20, 32, 8, 14, 24) 2657 | .sorted() // ordena el stream 2658 | .forEach(e -> System.out.println(e)); // imprime el stream ordenado 2659 | 2660 | empleados.stream() 2661 | .sorted((emp1, emp2) -> emp1.getAge() - emp2.getAge()) 2662 | .forEach(emp -> System.out.println("Empleado: " + emp.getName())); 2663 | ``` 2664 | 2665 | ### Operaciones de mapeo 2666 | 2667 | Mapear un _stream_ se considera una **operación intermedia**. 2668 | 2669 | Las operaciones de mapeo permiten aplicar una función a un _stream_ para producir otro _stream_ de tipo diferente como por ejemplo `mapToInt()` o `mapToLong().` La expresión lambda es una implementación de la interfaz funcional `java.util.function.Function`. 2670 | 2671 | El hecho de construir un _stream_ de tipos primitivos puede servir para realizar algún tipo de operación como por ejemplo una suma o una media. 2672 | 2673 | ```java 2674 | empleados.stream() 2675 | .sorted((emp1, emp2) -> emp1.getAge() - emp2.getAge()) // ordena el stream 2676 | .mapToInt(emp -> emp.getAge()) // mapea la edad en un nuevo stream 2677 | .forEach(emp -> System.out.println("Edad del empleado: " + emp)); // recorre el stream 2678 | ``` 2679 | 2680 | ### Operaciones aritméticas 2681 | 2682 | Este tipo de operaciones se consideran una **operación final**. 2683 | 2684 | Las clases _stream_ que envuelven tipos primitivos como las subclases `IntStream`, `DoubleStream` o `LongStream` incorporan métodos que permiten realizar algunas operaciones aritméticas como por ejemplo `sum()`, `average()`, `max()`, `min()` o `count()`: 2685 | 2686 | ```java 2687 | empleados.stream() 2688 | .mapToInt(emp -> emp.getAge()) // mapea la edad en un nuevo stream 2689 | .average() // calcula la media de los enteros del stream 2690 | .getAsDouble(); // imprime la media de edad 2691 | ``` 2692 | 2693 | ### Operaciones de colección 2694 | 2695 | Este tipo de operaciones se consideran una **operación final**. 2696 | 2697 | Permiten generar un nuevo objeto o una lista de ellos a partir de un _stream_: 2698 | 2699 | ```java 2700 | List nombres = empleados.stream() 2701 | .map(emp -> emp.getName()) // mapea el nombre en un nuevo stream 2702 | .sorted() // ordena alfabéticamente los nombres 2703 | .collect(Collectors.toList()); // retorna una lista a partir del stream 2704 | ``` 2705 | 2706 | ## Colecciones 2707 | 2708 | Una **colección** -a veces llamada contenedor- es simplemente un objeto que agrupa múltiples elementos en una sola unidad. Las colecciones se utilizan para almacenar, recuperar, manipular y comunicar datos agregados. 2709 | 2710 | Un [framework de colecciones](https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html) es una arquitectura unificada para representar y manipular colecciones. Todos los _frameworks_ de colecciones contienen lo siguiente: 2711 | 2712 | - **Interfaces**: Estos son tipos de datos abstractos que representan colecciones. Las interfaces permiten manipular las colecciones independientemente de los detalles de su representación. En los lenguajes orientados a objetos, las interfases generalmente forman una jerarquía. 2713 | 2714 | - **Implementaciones**: Estas son las implementaciones concretas de las interfaces de colecciones. En esencia, son estructuras de datos reutilizables. 2715 | 2716 | - **Algoritmos**: Estos son métodos que realizan cálculos útiles, como la búsqueda y clasificación, en objetos que implementan las interfaces de colección. Se dice que los algoritmos son **polimórficos**, es decir, que se puede utilizar el mismo método en muchas implementaciones diferentes de la interfaz de colección correspondiente. En esencia, los algoritmos son funciones reutilizables. 2717 | 2718 | ### La interfaz 'Collection' 2719 | 2720 | Una [colección](https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html) representa un grupo de objetos conocidos como sus elementos. La interfaz `Collection` se utiliza para transmitir colecciones de objetos en las que se desea la máxima generalidad. 2721 | 2722 | La interfaz `Collection` contiene métodos que realizan operaciones básicas como: 2723 | 2724 | - `int size()` 2725 | - `boolean isEmpty()` 2726 | - `boolean contains(Object element)` 2727 | - `boolean add(E element)` 2728 | - `boolean remove(Object element)` 2729 | - `Iterator iterator()`. 2730 | 2731 | También contiene métodos que operan en colecciones enteras como: 2732 | 2733 | - `boolean containsAll(Collection c)` 2734 | - `boolean addAll(Collection c)` 2735 | - `boolean removeAll(Collection c)` 2736 | - `boolean retainAll(Collection c)` 2737 | - `void clear()`. 2738 | 2739 | La interfaz `Collection` hace lo que cabría esperar, dado que una colección representa un grupo de objetos. Tiene métodos que le dicen cuántos elementos hay en la colección (`size()`, `isEmpty()`), métodos que comprueban si un objeto dado está en la colección (`contains(Object element)`), métodos que añaden y eliminan un elemento de la colección (`add(E element)`, `remove(Object element)`), y métodos que proporcionan un iterador sobre la colección (`iterator()`). 2740 | 2741 | `Collection` es la superinterfaz de otras interfaces fundamentales en Java, como: 2742 | 2743 | - [**`List`**](https://docs.oracle.com/javase/8/docs/api/java/util/List.html): representa una secuencia ordenada de elementos que permite duplicados y acceso por posición. 2744 | 2745 | - [**`Set`**](https://docs.oracle.com/javase/8/docs/api/java/util/Set.html): estructura donde no se permiten elementos duplicados y modela un conjunto matemático. 2746 | 2747 | - [**`Queue`**](https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html): ordena sus elementos generalmente de acuerdo con el principio FIFO (_first-in-first-out_), aunque existen excepciones, como las colas de prioridad. 2748 | 2749 | Cada una de estas subinterfaces especializa `Collection` para diferentes estructuras de datos, añadiendo métodos y restricciones adicionales. 2750 | 2751 | Los métodos `toArray()` y `toArray(T[] a)` se proporcionan como un puente entre colecciones y APIs antiguas que esperan matrices en la entrada. Las operaciones de array permiten traducir el contenido de una colección a un array. La forma sencilla sin argumentos crea una nueva matriz de `Object`. La forma más compleja permite al invocador proporcionar un array o elegir el tipo del array de salida en tiempo de ejecución. 2752 | 2753 | ```java 2754 | Object[] a = c.toArray(); 2755 | 2756 | String[] a = c.toArray(new String[0]); 2757 | ``` 2758 | 2759 | Hay tres formas de recorrer las colecciones: utilizando operaciones agregadas, con la construcción `for-each` y utilizando iteradores. 2760 | 2761 | En JDK 8 y versiones posteriores, el método preferido para iterar sobre una colección es obtener un flujo y realizar [operaciones agregadas](https://docs.oracle.com/javase/tutorial/collections/streams/index.html) en él. Las operaciones agregadas a menudo se usan junto con las **expresiones lambda** para hacer que la programación sea más expresiva, utilizando menos líneas de código. 2762 | 2763 | ```java 2764 | myShapesCollection.stream() 2765 | .filter(e -> e.getColor() == Color.RED) 2766 | .forEach(e -> System.out.println(e.getName())); 2767 | 2768 | // parallel stream if the collection is large enough 2769 | myShapesCollection.parallelStream() 2770 | .filter(e -> e.getColor() == Color.RED) 2771 | .forEach(e -> System.out.println(e.getName())); 2772 | 2773 | String joined = elements.stream() 2774 | .map(Object::toString) 2775 | .collect(Collectors.joining(", ")); 2776 | ``` 2777 | 2778 | La construcción `for-each` permite recorrer de forma concisa, es decir, de uno en uno, una colección o array utilizando un bucle `for`: 2779 | 2780 | ```java 2781 | for (Object o : collection) { 2782 | System.out.println(o); 2783 | } 2784 | ``` 2785 | 2786 | Un [`Iterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html) es un objeto que permite recorrer una colección y eliminar elementos de la colección de forma selectiva, si se desea. Se obtiene un `iterator` para una colección llamando a su método `iterator()`. 2787 | 2788 | La interfaz `Iterator` tiene esta forma: 2789 | 2790 | ```java 2791 | public interface Iterator { 2792 | boolean hasNext(); 2793 | E next(); 2794 | void remove(); //optional 2795 | } 2796 | ``` 2797 | 2798 | El método `hasNext()` devuelve `true` si hay más elementos y el método `next()` devuelve el siguiente elemento. El método `remove()` elimina el último elemento devuelto por el método `next()`. Por tanto sólo puede ser invocado **una vez** por cada llamada a `next()`. Incumplir la regla lanza una excepción. 2799 | 2800 | Es recomendable usar iteradores en vez de una construcción `for-each` cuando se necesita eliminar el elemento actual. 2801 | 2802 | ```java 2803 | static void filter(Collection c) { 2804 | for (Iterator it = c.iterator(); it.hasNext(); ) { 2805 | if (!cond(it.next())) { 2806 | it.remove(); 2807 | } 2808 | } 2809 | } 2810 | ``` 2811 | 2812 | Java permite la creación de **colecciones inmutables**, que no se pueden modificar después de su creación. Estas colecciones son útiles en entornos donde se necesita evitar modificaciones accidentales o garantizar la seguridad en entornos multihilo. Las colecciones inmutables pueden crearse mediante métodos como `Collections.unmodifiableCollection(Collection c)` o con las fábricas de colecciones inmutables introducidas en Java 9, como `List.of()`, `Set.of()`, y `Map.of()`. 2813 | 2814 | La clase [`Collections`](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html) es una clase utilitaria en Java que proporciona métodos estáticos para operar en y devolver colecciones. Esta clase no puede ser instanciada, ya que su constructor es privado. 2815 | 2816 | Java ofrece implementaciones específicas para trabajar con colecciones en entornos multihilo, donde múltiples hilos acceden a la colección simultáneamente. Algunas de las implementaciones más comunes son: 2817 | 2818 | - [**`ConcurrentHashMap`**](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html): un mapa concurrente eficiente que permite acceso seguro en entornos multihilo sin necesidad de sincronización explícita. 2819 | 2820 | - [**`CopyOnWriteArrayList`**](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html): una lista que crea una copia de la estructura subyacente en cada modificación, asegurando la seguridad en concurrencia pero a costa de un mayor uso de memoria. 2821 | 2822 | Estas colecciones concurrentes proporcionan un manejo más eficiente y seguro en situaciones donde las colecciones estándar no son adecuadas. 2823 | 2824 | ### La interfaz 'Set' 2825 | 2826 | Un [`Set`](https://docs.oracle.com/javase/8/docs/api/java/util/Set.html) (conjunto) es una colección que **no puede contener elementos duplicados**. Modela la abstracción del conjunto matemático. La interfaz `Set` hereda métodos de `Collection` pero añade la restricción de que los elementos duplicados están prohibidos. 2827 | 2828 | Para garantizar la unicidad de los elementos, ya que no se permiten los duplicados, `Set` depende de las implementaciones correctas de los métodos `equals(Object o)` y `hashCode()`. Estos métodos se utilizan para comparar los elementos dentro del conjunto, asegurando que dos elementos sean considerados iguales si tienen el mismo valor, incluso si provienen de diferentes implementaciones de `Set`. 2829 | 2830 | Dos instancias de `Set` son consideradas iguales si contienen los mismos elementos, sin importar el orden o la implementación subyacente, siempre que se respete el contrato de `equals(Object o)`. 2831 | 2832 | Algunas de las implementaciones más conocidas de la interfaz `Set` son: 2833 | 2834 | - [**`HashSet`**](https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html), que almacena los elementos en una tabla _hash_. Es la implementación más eficiente en términos de rendimiento, pero no garantiza ningún orden de iteración. 2835 | 2836 | - [**`TreeSet`**](https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html) que almacena los elementos en un árbol _'red-black'_ (rojo-negro), ordenando los elementos en función de sus valores. Aunque es más lenta que `HashSet`, garantiza el orden natural de los elementos. 2837 | 2838 | - [**`LinkedHashSet`**](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashSet.html), que implementa una tabla _hash_ vinculada a una lista enlazada. Mantiene el orden de inserción de los elementos, aunque tiene un coste ligeramente superior al de `HashSet`. 2839 | 2840 | La interfaz `Set` cuenta con una subinterface [`SortedSet`](https://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html), que asegura que los elementos se mantengan en orden ascendente, ya sea según el orden natural o de acuerdo con un `Comparator` proporcionado al momento de la creación del `SortedSet`. 2841 | 2842 | ### La interfaz 'List' 2843 | 2844 | Una [`List`](https://docs.oracle.com/javase/8/docs/api/java/util/List.html) es una **colección ordenada que pueden contener elementos duplicados** (también llamada secuencia). Además de las operaciones heredadas de `Collection`, la interfaz `List` incluye funcionalidades adicionales: 2845 | 2846 | - **Acceso por posición**: permite manipular los elementos de la lista por su índice. Los métodos incluyen `get(int index)`, `set(int index, E element)`, `add(E e)` y `remove()`. 2847 | 2848 | - **Búsqueda**: se pueden buscar elementos específicos dentro de la lista y devolver su posición numérica mediante métodos como `indexOf(Object o)` y `lastIndexOf(Object o)`. 2849 | 2850 | - **Iteración avanzada**: extiende las capacidades de iteración, aprovechando la naturaleza secuencial de las listas, con el uso de `listIterator()`, que permite recorrer la lista en ambas direcciones. 2851 | 2852 | - **Operaciones sobre sublistas**: proporciona la posibilidad de realizar operaciones arbitrarias sobre secciones específicas de la lista con el método `subList(int fromIndex, int toIndex)`. 2853 | 2854 | Algunas de las implementaciones más conocidas de la interfaz `List` son: 2855 | 2856 | - [**`ArrayList`**](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html), que suele ser la implementación de mejor rendimiento en la mayoría de los casos. 2857 | 2858 | - [**`LinkedList`**](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html), que puede ofrecer un mejor rendimiento en ciertas situaciones, como inserciones o eliminaciones frecuentes en el medio de la lista. 2859 | 2860 | ### La interfaz 'Queue' 2861 | 2862 | Una [`Queue`](https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html) (cola) es una colección que contiene elementos antes de ser procesados. Además de las operaciones básicas de una `Collection`, las colas proporcionan operaciones adicionales para insertar, extraer e inspeccionar elementos. 2863 | 2864 | Algunas de las implementaciones más conocidas de la interfaz `Queue` son: 2865 | 2866 | - [**`LinkedList`**](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html) implementa tanto la interfaz `Queue` como la interfaz `List`, lo que le permite actuar como una lista enlazada y una cola al mismo tiempo. 2867 | 2868 | - [**`PriorityQueue`**](https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html) es una cola de prioridad basada en la estructura de pila de datos. Esta cola ordena los elementos según el orden especificado en el momento de la construcción, que puede ser el orden natural de los elementos o el orden impuesto por un comparador explícito. 2869 | 2870 | ```java 2871 | public interface Queue extends Collection { 2872 | E element(); 2873 | boolean offer(E e); 2874 | E peek(); 2875 | E poll(); 2876 | E remove(); 2877 | } 2878 | ``` 2879 | 2880 | Cada método de `Queue` existe en dos formas: una forma lanza una **excepción** si la operación falla, y la otra forma devuelve un valor **especial** si la operación falla (ya sea nulo o falso, dependiendo de la operación): 2881 | 2882 | | Operación | Lanza excepción | Nulo o false | 2883 | |--------------|:---------------:|:------------:| 2884 | | Insertar | `add(e)` | `offer(e)` | 2885 | | Eliminar | `remove()` | `poll()` | 2886 | | Inspeccionar | `element()` | `peek()` | 2887 | 2888 | Las colas generalmente siguen un **orden FIFO** (_first-in-first-out_), aunque no siempre. Las excepciones incluyen las colas de prioridad, que ordenan los elementos según sus valores o prioridades. 2889 | 2890 | Independientemente del orden, la cabeza de la `Queue` es el elemento que sería eliminado por una llamada a `remove()` o `poll()`. En una cola FIFO, los nuevos elementos se insertan al final. Otros tipos de colas pueden utilizar diferentes reglas para la colocación de elementos. Cada implementación de cola debe especificar sus propias reglas de orden. 2891 | 2892 | Algunas implementaciones de `Queue` pueden tener una capacidad limitada, conocidas como **colas acotadas** (_bounded_). 2893 | 2894 | El método `add()`, heredado de `Collection`, inserta un elemento a menos que viole las restricciones de capacidad de la cola, en cuyo caso lanza una `IllegalStateException`. Por otro lado, el método `offer()`, comúnmente usado en colas acotadas, devuelve `false` si el elemento no puede ser insertado. 2895 | 2896 | Los métodos `remove()` y `poll()` eliminan y devuelven la cabeza de la cola. Si la cola está vacía, `remove()` lanza una `NoSuchElementException`, mientras que `poll()` simplemente devuelve nulo. 2897 | 2898 | Finalmente, los métodos `element()` y `peek()` devuelven, pero no eliminan, la cabeza de la cola. La diferencia es que `element()` lanza una excepción si la cola está vacía, mientras que `peek()` devuelve nulo. 2899 | 2900 | ### La interfaz 'Deque' 2901 | 2902 | Una [`Deque`](https://docs.oracle.com/javase/8/docs/api/java/util/Deque.html) (_Double-Ended Queue_ o cola de dos extremos) es una estructura de datos que permite **la inserción y extracción de elementos en ambos extremos**. A diferencia de una `Queue` convencional, que solo permite operaciones en un extremo (**FIFO**), una `Deque` admite operaciones en ambos extremos, lo que la hace más flexible. 2903 | 2904 | La interfaz `Deque` es más versátil que `Stack` y `Queue`, ya que puede implementarse tanto como una pila (**LIFO**) como una cola (**FIFO**). Algunas de las implementaciones más conocidas de la interfaz `Deque` son: 2905 | 2906 | - [**`ArrayDeque`**](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html): una implementación basada en un _array_ redimensionable, eficiente para la mayoría de las operaciones. 2907 | 2908 | - [**`LinkedList`**](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html): una implementación basada en una lista doblemente enlazada, que ofrece un rendimiento consistente para inserciones y eliminaciones en ambos extremos. 2909 | 2910 | La interfaz `Deque` define métodos específicos para acceder, insertar, eliminar y examinar elementos en ambos extremos de la colección. Existen versiones de métodos que pueden lanzar excepciones o devolver un valor nulo en caso de fallos. 2911 | 2912 | | Operación | First Element | Last Element | 2913 | |-----------------------|:---------------:|:--------------:| 2914 | | Insertar (Exception) | `addFirst(e)` | `addLast(e)` | 2915 | | Insertar (boolean) | `offerFirst(e)` | `offerLast(e)` | 2916 | | Eliminar (Exception) | `removeFirst()` | `removeLast()` | 2917 | | Eliminar (null) | `pollFirst()` | `pollLast()` | 2918 | | Examinar (Exception) | `getFirst()` | `getLast()` | 2919 | | Examinar (null) | `peekFirst()` | `peekLast()` | 2920 | 2921 | ### La interfaz 'Map' 2922 | 2923 | Un [`Map`](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html) es un objeto que asigna claves a valores. Un mapa **no puede contener claves duplicadas**; cada clave puede estar asociada a un valor como máximo. Este comportamiento modela la abstracción de una función matemática. 2924 | 2925 | Es importante notar que, a diferencia de otras interfaces en el marco de colecciones de Java como `List` o `Set`, la interfaz `Map` no hereda de `Collection`. Esto se debe a que trabaja con pares clave-valor, mientras que `Collection` opera sobre elementos individuales. Debido a esta diferencia conceptual, `Map` no incluye métodos como `add()` o `iterator()`, que son característicos de las colecciones. 2926 | 2927 | Algunas de las implementaciones más conocidas de la interfaz `Map` son: 2928 | 2929 | - [**`HashMap`**](https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html) almacena sus elementos en una **tabla _hash_** y es generalmente la implementación más rápida. Sin embargo, no garantiza el orden de iteración de los elementos. 2930 | 2931 | - [**`TreeMap`**](https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html) almacena sus elementos en un **árbol _'red-black'_** (árbol rojo-negro) lo que le permite ordenar los elementos en función de sus claves. Esta implementación es más lenta en comparación con `HashMap`. 2932 | 2933 | - [**`LinkedHashMap`**](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html) combina una **tabla _hash_ con una lista enlazada** que mantiene el orden de inserción de los elementos. Aunque tiene un costo ligeramente mayor que `HashMap`, conserva el orden de inserción de los elementos durante la iteración. 2934 | 2935 | La interfaz `Map` tiene una subinterfaz, [`SortedMap`](https://docs.oracle.com/javase/8/docs/api/java/util/SortedMap.html), que garantiza que sus elementos se mantengan en orden ascendente, ya sea según el orden natural de las claves o de acuerdo a un `Comparator` proporcionado al crear el `SortedMap`. 2936 | 2937 | ### Análisis de complejidad en Java Collections 2938 | 2939 | En la **Java Collections Framework**, se utilizan varias estructuras de datos que proporcionan diferentes niveles de eficiencia en términos de tiempo para las operaciones comunes, como acceso, búsqueda, inserción y eliminación. La elección de una estructura de datos adecuada puede tener un impacto significativo en el rendimiento de una aplicación, dependiendo de los patrones de uso que se requieran. 2940 | 2941 | A continuación, se presenta una tabla con la **complejidad temporal**, expresada en notación O grande, de las operaciones más comunes en las estructuras de datos más utilizadas en Java. Esta notación ayuda a estimar el tiempo de ejecución en función del tamaño de la colección: 2942 | 2943 | | Estructura de Datos | Acceso | Búsqueda | Inserción | Eliminación | 2944 | |-------------------------|:------:|:--------:|:---------:|:-----------:| 2945 | | **ArrayList** | O(1) | O(n) | O(1) | O(n) | 2946 | | **LinkedList** | O(n) | O(n) | O(1) | O(1) | 2947 | | **HashMap** | - | O(1) | O(1) | O(1) | 2948 | | **TreeMap** | O(log n)| O(log n) | O(log n) | O(log n) | 2949 | | **HashSet** | - | O(1) | O(1) | O(1) | 2950 | | **TreeSet** | O(log n)| O(log n) | O(log n) | O(log n) | 2951 | | **PriorityQueue** | O(n) | O(n) | O(log n) | O(log n) | 2952 | | **LinkedHashMap** | - | O(1) | O(1) | O(1) | 2953 | | **Stack** (basado en **Vector**) | O(1) | O(n) | O(1) | O(1) | 2954 | | **Deque** (como **ArrayDeque**)| O(1) | O(n) | O(1) | O(1) | 2955 | 2956 | - `ArrayList` tiene tiempo constante para el acceso a elementos, pero las operaciones de búsqueda, inserción o eliminación pueden requerir mover varios elementos. 2957 | 2958 | - `LinkedList` tiene tiempos más costosos de acceso y búsqueda debido a su naturaleza lineal. 2959 | 2960 | - Las estructuras basadas en tablas de _hash_ (`HashMap`, `HashSet`, `LinkedHashMap`) ofrecen tiempos de búsqueda, inserción y eliminación constantes promedio. 2961 | 2962 | - Las estructuras ordenadas como `TreeMap` y `TreeSet` tienen operaciones logarítmicas debido a su implementación basada en árboles (generalmente árboles rojos-negros). 2963 | 2964 | - `PriorityQueue` está diseñada para obtener el elemento de mayor prioridad de manera eficiente, pero las búsquedas dentro de la cola son lineales. 2965 | 2966 | ## Módulos 2967 | 2968 | Con la aparición de JDK 9 se incorporó a Java la característica de los **módulos**. Un módulo es una agrupación de paquetes y recursos a los que se puede hacer referencia conjuntamente a través del nombre del módulo. 2969 | 2970 | La declaración de un módulo son instrucciones en un archivo fuente de Java llamado _'module-info.java'_. Luego `javac` compila ese archivo en un archivo de clase que se conoce como **descriptor de módulo**. Un descriptor de módulo empieza por la palabra clave `module` y tiene la sintaxis: 2971 | 2972 | ```java 2973 | module nombreMódulo { 2974 | // definición de módulo 2975 | } 2976 | ``` 2977 | 2978 | Para especificar la dependencia de un módulo se utiliza la sintaxis `requires NombreMódulo`. 2979 | 2980 | Para exportar un módulo y permitir su uso en otros módulos se utiliza la sintaxis `exports NombrePaquete`. Cuando un módulo exporta un paquete, hace que todos los tipos públicos y protegidos del paquete sean accesibles para otros módulos. Además, los miembros `public` y `protected` de esos tipos también son accesibles. Cualquier paquete no exportado es sólo para uso interno de su módulo. Por tanto, la visibilidad `public` que es la menos restrictiva es únicamente visible dentro de su propio módulo hasta que no se _'exporte'_, lo que hace que sea visible para otros módulos. 2981 | 2982 | Tanto `requires` como `exports` deben estar solo dentro de una declaración de módulo. 2983 | 2984 | ### Módulos de la plataforma 2985 | 2986 | A partir de JDK 9 los paquetes de la API de Java se han incorporado a módulos, permitiendo implementar aplicaciones con únicamente los paquetes necesarios de la JRE, reduciendo considerablemente el tamaño de las aplicaciones. 2987 | 2988 | De los módulos de la plataforma, el más importante es `java.base`. Este módulo incluye y exporta paquetes esenciales de Java como `java.lang`, `java.io` o `java.util` entre otros. Dada su importancia está disponible automáticamente para todos los progamas sin necesidad de usar la instrucción `import` y todos los módulos lo requieren automáticamente y por tanto tampoco es necesario usar la instrucción `requires`. 2989 | 2990 | ### Módulos y código legado 2991 | 2992 | Para permitir la compatibilidad con código anterior a JDK 9, Java introduce dos características para permitir dicha compatibilidad. 2993 | 2994 | Cuando se usa código legado que no forma parte de un módulo nombrado, pasa automáticamente a formar parte del **"módulo sin nombre"**. Este módulo tiene dos atributos importantes. En primer lugar, todos los paquetes que contiene se exportan de forma automática. En segundo lugar, este módulo puede acceder a todos los demás. Por tanto, cuando un programa no usa módulos, todos los módulos de la API de la plataforma Java se vuelven accesibles automáticamente a través del **"módulo sin nombre"**. 2995 | 2996 | Otra característica que permite la compatibilidad con código legado es el uso automático de la ruta de clase en vez de la ruta de módulo. 2997 | 2998 | ## Introducción a JShell 2999 | 3000 | A partir del JDK 9 se incluye una herramienta llamada **JShell** que proporciona un entorno interactivo para experimentar de manera rápida y fácil código Java. 3001 | 3002 | JShell implementa lo que se conoce como ejecución **REPL _(read-evaluate-print loop)_**. Con este mecanismo, se introduce un fragmento de código que se lee y evalúa. A continuación, JShell muestra el resultado del código y queda a la espera del siguiente fragmento o expresión. 3003 | 3004 | Cada secuencia de código introducida se llama _snippet_. 3005 | 3006 | JShell puede evaluar fragmentos de código y expresiones ya que entre bastidores proporciona una clase y un método sintéticos. Es decir, proporciona todo lo necesario para poder ejecutar por ejemplo una instrucción como `System.out.println()`. 3007 | 3008 | En JShell se puede utilizar variables, expresiones, métodos, clases, interfaces, enumeraciones, etcétera... 3009 | 3010 | Además, en JShell se importan por defecto varios paquetes por lo que no es necesario realizar importaciones de los paquetes más comunes. Pueden listarse con `/imports`. 3011 | 3012 | Para iniciar JShell escribimos `jshell` desde la línea de comandos. 3013 | 3014 | Podemos cargar un fichero de cualquier extensión con fragmentos de código o con una sesión previa con `jshell nombrearchivo`. 3015 | 3016 | Una vez iniciada la consola, JShell dispone de una serie de comandos que empiezan por `/`: 3017 | 3018 | - **/help**: muestra la ayuda 3019 | - **/exit**: salir de JShell 3020 | - **/list**: muestra todos los _snippets_ introducidos 3021 | - **/edit o /edit n**: permite editar todos los snipets o uno en concreto 3022 | - **/save nombrearchivo**: permite guardar la sesión actual de _snippets_ 3023 | - **/open nombrearchivo**: permite cargar una sesión de _snippets_ 3024 | - **/types**: muestra clases, interfaces y enumeraciones 3025 | - **/imports**: muestra las importaciones 3026 | - **/methods**: muestra los métodos 3027 | - **/vars**: muestra las variables 3028 | 3029 | Más información [aquí](https://dev.java/learn/jshell-tool/) o [aquí](https://docs.oracle.com/en/java/javase/21/jshell/introduction-jshell.html) 3030 | 3031 | --- 3032 | 3033 | ## Histórico de versiones 3034 | 3035 | ### JDK 1.0 (23/01/1996) 3036 | 3037 | - Primera versión 3038 | 3039 | ### JDK 1.1 (19/02/1997) 3040 | 3041 | - Reestructuración intensiva del modelo de eventos AWT (Abstract Windowing Toolkit) 3042 | - Clases internas (inner classes) 3043 | - JavaBeans 3044 | - JDBC (Java Database Connectivity), para la integración de bases de datos 3045 | - RMI (Remote Method Invocation) 3046 | 3047 | ### J2SE 1.2 (08/12/1998) 3048 | 3049 | - Palabra reservada (keyword) `strictfp` 3050 | - Reflexión en la programación 3051 | - API gráfica (Swing) fue integrada en las clases básicas 3052 | - Máquina virtual (JVM) de Sun fue equipada con un compilador JIT (Just in Time) por primera vez 3053 | - Java Plug-in 3054 | - Java IDL, una implementación de IDL (Lenguaje de Descripción de Interfaz) para la interoperabilidad con CORBA 3055 | - Colecciones (Collections) 3056 | 3057 | ### J2SE 1.3 (08/05/2000) 3058 | 3059 | - Inclusión de la máquina virtual de HotSpot JVM (la JVM de HotSpot fue lanzada inicialmente en abril de 1999, para la JVM de J2SE 1.2) 3060 | - RMI fue cambiado para que se basara en CORBA 3061 | - JavaSound 3062 | - Inclusión de 'Java Naming and Directory Interface' (JNDI) en el paquete de bibliotecas principales (anteriormente disponible como una extensión) 3063 | - Java Platform Debugger Architecture (JPDA) 3064 | 3065 | ### J2SE 1.4 (06/02/2002) 3066 | 3067 | - Palabra reservada `assert` 3068 | - Expresiones regulares modeladas al estilo de las expresiones regulares Perl 3069 | - Encadenación de excepciones. Permite a una excepción encapsular la excepción de bajo nivel original. 3070 | - Non-blocking NIO (New Input/Output) 3071 | - Logging API 3072 | - API I/O para la lectura y escritura de imágenes en formatos como JPEG o PNG 3073 | - Parser XML integrado y procesador XSLT (JAXP) 3074 | - Seguridad integrada y extensiones criptográficas (JCE, JSSE, JAAS) 3075 | - Java Web Start incluido (El primer lanzamiento ocurrió en marzo de 2001 para J2SE 1.3) 3076 | 3077 | ### J2SE 5.0 (30/09/2004) 3078 | 3079 | - Genéricos 3080 | - Anotaciones 3081 | - Autoboxing/unboxing 3082 | - Enumeraciones 3083 | - `Varargs` (número de argumentos variable) 3084 | - Bucle `for` mejorado. 3085 | - Utilidades de concurrencia 3086 | - Clase `Scanner` 3087 | 3088 | ### Java SE 6 (11/12/2006) 3089 | 3090 | - Incluye un nuevo marco de trabajo y APIs que hacen posible la combinación de Java con lenguajes dinámicos como PHP, Python, Ruby y JavaScript. 3091 | - Incluye el motor Rhino, de Mozilla, una implementación de Javascript en Java. 3092 | - Incluye un cliente completo de Servicios Web y soporta las últimas especificaciones para Servicios Web, como JAX-WS 2.0, JAXB 2.0, STAX y JAXP. 3093 | - Mejoras en la interfaz gráfica y en el rendimiento. 3094 | 3095 | ### Java SE 7 (07/07/2011) 3096 | 3097 | - Soporte para XML dentro del propio lenguaje. 3098 | - Un nuevo concepto de superpaquete. 3099 | - Soporte para `closures`. 3100 | - Introducción de anotaciones estándar para detectar fallos en el software. 3101 | - NIO2. 3102 | - Java Module System. 3103 | - Java Kernel. 3104 | - Nueva API para el manejo de Días y Fechas, la cual reemplazará las antiguas clases `Date` y `Calendar`. 3105 | - Posibilidad de operar con clases `BigDecimal` usando operandos. 3106 | - Uso de `Strings` en bloques `switch` 3107 | - Uso de guiones bajos en literales numéricos (1_000_000) 3108 | 3109 | ### Java SE 8 LTS (18/03/2014) 3110 | 3111 | - [JDK 8 Documentation](https://docs.oracle.com/javase/8/) 3112 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk8/) 3113 | - [JEP 126](https://openjdk.org/jeps/126): Lambda Expressions & Virtual Extension Methods 3114 | - [JEP 153](https://openjdk.org/jeps/153): Launch JavaFX Applications 3115 | - [JEP 178](https://openjdk.org/jeps/178): Statically-Linked JNI Libraries 3116 | - [JEP 155](https://openjdk.org/jeps/155): Concurrency Updates 3117 | - [JEP 174](https://openjdk.org/jeps/174): Nashorn Javascript Engine 3118 | - [JEP 104](https://openjdk.org/jeps/104): Annotations on Java Types 3119 | - [JEP 150](https://openjdk.org/jeps/150): Date & Time API 3120 | 3121 | ### Java 9 (21/09/2017) 3122 | 3123 | - [JDK 9 Documentation](https://docs.oracle.com/javase/9/) 3124 | - [Java Language Changes for Java SE 9](https://docs.oracle.com/javase/9/language/toc.htm) 3125 | - [Significant Changes in JDK 9 Release](https://docs.oracle.com/javase/9/migrate/toc.htm) 3126 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk9/) 3127 | - [JEP 200](https://openjdk.org/jeps/200): The Modular JDK 3128 | - [JEP 222](https://openjdk.org/jeps/222): 'jshell': The Java Shell (Read-Eval-Print Loop) 3129 | - [JEP 295](https://openjdk.org/jeps/295): Compilación _Ahead-of-Time_ 3130 | - [JEP 282](https://openjdk.org/jeps/282): jlink: The Java Linker 3131 | - [JEP 266](https://openjdk.org/jeps/266): More Concurrency Updates 3132 | - [JEP 263](https://openjdk.org/jeps/263): Gráficos HiDPI 3133 | - [JEP 224](https://openjdk.org/jeps/224): HTML5 Javadoc 3134 | - [JEP 275](https://openjdk.org/jeps/275): Modular Java Application Packaging 3135 | - [JEP 261](https://openjdk.org/jeps/261): Module System 3136 | 3137 | ### Java 10 (20/03/2018) 3138 | 3139 | - [JDK 10 Documentation](https://docs.oracle.com/javase/10/) 3140 | - [Java Language Changes for Java SE 10](https://docs.oracle.com/javase/10/language/toc.htm) 3141 | - [Significant Changes in JDK 10 Release](https://docs.oracle.com/javase/10/migrate/toc.htm) 3142 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/10/) 3143 | - [JEP 286](https://openjdk.org/jeps/286): Local-Variable Type Inference 3144 | - [JEP 317](https://openjdk.org/jeps/317): Experimental Java-Based JIT Compiler 3145 | - [JEP 310](https://openjdk.org/jeps/310): Application Class-Data Sharing 3146 | - [JEP 322](https://openjdk.org/jeps/322): Time-Based Release Versioning 3147 | - [JEP 307](https://openjdk.org/jeps/307): Parallel Full GC for G1 3148 | - [JEP 304](https://openjdk.org/jeps/304): Garbage-Collector Interface 3149 | - [JEP 314](https://openjdk.org/jeps/314): Additional Unicode Language-Tag Extensions 3150 | - [JEP 319](https://openjdk.org/jeps/319): Root Certificates 3151 | - [JEP 312](https://openjdk.org/jeps/312): Thread-Local Handshakes 3152 | - [JEP 316](https://openjdk.org/jeps/316): Heap Allocation on Alternative Memory Devices 3153 | - [JEP 313](https://openjdk.org/jeps/313): Remove the Native-Header Generation Tool – javah 3154 | - [JEP 296](https://openjdk.org/jeps/296): Consolidate the JDK Forest into a Single Repository 3155 | 3156 | ### Java 11 LTS (25/09/2018) 3157 | 3158 | - [JDK 11 Documentation](https://docs.oracle.com/en/java/javase/11/index.html) 3159 | - [Java Language Changes for Java SE 11](https://docs.oracle.com/en/java/javase/11/language/java-language-changes.html) 3160 | - [Significant Changes in JDK 11 Release](https://docs.oracle.com/en/java/javase/11/migrate/index.html) 3161 | - [Lista completa de características -JEP](https://openjdk.org/projects/jdk/11/) 3162 | - [JEP 309](https://openjdk.org/jeps/309): Dynamic Class-File Constants 3163 | - [JEP 318](https://openjdk.org/jeps/318): Epsilon: A No-Op Garbage Collector 3164 | - [JEP 323](https://openjdk.org/jeps/323): Local-Variable Syntax for Lambda Parameters 3165 | - [JEP 331](https://openjdk.org/jeps/331): Low-Overhead Heap Profiling 3166 | - [JEP 321](https://openjdk.org/jeps/321): HTTP Client (Standard) 3167 | - [JEP 332](https://openjdk.org/jeps/323): Transport Layer Security (TLS) 1.3 3168 | - [JEP 328](https://openjdk.org/jeps/328): Flight Recorder 3169 | - [JEP 335](https://openjdk.org/jeps/335): Deprecate the Nashorn Javascript Engine 3170 | 3171 | ### Java 12 (19/03/2019) 3172 | 3173 | - [JDK 12 Documentation](https://docs.oracle.com/en/java/javase/12/index.html) 3174 | - [Java Language Changes for Java SE 12](https://docs.oracle.com/en/java/javase/12/language/index.html) 3175 | - [Significant Changes in JDK 12 Release](https://docs.oracle.com/en/java/javase/12/migrate/index.html) 3176 | - [Lista completa de características- JEP](https://openjdk.org/projects/jdk/12/) 3177 | - [JEP 230](https://openjdk.org/jeps/230): Microbenchmark Suite 3178 | - [JEP 334](https://openjdk.org/jeps/334): JVM Constants API 3179 | 3180 | ### Java 13 (17/09/2019) 3181 | 3182 | - [JDK 13 Documentation](https://docs.oracle.com/en/java/javase/13/index.html) 3183 | - [Java Language Changes for Java SE 13](https://docs.oracle.com/en/java/javase/13/language/java-language-changes.html) 3184 | - [Significant Changes in JDK 13 Release](https://docs.oracle.com/en/java/javase/13/migrate/index.html) 3185 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/13/) 3186 | - [JEP 353](https://openjdk.org/jeps/353): Reimplement the Legacy Socket API 3187 | 3188 | ### Java 14 (17/03/2020) 3189 | 3190 | - [JDK 14 Documentation](https://docs.oracle.com/en/java/javase/14/index.html) 3191 | - [Java Language Changes for Java SE 14](https://docs.oracle.com/en/java/javase/14/language/java-language-changes.html) 3192 | - [Significant Changes in JDK 14 Release](https://docs.oracle.com/en/java/javase/14/migrate/index.html) 3193 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/14/) 3194 | - [JEP 358](https://openjdk.org/jeps/358): Helpful NullPointerExceptions 3195 | - [JEP 361](https://openjdk.org/jeps/361): Switch Expressions 3196 | - [JEP 349](https://openjdk.org/jeps/349): JFR Event Streaming 3197 | 3198 | ### Java 15 (15/09/2020) 3199 | 3200 | - [JDK 15 Documentation](https://docs.oracle.com/en/java/javase/15/index.html) 3201 | - [Java Language Changes for Java SE 15](https://docs.oracle.com/en/java/javase/15/language/java-language-changes.html) 3202 | - [Significant Changes in JDK 15 Release](https://docs.oracle.com/en/java/javase/15/migrate/index.html) 3203 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/15/) 3204 | - [JEP 371](https://openjdk.org/jeps/371): Hidden Classes 3205 | - [JEP 372](https://openjdk.org/jeps/372): Remove the Nashorn JavaScript Engine 3206 | - [JEP 373](https://openjdk.org/jeps/373): Reimplement the Legacy DatagramSocket API 3207 | - [JEP 378](https://openjdk.org/jeps/378): Text Blocks 3208 | 3209 | ### Java 16 (16/03/2021) 3210 | 3211 | - [JDK 16 Documentation](https://docs.oracle.com/en/java/javase/16/index.html) 3212 | - [Java Language Changes for Java SE 16](https://docs.oracle.com/en/java/javase/16/language/java-language-changes.html) 3213 | - [Significant Changes in JDK 16 Release](https://docs.oracle.com/en/java/javase/16/migrate/significant-changes-jdk-release.html) 3214 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/16/) 3215 | - [JEP 347](https://openjdk.org/jeps/347): Enable C++14 Language Features 3216 | - [JEP 369](https://openjdk.org/jeps/369): Migrate to GitHub 3217 | - [JEP 392](https://openjdk.org/jeps/392): Packaging Tool 3218 | - [JEP 394](https://openjdk.org/jeps/394): Pattern Matching for instanceof 3219 | - [JEP 395](https://openjdk.org/jeps/395): Records 3220 | - [JEP 396](https://openjdk.org/jeps/396): Strongly Encapsulate JDK Internals by Default 3221 | 3222 | ### Java 17 LTS (13/09/2021) 3223 | 3224 | - [JDK 17 Documentation](https://docs.oracle.com/en/java/javase/17/index.html) 3225 | - [Java Language Changes for Java SE 17](https://docs.oracle.com/en/java/javase/17/language/java-language-changes.html) 3226 | - [Significant Changes in JDK 17 Release](https://docs.oracle.com/en/java/javase/17/migrate/significant-changes-jdk-release.html) 3227 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/17/) 3228 | - [JEP 356](https://openjdk.org/jeps/356): Enhanced Pseudo-Random Number Generators 3229 | - [JEP 409](https://openjdk.org/jeps/409): Sealed Classes 3230 | - [JEP 403](https://openjdk.org/jeps/403): Strongly Encapsulate JDK Internals 3231 | 3232 | ### Java 18 (22/03/2022) 3233 | 3234 | - [JDK 18 Documentation](https://docs.oracle.com/en/java/javase/18/index.html) 3235 | - [Java Language Changes for Java SE 18](https://docs.oracle.com/en/java/javase/18/language/java-language-changes.html) 3236 | - [Significant Changes in JDK 18 Release](https://docs.oracle.com/en/java/javase/18/migrate/significant-changes-jdk-release.html) 3237 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/18/) 3238 | - [JEP 400](https://openjdk.org/jeps/400): UTF-8 by Default 3239 | - [JEP 408](https://openjdk.org/jeps/408): Simple Web Server 3240 | - [JEP 413](https://openjdk.org/jeps/413): Code Snippets in Java API Documentation 3241 | 3242 | ### Java 19 (20/09/2022) 3243 | 3244 | - [JDK 19 Documentation](https://docs.oracle.com/en/java/javase/19/index.html) 3245 | - [Java Language Changes for Java SE 19](https://docs.oracle.com/en/java/javase/19/language/java-language-changes.html) 3246 | - [Significant Changes in JDK 19 Release](https://docs.oracle.com/en/java/javase/19/migrate/significant-changes-jdk-release.html) 3247 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/19/) 3248 | 3249 | ### Java 20 LTS (21/03/2023) 3250 | 3251 | - [JDK 20 Documentation](https://docs.oracle.com/en/java/javase/20/index.html) 3252 | - [Java Language Changes for Java SE 20](https://docs.oracle.com/en/java/javase/20/language/java-language-changes.html) 3253 | - [Significant Changes in JDK 20 Release](https://docs.oracle.com/en/java/javase/20/migrate/significant-changes-jdk-release.html) 3254 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/20/) 3255 | 3256 | ### Java 21 (21/09/2023) 3257 | 3258 | - [JDK 21 Documentation](https://docs.oracle.com/en/java/javase/21/index.html) 3259 | - [Java Language Changes for Java SE 21](https://docs.oracle.com/en/java/javase/21/language/java-language-changes.html) 3260 | - [Significant Changes in JDK 21 Release](https://docs.oracle.com/en/java/javase/21/migrate/significant-changes-jdk-release.html) 3261 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/21/) 3262 | - [JEP 431](https://openjdk.org/jeps/431): Sequenced Collections 3263 | - [JEP 440](https://openjdk.org/jeps/440): Record Patterns 3264 | - [JEP 441](https://openjdk.org/jeps/441): Pattern Matching for switch 3265 | - [JEP 444](https://openjdk.org/jeps/444): Virtual Threads 3266 | 3267 | ### Java 22 (19/03/2024) 3268 | 3269 | - [JDK 22 Documentation](https://docs.oracle.com/en/java/javase/22/index.html) 3270 | - [Java Language Changes for Java SE 22](https://docs.oracle.com/en/java/javase/22/language/java-language-changes.html) 3271 | - [Significant Changes in JDK 22 Release](https://docs.oracle.com/en/java/javase/22/migrate/significant-changes-jdk-release.html) 3272 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/22/) 3273 | - [JEP 454](https://openjdk.org/jeps/454): Foreign Function & Memory API 3274 | - [JEP 456](https://openjdk.org/jeps/456): Unnamed Variables & Patterns 3275 | 3276 | ### Java 23 (17/09/2024) 3277 | 3278 | - [JDK 23 Documentation](https://docs.oracle.com/en/java/javase/23/index.html) 3279 | - [Java Language Changes for Java SE 23](https://docs.oracle.com/en/java/javase/23/language/java-language-changes.html) 3280 | - [Significant Changes in JDK 23 Release](https://docs.oracle.com/en/java/javase/24/migrate/significant-changes-jdk-23.html) 3281 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/23/) 3282 | 3283 | ### :new: Java 24 (18/03/2025) 3284 | 3285 | - [JDK 24 Documentation](https://docs.oracle.com/en/java/javase/24/index.html) 3286 | - [Java Language Changes for Java SE 24](https://docs.oracle.com/en/java/javase/24/language/java-language-changes-release.html) 3287 | - [Significant Changes in JDK 24 Release](https://docs.oracle.com/en/java/javase/24/migrate/significant-changes-jdk-24.html) 3288 | - [Lista completa de características - JEP](https://openjdk.org/projects/jdk/24/) 3289 | 3290 | --- 3291 | 3292 | ## Enlaces 3293 | 3294 | ### Java 3295 | 3296 | - 🔸 [Java Platform, Standard Edition Documentation](https://docs.oracle.com/en/java/javase/index.html) 3297 | - [Oracle Technology Network / Java](https://www.oracle.com/java/) 3298 | - 3299 | - [Java Documentation](https://docs.oracle.com/en/java/) 3300 | - [JDK Release Notes](https://www.oracle.com/java/technologies/javase/jdk-relnotes-index.html) 3301 | - [OpenJDK](https://openjdk.org/) 3302 | - [OpenJDK - Github](https://github.com/openjdk/) 3303 | - [This JEP is the index of all JDK Enhancement Proposals, known as JEPs](http://openjdk.java.net/jeps/0) 3304 | - ⭐ [The Java Version Almanac](https://javaalmanac.io/) 3305 | - 👓 [Awesome Java](https://github.com/akullpp/awesome-java) 3306 | - [The Scala Programming Language](http://www.scala-lang.org/) 3307 | - ⭐ [Writing Java with Visual Studio Code](https://code.visualstudio.com/docs/java/java-tutorial) 3308 | - ⭐ [Java Development in 2018](https://coggle.it/diagram/WqgTTNMJtPiHph_q/t/java-development-in-2018) 3309 | - [New language features since Java 8 to 18](https://advancedweb.hu/new-language-features-since-java-8-to-18/) 3310 | - ⭐ [SDKMAN! the Software Development Kit Manager](https://sdkman.io/) 3311 | - [jbang - Try out any Java API with one file](https://www.jbang.dev/) 3312 | - [Javadoc hosting for open source projects](https://javadoc.io/) 3313 | - ⭐ [The Java Playground is a simple online tool that helps you to explore Java Language features - Oracle](https://dev.java/playground/) 3314 | - [JShell was a great addition to the JDK. Now it’s online!](https://www.tryjshell.org/) 3315 | - [Ideone is an online compiler and debugging tool](https://ideone.com/) 3316 | - [GraalVM - Run Programs Faster Anywhere](https://www.graalvm.org/) 3317 | 3318 | ### Java - Learning 3319 | 3320 | - ⭐ [The Java™ Tutorials](https://docs.oracle.com/javase/tutorial/index.html) 3321 | - [The Java™ Tutorials](https://docs.oracle.com/javase/tutorial/reallybigindex.html) 3322 | - [Java Tutorials Learning Paths](https://docs.oracle.com/javase/tutorial/tutorialLearningPaths.html) 3323 | - ⭐⭐ 3324 | - ⭐ [Eclipse Collections Kata](https://github.com/eclipse/eclipse-collections-kata) 3325 | - ⭐ 3326 | - 3327 | - 3328 | - 📕 [Introduction to Programming Using Java, Eighth Edition](http://math.hws.edu/javanotes/) 3329 | - 📕 [Think Java](https://handwiki.org/wiki/Book:ThinkJava) 3330 | - 📕 [Java Book](http://www.java2s.com/Book/Java/CatalogJava.htm) 3331 | - 📕 3332 | 3333 | ### Java - Jakarta 3334 | 3335 | - [Jakarta EE](https://jakarta.ee/) 3336 | - [Jakarta EE Platform 10](https://jakarta.ee/specifications/platform/10/) 3337 | - [Apache TomEE is an all-Apache Jakarta EE 9.1 certified application server](http://openejb.apache.org/) 3338 | - [Eclipse GlassFish - Open Source Jakarta EE Platform Implementation](https://glassfish.org/) 3339 | 3340 | ### Java - Libraries 3341 | 3342 | - ⭐ [Guava - Google core libraries for Java](https://github.com/google/guava) 3343 | - ⭐ [Apache Commons is an Apache project focused on all aspects of reusable Java components](https://commons.apache.org/) 3344 | - ⭐⭐ [Apache Projects](https://projects.apache.org/projects.html) 3345 | - ⭐ [Eclipe Projects](https://projects.eclipse.org/) 3346 | - ⭐⭐ [Eclipse Collections is a collections framework for Java](https://eclipse.dev/collections/) 3347 | - ⭐ [Sonatype - The Central Repository](https://central.sonatype.com) 3348 | - ⭐⭐ [Package Search - Jetbrains](https://package-search.jetbrains.com/) 3349 | - ⭐ [Trending Java Projects](https://www.libhunt.com/l/java/trending) 3350 | - [Lombok es una biblioteca que se utiliza para reducir el código boilerplate en Java](https://projectlombok.org/) 3351 | - [Guice is a lightweight dependency injection framework for Java](https://github.com/google/guice) 3352 | - [jsoup - Java HTML Parser, with best of DOM, CSS, and jquery](https://jsoup.org/) 3353 | - [WebJars are client-side web libraries (e.g. jQuery & Bootstrap) packaged into JAR files](https://www.webjars.org/) 3354 | - [jsweet - A transpiler from Java to TypeScript/JavaScript](https://www.jsweet.org/) 3355 | - [TeaVM is an ahead-of-time compiler for Java bytecode that emits JavaScript and WebAssembly that runs in a browser](https://teavm.org/) 3356 | - [GWT is a development toolkit for building and optimizing complex browser-based applications](https://www.gwtproject.org/) 3357 | - [CheerpJ is the Java compiler for Web applications](https://cheerpj.com/) 3358 | - ⭐ [Vaadin - Build Progressive Web Apps in Java](https://vaadin.com/) 3359 | - [J2CL is a powerful, simple and lightweight transpiler from Java to Closure style JavaScript](https://github.com/google/j2cl) 3360 | - [Joda-Time provides a quality replacement for the Java date and time classes](https://www.joda.org/joda-time/) 3361 | - [Strata is the award-winning open source analytics and market risk library from OpenGamma](https://strata.opengamma.io/) 3362 | - [crawler4j is an open source web crawler for Java](https://github.com/yasserg/crawler4j) 3363 | - [JReleaser - The quick and effortless way to release your Java project!](https://jreleaser.org/) 3364 | - 3365 | - [JTS Topology Suite](https://github.com/locationtech/jts) 3366 | - [MapStruct - librería para la generación automática de mappers entre objetos Java](https://mapstruct.org/) 3367 | - [Quartz is a richly featured, open source job scheduling library](https://www.quartz-scheduler.org/) 3368 | - [Flyway - Version control for your database, so you can migrate it with ease and confidence](https://flywaydb.org/) 3369 | - [Apache POI - the Java API for Microsoft Documents](https://poi.apache.org/) 3370 | - [picocli - a mighty tiny command line interface](https://picocli.info/) 3371 | - [Weld is the reference implementation of CDI: Contexts and Dependency Injection for the Java EE Platform](https://weld.cdi-spec.org/) 3372 | - [FlatLaf is a modern open-source cross-platform Look and Feel for Java Swing desktop applications](https://github.com/JFormDesigner/FlatLaf) 3373 | 3374 | ### Java - JSON 3375 | 3376 | - [Gson is a Java library that can be used to convert Java Objects into their JSON representation](https://github.com/google/gson) 3377 | - [Jackson](https://github.com/FasterXML/jackson) 3378 | - [Moshi - A modern JSON library for Android and Java](https://github.com/square/moshi) 3379 | 3380 | ### Java - Logging 3381 | 3382 | - ⭐ [Flogger - A Fluent Logging API for Java by Google](https://github.com/google/flogger) 3383 | - [The Simple Logging Facade for Java (SLF4J)](https://www.slf4j.org/) 3384 | - [Apache Log4j](https://logging.apache.org/log4j) 3385 | - [Logback Project](https://logback.qos.ch/) 3386 | 3387 | ### Java - QA 3388 | 3389 | - ⭐ [Google Java Style](http://google.github.io/styleguide/javaguide.html) 3390 | - [PMD - An extensible cross-language static code analyzer](https://pmd.github.io/) 3391 | - [Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard](https://checkstyle.sourceforge.io/) 3392 | - [Continuous Code Quality](https://www.sonarqube.org/) 3393 | - [FindBugs](https://findbugs.sourceforge.net/) 3394 | - [JaCoCo Java Code Coverage Library](https://www.jacoco.org/jacoco/) 3395 | - [Apache JMeter may be used to test performance both on static and dynamic resources, Web dynamic applications.](https://jmeter.apache.org/) 3396 | - [JProfiler's intuitive UI helps you resolve performance bottlenecks](https://www.ej-technologies.com/products/jprofiler/overview.html) 3397 | - [VisualVM is a visual tool integrating commandline JDK tools and lightweight profiling capabilities.](https://visualvm.github.io/) 3398 | - [JMH - Java Microbenchmark Harness](https://github.com/openjdk/jmh) 3399 | - [Getting Started](https://www.baeldung.com/java-microbenchmark-harness) 3400 | - [Open source Java app performance management tool](https://inspectit.rocks/) 3401 | - [jUnit](https://junit.org) 3402 | - [mockito](https://site.mockito.org/) 3403 | - [TestNG is a testing framework inspired from JUnit and NUnit](https://testng.org/) 3404 | - [Cucumber Open is the world’s #1 automation tool for Behavior-Driven Development](https://cucumber.io/tools/cucumber-open/) 3405 | - [JBehave is a framework for Behaviour-Driven Development (BDD). BDD is an evolution of test-driven development (TDD) and acceptance-test driven design](https://jbehave.org/) 3406 | - [FitNesse - The fully integrated standalone wiki and acceptance testing framework](https://fitnesse.org/) 3407 | - [Jenkins - he leading open source automation server](https://jenkins.io/index.html) 3408 | - 👓 [guardrailsio/awesome-java-security - Awesome Java Security Resources](https://github.com/guardrailsio/awesome-java-security) 3409 | - ⭐ 3410 | 3411 | ### Java - Web 3412 | 3413 | - ⭐ [JHipster is a development platform to generate, develop and deploy Spring Boot + Angular/React/Vue Web applications and Spring microservices](https://www.jhipster.tech/) 3414 | - [Quarkus is a Cloud Native, Container First framework for writing Java applications.](https://quarkus.io/) 3415 | - [Spark Framework - A micro framework for creating web applications in Kotlin and Java 8 with minimal effort](https://sparkjava.com/) 3416 | - [Play Framework - Build Modern & Scalable Web Apps with Java and Scala](https://www.playframework.com/) 3417 | - [Payara Platform Community](https://www.payara.fish/products/payara-platform-community/) 3418 | - [WildFly is a flexible, lightweight, managed application runtime that helps you build amazing applications](https://wildfly.org/) 3419 | - [Eclipse Jetty provides a highly scalable and memory-efficient web server and servlet container](https://jetty.org/) 3420 | - [Netty is an asynchronous event-driven network application framework](https://netty.io/) 3421 | - [Akka - Build powerful reactive, concurrent, and distributed applications more easily](https://akka.io/) 3422 | - [Apache Wicket](https://wicket.apache.org/) 3423 | - [Javalin - A simple web framework for Java and Kotlin](https://javalin.io/) 3424 | - [Spincast is an highly flexible Java web framework, based on Guice](https://www.spincast.org) 3425 | - [Jersey - RESTful Web Services in Java](https://eclipse-ee4j.github.io/jersey/) 3426 | - [OkHttp is an HTTP client](https://square.github.io/okhttp/) 3427 | - [Apache HttpComponents](https://hc.apache.org/index.html) 3428 | - [Retrofit](https://square.github.io/retrofit/) 3429 | 3430 | ### Java - Templating 3431 | 3432 | - [Thymeleaf is a modern server-side Java template engine for both web and standalone environments](https://www.thymeleaf.org/) 3433 | - [Velocity is a Java-based template engine](https://velocity.apache.org/) 3434 | 3435 | ### Java - Microservices 3436 | 3437 | - 🎓 [Java Microservices: A Practical Guide](https://www.marcobehler.com/guides/java-microservices-a-practical-guide) 3438 | - [Eclipse MicroProfile - Optimizing Enterprise Java for a Microservices Architecture](https://microprofile.io/) 3439 | - [Helidon is a collection of Java libraries for writing microservices](https://helidon.io) 3440 | - [Open Liberty from IBM. Build cloud-native apps and microservices while running only what you need](https://openliberty.io/) 3441 | - ⭐ [The quickest way to learn all things Open Liberty, and beyond!](https://openliberty.io/guides/) 3442 | - [Micronaut - A modern, JVM-based, full-stack framework for building modular, easily testable microservice applications](https://micronaut.io/) 3443 | - [Cricket - Microservices Framework](https://cricketmsf.org/) 3444 | - [ActiveJ Java framework for modern web, cloud, high-load, and microservices solutions](https://activej.io/) 3445 | - [Simplify cloud-native application development - Microsoft](https://dapr.io/) 3446 | 3447 | ### Java - RxJava 3448 | 3449 | - [RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.](https://github.com/ReactiveX/RxJava) 3450 | - [Vert.x- Effortless asynchronous application development for the modern web and enterprise](https://vertx.io/) 3451 | - [RxJava Cheat Sheet](https://www.jrebel.com/blog/rxjava-cheat-sheet) 3452 | - 👓 [eleventigers/awesome-rxjava - Useful resources for working with RxJava](https://github.com/eleventigers/awesome-rxjava) 3453 | 3454 | ### Java - SQL 3455 | 3456 | - [Hibernate](https://hibernate.org/) 3457 | - [Jdbi provides convenient, idiomatic access to relational data in Java](https://jdbi.org/) 3458 | - [jOOQ: The easiest way to write SQL in Java](https://www.jooq.org/) 3459 | - [EclipseLink](https://eclipse.dev/eclipselink/) 3460 | 3461 | ### Java - Containers 3462 | 3463 | - [Eclipse JKube is a collection of plugins and libraries that are used for building container images using Docker, JIB or S2I build strategies](https://eclipse.dev/jkube/) 3464 | - [Jib - Build container images for your Java applications.](https://github.com/GoogleContainerTools/jib) 3465 | 3466 | ### Java - Builds 3467 | 3468 | - 3469 | - 3470 | - 3471 | - 3472 | - 3473 | - 3474 | - 3475 | - 3476 | 3477 | ### Java - Sites 3478 | 3479 | - ⭐ [The Destination for Java Developers](https://dev.java/) 3480 | - ⭐ [Baeldung](https://www.baeldung.com/) 3481 | - [Oracle Blogs | The Java Source](https://blogs.oracle.com/java/) 3482 | - [Oracle Blogs | Java Magazine](https://blogs.oracle.com/javamagazine/) 3483 | - [JavaWorld](https://www.infoworld.com/category/java/) 3484 | - [InfoQ - Java](https://www.infoq.com/java/) 3485 | - [Javarevisited](https://javarevisited.blogspot.com/) 3486 | - [Java, SQL and JOOQ](https://blog.jooq.org/) 3487 | - [A Java geek](https://blog.frankel.ch/) 3488 | - [Java Code Geeks](https://www.javacodegeeks.com/) 3489 | - [DZone](https://dzone.com/java) 3490 | - [TheServerSide](https://www.theserverside.com/) 3491 | - [devmio](https://devm.io/java) 3492 | - [The Spring Blog](https://spring.io/blog) 3493 | - [Inside Java - News and views from the Java team at Oracle](https://inside.java/) 3494 | - [The JetBrains Blog](https://blog.jetbrains.com/category/news/) 3495 | - [James Ward](https://jamesward.com/) 3496 | - [Microsoft | Java at Microsoft](https://developer.microsoft.com/en-us/java) 3497 | - [Java en AWS](https://aws.amazon.com/es/developer/language/java/) 3498 | - [foojay — a place for friends of OpenJDK](https://foojay.io/today/) 3499 | 3500 | ## Licencia 3501 | 3502 | [![Licencia de Creative Commons](https://i.creativecommons.org/l/by-sa/4.0/80x15.png)](http://creativecommons.org/licenses/by-sa/4.0/) 3503 | Esta obra está bajo una [licencia de Creative Commons Reconocimiento-Compartir Igual 4.0 Internacional](http://creativecommons.org/licenses/by-sa/4.0/). 3504 | -------------------------------------------------------------------------------- /README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alxgcrz/_learning_java_/4c5a00bf36b72ee0601a27a2a35e0171a61a2599/README.pdf -------------------------------------------------------------------------------- /live.js: -------------------------------------------------------------------------------- 1 | const readline = require('readline'); 2 | const { execSync } = require('child_process'); 3 | 4 | const html = process.env.npm_package_config_html || 'index.html'; 5 | 6 | const options = [ 7 | { key: '1', alias: 'F', name: 'Firefox', browser: 'firefox' }, 8 | { key: '2', alias: 'C', name: 'Chrome', browser: 'chrome' }, 9 | { key: '3', alias: 'E', name: 'Edge', browser: 'msedge' } 10 | ]; 11 | 12 | function printMenu() { 13 | console.log('\nSelecciona un navegador:\n'); 14 | options.forEach(opt => { 15 | console.log(` [${opt.key}] ${opt.name} (${opt.alias})`); 16 | }); 17 | console.log(' [Enter] por defecto: Edge'); 18 | } 19 | 20 | function run(browser) { 21 | console.log(`\n🚀 Abriendo "${html}" con live-server en ${browser}...\n`); 22 | execSync(`live-server ${html} --browser=${browser}`, { stdio: 'inherit' }); 23 | } 24 | 25 | function getBrowserFromKey(key) { 26 | const match = options.find(opt => 27 | opt.key === key || opt.alias.toLowerCase() === key.toLowerCase() 28 | ); 29 | return match?.browser || 'msedge'; 30 | } 31 | 32 | printMenu(); 33 | 34 | readline.emitKeypressEvents(process.stdin); 35 | process.stdin.setRawMode(true); 36 | 37 | process.stdin.on('keypress', (str, key) => { 38 | process.stdin.setRawMode(false); 39 | process.stdin.pause(); 40 | 41 | if (key.name === 'return') { 42 | run('msedge'); 43 | } else { 44 | const browser = getBrowserFromKey(str); 45 | run(browser); 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning_java", 3 | "version": "1.0.0", 4 | "description": "Learning Java", 5 | "private": true, 6 | "main": "README.md", 7 | "author": "@alxgcrz", 8 | "license": "CC-BY-4.0", 9 | "homepage": "https://alxgcrz.com/java.html", 10 | "engines": { 11 | "pandoc": "required", 12 | "mdpdf": "required", 13 | "live-server": "required" 14 | }, 15 | "config": { 16 | "html": "java.html", 17 | "pdf": "Desarrollo\\Java\\Java[ES].pdf", 18 | "public": "portfolio_v3\\public" 19 | }, 20 | "scripts": { 21 | "pandoc": "npm run pandoc:create && npm run pandoc:copy", 22 | "pandoc:create": "pandoc -d custom", 23 | "pandoc:copy": "copy %npm_package_config_html% \"%WEB_PUBLIC_FOLDER%/%npm_package_config_public%\"", 24 | "pdf": "npm run pdf:create && npm run pdf:copy", 25 | "pdf:create": "mdpdf README.md README.pdf", 26 | "pdf:copy": "copy README.pdf \"%PDF_BASE_PATH%/%npm_package_config_pdf%\"", 27 | "live": "node live.js", 28 | "live-edge": "live-server %npm_package_config_html% --browser=msedge" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "https://github.com/alxgcrz/_learning_java_.git" 33 | } 34 | } 35 | --------------------------------------------------------------------------------