├── .devcontainer └── devcontainer.json ├── .github ├── CODEOWNERS ├── FUNDING.yml └── workflows │ ├── deploy-gh-pages.yaml │ ├── language.yaml │ ├── linter.yaml │ └── stale.yml ├── .gitignore ├── .markdownlint.yaml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── book.toml ├── ferris.css ├── ferris.js ├── src ├── SUMMARY.md ├── abstract_classes.md ├── acronyms.md ├── acronyms │ ├── ambiguity.md │ ├── elaboration.md │ ├── familiarity.md │ ├── niches.md │ └── usage_contexts.md ├── arguments.md ├── arguments │ ├── aliasing.md │ ├── challenges.md │ ├── declaration.md │ ├── final_arguments.md │ ├── inferred_types.md │ ├── invocation_with_arguments.md │ ├── overloading.md │ └── reassignment.md ├── array_list.md ├── array_list │ ├── add_an_item.md │ ├── get_an_item.md │ ├── loop_over_items.md │ ├── remove_an_item.md │ ├── set_an_item.md │ ├── size.md │ └── ubiquity.md ├── arrays.md ├── arrays │ ├── access_individual_elements.md │ ├── aliasing.md │ ├── array_initializers.md │ ├── challenges.md │ ├── difference_between_initializer_and_literal.md │ ├── empty_array.md │ ├── initialization_with_new.md │ ├── initialization_with_size.md │ ├── length.md │ ├── printing_the_contents_of_an_array.md │ ├── reassignment.md │ ├── relation_to_final_variables.md │ └── set_individual_elements.md ├── arrays_ii.md ├── arrays_ii │ ├── challenges.md │ ├── default_values.md │ ├── initialization_with_size.md │ └── populate_arrays.md ├── basic_loops.md ├── boolean.md ├── boolean │ ├── and.md │ ├── challenges.md │ ├── not.md │ ├── operator_precedence.md │ └── or.md ├── boxed_primitives.md ├── boxed_primitives │ ├── arrays_of_boxed_primitives.md │ ├── boolean.md │ ├── boxing_conversion.md │ ├── challenges.md │ ├── character.md │ ├── double.md │ ├── equality.md │ ├── integer.md │ ├── primitive_types.md │ └── unboxing_conversion.md ├── branching_l.md ├── branching_logic.md ├── branching_logic │ ├── boolean_expressions.md │ ├── challenges.md │ ├── conditional_operator.md │ ├── else.md │ ├── else_if.md │ ├── if.md │ ├── nested_ifs.md │ ├── relation_to_delayed_assignment.md │ └── scoped_variables.md ├── branching_paths.md ├── branching_paths_ii.md ├── characters.md ├── characters │ ├── challenges.md │ ├── character_literals.md │ ├── common_escape_sequences.md │ ├── conversion_from_integers.md │ ├── conversion_to_integers.md │ ├── escaped_characters.md │ └── unicode.md ├── class_extension.md ├── classes.md ├── classes │ ├── aliasing.md │ ├── challenges.md │ ├── class_declaration.md │ ├── declaration.md │ ├── default_values.md │ ├── field_access.md │ ├── field_declaration.md │ ├── field_default_values.md │ ├── field_initialization.md │ ├── fields.md │ ├── instances.md │ ├── multiple_return_values.md │ ├── naming.md │ ├── naming_fields.md │ ├── new.md │ ├── null.md │ ├── primitive_classes.md │ ├── reference_classes.md │ ├── return_multiple_values.md │ ├── return_values.md │ └── the_meaning_of_the_word_class.md ├── code_is_read_more_than_written.md ├── code_is_read_more_than_written │ ├── audience.md │ ├── implications.md │ ├── information_density.md │ ├── meaning.md │ └── practice.md ├── command_line_arguments.md ├── command_line_arguments │ ├── accessing_arguments.md │ └── conventions.md ├── constructors.md ├── constructors │ ├── arguments.md │ ├── challenges.md │ ├── declaration.md │ ├── delegation.md │ ├── final_fields.md │ ├── invariants.md │ ├── multiple_constructors.md │ ├── overloads.md │ ├── the_default_constructor.md │ └── this.md ├── drawing_shapes │ └── right_triangles.md ├── encapsulation.md ├── encapsulation │ ├── abstractions.md │ ├── classes.md │ ├── implementation_details.md │ ├── implicit_interfaces.md │ ├── information_hiding.md │ ├── leaky_abstractions.md │ └── methods.md ├── enums.md ├── enums │ ├── challenges.md │ ├── comparison_to_boolean.md │ ├── declaration.md │ ├── equality.md │ ├── naming.md │ ├── switch.md │ ├── usage.md │ └── variants.md ├── exceptions.md ├── exceptions │ ├── challenges.md │ ├── exception_messages.md │ ├── messages.md │ ├── stack_traces.md │ ├── throw.md │ └── try_catch.md ├── exceptions_ii.md ├── exceptions_ii │ ├── checked_exceptions.md │ ├── exception.md │ ├── main.md │ ├── propagating_exceptions.md │ ├── rethrowing_exceptions.md │ ├── runtime_exception.md │ ├── throws.md │ └── unchecked_exceptions.md ├── fields.md ├── fields │ └── default_values.md ├── files.md ├── files │ ├── challenges.md │ ├── creating_a_folder.md │ ├── deleting_a_file.md │ ├── deleting_a_folder.md │ ├── ioexception.md │ ├── paths.md │ ├── read_from_a_file.md │ ├── uncheckedioexception.md │ └── write_to_a_file.md ├── first_steps.md ├── first_steps │ ├── challenges.md │ ├── comments.md │ ├── formatting.md │ └── semicolon.md ├── floating_point_numbers.md ├── floating_point_numbers │ ├── accuracy.md │ ├── addition.md │ ├── challenges.md │ ├── comparison.md │ ├── conversion_from_integers.md │ ├── conversion_to_integers.md │ ├── division.md │ ├── equality.md │ ├── floating_point_literals.md │ ├── limits.md │ ├── multiplication.md │ ├── nan.md │ ├── positive_and_negative_infinity.md │ ├── shorthands_for_reassignment.md │ ├── square_root.md │ └── subtraction.md ├── floating_point_numbers_ii.md ├── for.md ├── generic_growable_arrays.md ├── generic_growable_arrays │ └── arraylist.md ├── generic_hash_maps │ └── hash_map ├── generics.md ├── generics │ ├── inference.md │ ├── instantiation.md │ ├── naming.md │ ├── raw_types.md │ ├── soundness.md │ └── type_variables.md ├── getting_started.md ├── getting_started │ ├── hello_world.md │ ├── repl_1.png │ ├── repl_2.png │ ├── repl_3.png │ ├── repl_4.png │ ├── repl_4_voidmain.png │ ├── repl_5.png │ ├── repl_5_voidmain.png │ ├── repl_signup_0.png │ └── repl_signup_1.png ├── global_fields.md ├── global_fields │ ├── default_values.md │ ├── field_access.md │ ├── final_fields.md │ └── inferred_types.md ├── growable_arrays.md ├── growable_arrays │ ├── concept.md │ ├── optimized_implementation.md │ ├── performance_problems.md │ ├── performance_solutions.md │ ├── simple_implementation.md │ └── usage.md ├── hardware.md ├── hardware │ ├── cpu.md │ ├── hard_drives.md │ ├── motherboard.md │ └── ram.md ├── hash_map.md ├── hash_maps.md ├── hash_maps │ ├── buckets.md │ ├── filing_cabinets.md │ ├── function_range.md │ ├── get_items.md │ ├── growable_buckets.md │ ├── hash_collision.md │ ├── hash_distribution.md │ ├── hash_functions.md │ ├── keys_and_values.md │ ├── put_items.md │ └── redistribution.md ├── hyrums_law.md ├── hyrums_law │ ├── authority.md │ ├── emergent_properties.md │ ├── importance.md │ └── validity.md ├── identity_types.md ├── identity_types │ └── comparison_with_equalsequals.md ├── img │ ├── Agent.svg │ ├── Boxer.svg │ ├── ChezDuke.svg │ ├── NyaNya.svg │ ├── PalmTree.svg │ ├── Paper.svg │ ├── Wave.svg │ ├── armcross.webp │ ├── computer_bad.webp │ ├── does_not_compile.svg │ ├── does_not_compile_ferris.svg │ ├── duke_armcross.webp │ ├── duke_computer.webp │ ├── duke_finger.webp │ ├── eyeclose.webp │ ├── not_desired_behavior.svg │ ├── panics.svg │ └── panics_ferris.svg ├── inner_classes.md ├── inner_classes │ ├── disambiguation.md │ ├── instance_new.md │ ├── instances.md │ ├── new_operator.md │ ├── private_inner_classes.md │ ├── scope.md │ ├── static_inner_classes.md │ ├── the_anonymous_main_class.md │ └── type.md ├── instance_methods.md ├── instance_methods │ ├── aliasing.md │ ├── arguments.md │ ├── challenges.md │ ├── clarity.md │ ├── declaration.md │ ├── derived_values.md │ ├── disambiguation.md │ ├── field_access.md │ ├── field_updates.md │ ├── invocation.md │ ├── invoke_other_methods.md │ └── this.md ├── integer_ii │ └── integer_to_a_base_16_string.md ├── integers.md ├── integers │ ├── addition.md │ ├── chained_comparisons.md │ ├── challenges.md │ ├── comparison.md │ ├── division.md │ ├── equality.md │ ├── integer_literals.md │ ├── limits.md │ ├── multiplication.md │ ├── operator_precedence.md │ ├── reassignment.md │ ├── remainder.md │ ├── shorthands_for_reassignment.md │ └── subtraction.md ├── integers_ii.md ├── integers_ii │ ├── base_16_integer_literals.md │ ├── integer_from_a_base_16_string.md │ ├── integer_from_a_string.md │ ├── integer_to_a_base_16_string.md │ ├── integer_to_a_string.md │ └── underscores_in_integer_literals.md ├── interface_extension.md ├── interfaces.md ├── interfaces │ ├── fields.md │ ├── implementation.md │ ├── instances.md │ ├── interface_declaration.md │ ├── methods.md │ ├── multiple_implementations.md │ ├── naming.md │ ├── override.md │ └── subtypes.md ├── iterable_and_iterator.md ├── limits.md ├── loops.md ├── loops │ ├── break.md │ ├── challenges.md │ ├── continue.md │ ├── counting_down.md │ ├── counting_up.md │ ├── do_while.md │ ├── endless_loops.md │ ├── iterate_over_a_string.md │ ├── iteration.md │ ├── labeled_break.md │ ├── labeled_continue.md │ ├── nested_loops.md │ ├── unreachable_code.md │ └── while.md ├── loops_ii.md ├── loops_ii │ ├── break.md │ ├── challenges.md │ ├── comparison_to_while.md │ ├── continue.md │ ├── delayed_assignment.md │ ├── drawing_isosceles_triangles.md │ ├── drawing_right_triangles.md │ ├── empty_expressions.md │ ├── empty_initializers.md │ ├── empty_statements.md │ ├── final_variables.md │ ├── for.md │ ├── for_counting_up_and_down.md │ ├── for_syntax.md │ ├── i.md │ ├── inferred_types.md │ ├── iterate_over_a_string.md │ ├── iterate_over_an_array.md │ ├── labeled_break.md │ └── labeled_continue.md ├── loops_iii.md ├── loops_iii │ ├── concurrent_modifications.md │ └── for_each_loops.md ├── methods.md ├── methods │ ├── arguments.md │ ├── challenges.md │ ├── declaration.md │ ├── invocation.md │ ├── main.md │ ├── pure_functions.md │ ├── return.md │ ├── scope.md │ └── void.md ├── multi_dimensional_arrays.md ├── multi_file_programs.md ├── multi_file_programs │ ├── a_second_file.md │ ├── file_names.md │ ├── global_fields.md │ ├── the_anonymous_main_class.md │ ├── the_main_file.md │ └── the_sources_folder.md ├── multiple_files.md ├── null.md ├── null │ ├── challenges.md │ ├── checking_for_null.md │ ├── field_access.md │ ├── instance_methods.md │ ├── null_as_absence.md │ ├── null_as_unknown.md │ ├── null_pointer_exception.md │ └── null_pointerexception.md ├── numbers │ └── float_and_double.md ├── objects.md ├── objects │ ├── array_subtypes.md │ ├── equals_and_hashCode.md │ ├── instanceof.md │ ├── override.md │ ├── override_equals_and_hashCode.md │ ├── override_toString.md │ ├── recover_types.md │ ├── subclasses.md │ ├── subtypes.md │ ├── toString.md │ └── variance_and_casting.md ├── operating_systems.md ├── operating_systems │ ├── abstractions.md │ ├── defaults.md │ ├── game_consoles.md │ ├── mobile_phones.md │ ├── personal_computers.md │ └── servers.md ├── packages.md ├── packages │ ├── declaration.md │ ├── fully_qualified_class_name.md │ ├── import.md │ ├── package_private_constructors.md │ ├── package_private_fields.md │ ├── package_private_methods.md │ ├── public_classes.md │ ├── public_constructors.md │ ├── public_fields.md │ ├── public_methods.md │ ├── reverse_domain_name_notation.md │ ├── subpackages.md │ ├── the_anonymous_main_class.md │ ├── the_default_constructor.md │ ├── the_default_package.md │ └── visibility.md ├── paths.md ├── prelude.md ├── prelude │ ├── asking_for_help.md │ ├── lies.md │ └── toy_problems.md ├── primitive_types.md ├── records.md ├── records │ ├── check_for_equality.md │ ├── component_accessor_visibility.md │ ├── component_accessors.md │ ├── declaration.md │ ├── printing_a_record.md │ ├── return_multiple_values.md │ ├── shorthand.md │ ├── the_canonical_constructor.md │ └── why.md ├── recur ├── recursion.md ├── recursion │ ├── accumulators.md │ ├── base_case.md │ ├── base_cases.md │ ├── comparison_to_delegation.md │ ├── comparison_to_loops.md │ ├── counting_down.md │ ├── disclaimer.md │ ├── recursing_over_arrays.md │ └── recursing_over_strings.md ├── reflection.md ├── reflection │ ├── class_objects.md │ └── get_all_fields.md ├── return_values.md ├── return_values │ ├── challenges.md │ ├── conversion.md │ ├── declaration.md │ ├── early_return.md │ ├── exhaustiveness.md │ ├── impure_functions.md │ ├── pure_functions.md │ ├── return.md │ ├── return_in_void_methods.md │ ├── return_statement.md │ ├── return_values.md │ ├── unreachable_statements.md │ └── void.md ├── standard_input.md ├── standard_input │ ├── delayed_assignment.md │ ├── interpreting_input.md │ ├── leniency.md │ ├── prompting.md │ ├── reprompting.md │ └── transporting_data.md ├── static_fields.md ├── static_fields │ ├── constants.md │ ├── controversy.md │ ├── declaration.md │ ├── initialization.md │ ├── meaning.md │ ├── naming.md │ └── usage.md ├── static_methods.md ├── static_methods │ ├── declaration.md │ ├── factories.md │ ├── math.md │ ├── naming.md │ ├── scope.md │ └── usage.md ├── string_builder.md ├── stringbuilder.md ├── strings.md ├── strings │ ├── access_individual_characters.md │ ├── accessing_characters.md │ ├── challenges.md │ ├── characters.md │ ├── common_escape_sequences.md │ ├── concatenation.md │ ├── empty_string.md │ ├── equality.md │ ├── escaped_characters.md │ ├── length.md │ ├── multiline.md │ └── string_literals.md ├── strings_ii.md ├── strings_ii │ ├── UPPERCASE.md │ ├── challenges.md │ ├── check_if_blank.md │ ├── check_if_empty.md │ ├── equality_ignoring_case.md │ ├── lowercase.md │ └── strip_extra_whitespace.md ├── switch.md ├── switch │ ├── case_and_default.md │ ├── challenges.md │ ├── combining_cases.md │ ├── enums.md │ ├── exhaustiveness.md │ ├── ints.md │ ├── null.md │ ├── omitted_default.md │ └── strings.md ├── switch_ii.md ├── switch_ii │ ├── exhaustive_switches_with_enums.md │ ├── exhaustive_switches_with_strings.md │ ├── exhaustiveness.md │ ├── omitted_yield.md │ ├── return_a_switch.md │ └── yield.md ├── switch_iii.md ├── switch_iii │ ├── break.md │ ├── default.md │ ├── fallthrough.md │ ├── return.md │ └── yield.md ├── tcp ├── tcp_over_ip.md ├── tcp_over_ip │ ├── low_level_versus_high_level.md │ └── sockets.md ├── the_terminal.md ├── the_terminal │ ├── bash.md │ ├── changing_directories.md │ ├── chromebooks_and_school_computers.md │ ├── commands.md │ ├── creating_directories.md │ ├── creating_files.md │ ├── directories.md │ ├── getting_used_to_it.md │ ├── java_programs.md │ ├── listing_files.md │ ├── run_java_programs.md │ └── windows_subsystem_for_linux.md ├── time.md ├── time │ ├── date.md │ ├── duration.md │ ├── instant.md │ ├── local_date.md │ ├── local_date_time.md │ ├── local_time.md │ ├── offset_date_time.md │ ├── time_zones.md │ └── zoned_date_time.md ├── variables.md ├── variables │ ├── challenges.md │ ├── delayed_assignment.md │ ├── final_variables.md │ ├── inferred_types.md │ ├── naming.md │ ├── reassignment.md │ └── types.md ├── visibility.md ├── visibility │ ├── accessors.md │ ├── getter_and_setters.md │ ├── invariants.md │ ├── private.md │ ├── private_constructor.md │ ├── private_fields.md │ ├── private_methods.md │ └── the_game.md └── visibility_ii.md └── theme ├── book.js ├── css ├── chrome.css ├── general.css ├── print.css └── variables.css ├── favicon.png ├── favicon.svg ├── highlight.css ├── highlight.js └── index.hbs /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ModernJava", 3 | "image": "mcr.microsoft.com/devcontainers/universal:2", 4 | "hostRequirements": { 5 | "cpus": 1, 6 | "memory": "1gb", 7 | "storage": "2gb" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @Together-Java/moderators @Together-Java/maintainers 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: together-java 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/workflows/deploy-gh-pages.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy mdBook to GH Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-22.04 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Setup mdBook 17 | uses: peaceiris/actions-mdbook@v1.2.0 18 | with: 19 | mdbook-version: "latest" 20 | 21 | - run: mdbook build 22 | 23 | - name: Deploy 24 | uses: peaceiris/actions-gh-pages@v3.9.1 25 | if: ${{ github.ref == 'refs/heads/master' }} 26 | with: 27 | github_token: ${{ secrets.GITHUB_TOKEN }} 28 | publish_dir: ./book 29 | -------------------------------------------------------------------------------- /.github/workflows/language.yaml: -------------------------------------------------------------------------------- 1 | name: Language 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | check-language: 7 | name: "Check Language" 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: reviewdog/action-languagetool@v1 12 | with: 13 | github_token: ${{ secrets.GITHUB_TOKEN }} 14 | reporter: github-pr-review 15 | level: info 16 | enabled_categories: TYPOS 17 | -------------------------------------------------------------------------------- /.github/workflows/linter.yaml: -------------------------------------------------------------------------------- 1 | name: Linter 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | # markdown-linter: 7 | # name: "Markdown Linter" 8 | # runs-on: ubuntu-latest 9 | # steps: 10 | # - uses: actions/checkout@v2 11 | # - name: markdownlint-cli 12 | # uses: nosborn/github-action-markdown-cli@v3.2.0 13 | # with: 14 | # files: . 15 | # config_file: .markdownlint.yaml 16 | 17 | # markdown-link-check: 18 | # name: "Markdown Link Checker" 19 | # runs-on: ubuntu-latest 20 | # steps: 21 | # - uses: actions/checkout@v2 22 | # - uses: gaurav-nelson/github-action-markdown-link-check@1.0.14 23 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | # See the example config: https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml 2 | # MD013/line-length - Line length 3 | MD007: 4 | indent: 4 5 | MD013: 6 | line_length: 300 7 | MD033: 8 | allowed_elements: ["iframe", "sup"] 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to the Modern Java project 2 | 3 | First off, thank you for considering contributing to Modern Java. :tada: 4 | 5 | Modern Java is an open source project, and we love to receive contributions from our community — **you**! 6 | 7 | ## How to contribute 8 | 9 | Please head over to the [Wiki](https://github.com/Together-Java/ModernJava/wiki) and 10 | in particular check out the article 11 | [Contributing](https://github.com/Together-Java/ModernJava/wiki/Contributing) to 12 | learn more about this project and how you can make it a better place. 13 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | title = "Modern Java" 3 | description = "Book teaching how to write modern and effective Java." 4 | authors = ["Ethan McCue", "Together Java", "Contributions from the Java Community"] 5 | language = "en" 6 | 7 | [output.html] 8 | git-repository-url = "https://github.com/Together-Java/ModernJava" 9 | edit-url-template = "https://github.com/Together-Java/ModernJava/edit/develop/{path}" 10 | mathjax-support = true 11 | additional-css = ["ferris.css"] 12 | additional-js = ["ferris.js"] 13 | 14 | [output.html.fold] 15 | enable = true # whether or not to enable section folding 16 | level = 0 # the depth to start folding 17 | 18 | [output.html.playground] 19 | editable = true 20 | 21 | [output.html.code.hidelines] 22 | java = "~" 23 | -------------------------------------------------------------------------------- /src/abstract_classes.md: -------------------------------------------------------------------------------- 1 | # Abstract Classes 2 | -------------------------------------------------------------------------------- /src/acronyms.md: -------------------------------------------------------------------------------- 1 | # Acronyms 2 | 3 | In the 1940s, Franklin Delano Rosevelt -------------------------------------------------------------------------------- /src/acronyms/ambiguity.md: -------------------------------------------------------------------------------- 1 | # Ambiguity 2 | -------------------------------------------------------------------------------- /src/acronyms/elaboration.md: -------------------------------------------------------------------------------- 1 | # Elaboration 2 | -------------------------------------------------------------------------------- /src/acronyms/familiarity.md: -------------------------------------------------------------------------------- 1 | # Familiarity 2 | -------------------------------------------------------------------------------- /src/acronyms/niches.md: -------------------------------------------------------------------------------- 1 | # Niches 2 | -------------------------------------------------------------------------------- /src/acronyms/usage_contexts.md: -------------------------------------------------------------------------------- 1 | # Usage Contexts 2 | -------------------------------------------------------------------------------- /src/arguments.md: -------------------------------------------------------------------------------- 1 | # Arguments 2 | 3 | If methods always had to do the same thing each time they were run, they wouldn't be that useful. 4 | 5 | The way to customize what happens when a method is called is to have them take "arguments." 6 | 7 | ```java 8 | void sayHello(String name) { 9 | System.out.println("Hello " + name + "!"); 10 | } 11 | 12 | void main() { 13 | // Hello Joshua! 14 | sayHello("Joshua"); 15 | // Hello Claire! 16 | sayHello("Claire"); 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /src/arguments/aliasing.md: -------------------------------------------------------------------------------- 1 | # Aliasing 2 | 3 | Because arguments work like variables, if you pass something 4 | like an array as an argument the array referenced by the argument will be the exact same as the array referenced by the variable given to the method. 5 | 6 | ```java 7 | void incrementFirst(int[] numbers) { 8 | numbers[0] = numbers[0] + 1; 9 | } 10 | 11 | void main() { 12 | int[] nums = new int[] { 8 }; 13 | 14 | // The first number is 8 15 | System.out.println( 16 | "The first number is " + nums[0] 17 | ); 18 | 19 | incrementFirst(nums); 20 | 21 | // Now it is 9 22 | System.out.println( 23 | "Now it is " + nums[0] 24 | ); 25 | } 26 | ``` 27 | 28 | The argument aliases the value passed to the method. 29 | -------------------------------------------------------------------------------- /src/arguments/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | To declare a method which takes arguments, instead of putting `()` after the method name 4 | you need to put a comma separated list of argument declarations. 5 | 6 | Each argument declaration looks the same as a variable declaration and has both a type and a name. 7 | 8 | ```java,no_run 9 | // This declares a single argument named "food" that 10 | // has a type of "String". 11 | void eat(String food) { 12 | System.out.println("I ate " + food); 13 | } 14 | 15 | // This declares two arguments 16 | // "to", which is a String and 17 | // "age", which is an int. 18 | void happyBirthday(String to, int age) { 19 | System.out.println( 20 | "Happy " + age + "th birthday " + to + "!" 21 | ); 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /src/arguments/inferred_types.md: -------------------------------------------------------------------------------- 1 | # Inferred Types 2 | 3 | With variable declarations, you can use `var` to let Java figure out the type 4 | of the variable. 5 | 6 | ```java,no_run 7 | var name = "Jupiter"; 8 | ``` 9 | 10 | This is _not_ allowed with argument declarations. 11 | 12 | ```java,does_not_compile,no_run 13 | // You aren't allowed to use var for arguments! 14 | void makeHorchata(var milkFatPercent) { 15 | // ... 16 | } 17 | ``` 18 | 19 | You must always explicitly write out the types of arguments. 20 | 21 | ```java,no_run 22 | void makeHorchata(double milkFatPercent) { 23 | System.out.println( 24 | "Making a horchata with " + milkFatPercent + "% milk." 25 | ); 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /src/array_list.md: -------------------------------------------------------------------------------- 1 | # ArrayList 2 | 3 | Java comes with a generic growable array. It is called 4 | an `ArrayList`. 5 | 6 | ```java 7 | import java.util.ArrayList; 8 | 9 | void main() { 10 | ArrayList names = new ArrayList<>(); 11 | names.add("John Wick"); 12 | 13 | System.out.println(names); 14 | } 15 | ``` -------------------------------------------------------------------------------- /src/array_list/add_an_item.md: -------------------------------------------------------------------------------- 1 | # Add an item 2 | 3 | To add an item to an `ArrayList` you use the `.add` 4 | method. 5 | 6 | ```java 7 | import java.util.ArrayList; 8 | 9 | void main() { 10 | ArrayList names = new ArrayList<>(); 11 | names.add("The Bowery King"); 12 | names.add("Caine"); 13 | 14 | System.out.println(names); 15 | } 16 | ``` 17 | 18 | The way this works is conceptually the 19 | same as the growable array that we went over earlier. 20 | 21 | All you need to know though is that you can add 22 | as many items as you will and the container will grow 23 | dynamically. 24 | -------------------------------------------------------------------------------- /src/array_list/get_an_item.md: -------------------------------------------------------------------------------- 1 | # Get an item 2 | 3 | To get an item at a given index in an `ArrayList` 4 | you should use `.get` 5 | 6 | ```java 7 | import java.util.ArrayList; 8 | 9 | void main() { 10 | ArrayList names = new ArrayList<>(); 11 | names.add("Winston Scott"); 12 | 13 | String name = names.get(0); 14 | System.out.println(name); 15 | } 16 | ``` 17 | 18 | If the index you picked is greater than the number of elements in the `ArrayList` 19 | it will throw an `IndexOutOfBoundsException` 20 | 21 | ```java,panics 22 | import java.util.ArrayList; 23 | 24 | void main() { 25 | ArrayList names = new ArrayList<>(); 26 | names.add("Killa Harkan"); 27 | 28 | String name = names.get(10); 29 | System.out.println(name); 30 | } 31 | ``` -------------------------------------------------------------------------------- /src/array_list/loop_over_items.md: -------------------------------------------------------------------------------- 1 | # Loop over Contents 2 | 3 | Just like the `.length` and `[]` operations on arrays, 4 | you can loop over all the elements in an `ArrayList` 5 | with the combination of `.size()` and `.get(idx)` 6 | 7 | ```java 8 | import java.util.ArrayList; 9 | 10 | void main() { 11 | ArrayList names = new ArrayList<>(); 12 | names.add("Sofia Al-Azwar"); 13 | names.add("Viggo Tarasov"); 14 | names.add("Iosef Tarasov"); 15 | 16 | for (int i = 0; i < names.size(); i++) { 17 | String name = names.get(i); 18 | 19 | System.out.println("NAME: " + name); 20 | } 21 | } 22 | ``` 23 | 24 | Its not a rule, but this is also a convenient use of for loops. 25 | You can use all the same tricks you learned when looping over arrays here. -------------------------------------------------------------------------------- /src/array_list/set_an_item.md: -------------------------------------------------------------------------------- 1 | # Set an item 2 | 3 | You can set an item at an index with `.set` 4 | 5 | ```java 6 | import java.util.ArrayList; 7 | 8 | void main() { 9 | ArrayList names = new ArrayList<>(); 10 | names.add("John Wick"); 11 | 12 | names.set(0, "Baba Yaga"); 13 | 14 | System.out.println(names); 15 | System.out.println(names.get(0)); 16 | } 17 | ``` 18 | 19 | If the index you provide is out of bounds, you will get an `IndexOutOfBoundsException`. 20 | 21 | ```java,panics 22 | import java.util.ArrayList; 23 | 24 | void main() { 25 | ArrayList names = new ArrayList<>(); 26 | names.add("John Wick"); 27 | 28 | names.set(15, "Baba Yaga"); 29 | } 30 | ``` -------------------------------------------------------------------------------- /src/array_list/size.md: -------------------------------------------------------------------------------- 1 | # Size 2 | 3 | The you can access the number of elements in an 4 | `ArrayList` with the `.size()` method. 5 | 6 | ```java 7 | import java.util.ArrayList; 8 | 9 | void main() { 10 | ArrayList names = new ArrayList<>(); 11 | 12 | System.out.println(names.size()); 13 | 14 | names.add("Vincent Bisset de Gramont"); 15 | System.out.println(names.size()); 16 | 17 | names.add("Mr. Nobody"); 18 | System.out.println(names.size()); 19 | } 20 | ``` 21 | 22 | This will tell you the number of elements in the `ArrayList` but 23 | not the amount of space allocated by the underlying array. 24 | 25 | This is fine because, if you aren't the one making a growable array, 26 | it doesn't matter. All you need to concern yourself with is what is actually 27 | there, not any book keeping. -------------------------------------------------------------------------------- /src/array_list/ubiquity.md: -------------------------------------------------------------------------------- 1 | # Ubiquity 2 | 3 | Java comes with many classes. Some of these 4 | you might use a few times (like `LocalTime`), some you 5 | will see every day of your coding life (like `String`). 6 | 7 | `ArrayList` is in the second category. It turns out 8 | that a growable list of things is needed for a lot 9 | of different tasks. It is ubiquitous in code that 10 | you will see in the real world. 11 | 12 | I mention this mostly to make sure you are paying attention. 13 | Its not particuarly hard, but try not to zone out on these sorts 14 | of chapters. -------------------------------------------------------------------------------- /src/arrays.md: -------------------------------------------------------------------------------- 1 | # Arrays 2 | 3 | Arrays are used to represent a fixed-size collection of things. 4 | 5 | ```java,no_run 6 | int[] oddNumbers = { 1, 3, 5, 7, 9 }; 7 | ``` 8 | 9 | Fixed-size means that once an array is made, it will always hold the same 10 | number of things. 11 | 12 | We call the things stored in an array its "elements." 13 | 14 | You can make an array of any type of element by using the name of the type followed by 15 | `[]`. 16 | 17 | ```java,no_run 18 | char[] letters = { 'a', 'b', 'c' }; 19 | String[] words = { "its", "as", "easy", "as" } 20 | int[] numbers = { 1, 2, 3 }; 21 | double[] doubles = { 97.0, 98.0, 99.0, 1.0, 2.0, 3.0 }; 22 | ``` 23 | -------------------------------------------------------------------------------- /src/arrays/array_initializers.md: -------------------------------------------------------------------------------- 1 | # Array Initializers 2 | 3 | To give an initial value to an array you can use an array initializer. 4 | 5 | After the equals sign you write `{` followed by a comma separated list of elements and a final `}`. 6 | 7 | ```java,no_run 8 | int[] numbers = { 1, 2, 3 }; 9 | // |---------| 10 | // this part is 11 | // the initializer 12 | ``` 13 | 14 | The elements in an initializer do not have to be literals and can also be variables or expressions. 15 | 16 | ```java,no_run 17 | int two = 2; 18 | // Will hold 1, 2, 3 just like the array above 19 | int[] numbers = { 1, two, two + 1 } 20 | ``` 21 | 22 | We call them array initializers because you use them to give an initial value to an array.[^pattern] 23 | 24 | [^pattern]: You may be noticing a pattern. Confusing sounding names are often kinda "obvious" with enough context. 25 | -------------------------------------------------------------------------------- /src/arrays/empty_array.md: -------------------------------------------------------------------------------- 1 | # Empty Array 2 | 3 | If you use an array initializer that has no elements between the `{` and `}` 4 | you can create an empty array. 5 | 6 | ```java,no_run 7 | char[] emptyCharArray = {}; 8 | ``` 9 | 10 | An empty array is very similar to an empty `String`. It has a length of 0, it has no elements, 11 | and it is generally useful only as a placeholder value for when you have no data yet but will 12 | be able to reassign the variable holding it when you get some. 13 | 14 | ```java,panics 15 | ~void main() { 16 | char[] emptyCharArray = {}; 17 | 18 | // 0 19 | System.out.println(emptyCharArray.length); 20 | 21 | // Crash 22 | System.out.println(emptyCharArray[0]); 23 | ~} 24 | ``` -------------------------------------------------------------------------------- /src/arrays/initialization_with_size.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/arrays/initialization_with_size.md -------------------------------------------------------------------------------- /src/arrays/length.md: -------------------------------------------------------------------------------- 1 | # Length 2 | 3 | The number of elements which comprise an array can be accessed by using `.length`.[^unlike_string] 4 | 5 | ```java 6 | ~void main() { 7 | String[] veggies = { "brussels", "cabbage", "carrots" }; 8 | int numberOfElements = veggies.length; 9 | 10 | // veggies is 3 elements long 11 | System.out.println( 12 | "veggies is " + numberOfElements + " characters long" 13 | ); 14 | ~} 15 | ``` 16 | 17 | [^unlike_string]: Unlike with a `String`, you do not write `()` after `.length`. 18 | -------------------------------------------------------------------------------- /src/arrays/relation_to_final_variables.md: -------------------------------------------------------------------------------- 1 | # Relation to Final Variables 2 | 3 | Just like anything else, arrays can be stored in variables marked `final`. 4 | 5 | This means that the variable cannot be reassigned, but it does not mean 6 | that the array's contents cannot be changed directly or through an alias. 7 | 8 | ```java 9 | ~void main() { 10 | final char[] catchphrase = { 'w', 'o', 'a', 'h', '!' }; 11 | // woah! 12 | System.out.println(catchphrase); 13 | 14 | // Cannot reassign 15 | // catchphrase = { 'e', 'g', 'a', 'd', 's' } 16 | // but can set elements directly 17 | catchphrase[0] = 'e'; 18 | catchphrase[1] = 'g'; 19 | 20 | // or through an alias 21 | char[] alias = catchphrase; 22 | alias[2] = 'a'; 23 | alias[3] = 'd'; 24 | alias[4] = 's'; 25 | 26 | // egads 27 | System.out.println(catchphrase); 28 | ~} 29 | ``` 30 | -------------------------------------------------------------------------------- /src/arrays_ii.md: -------------------------------------------------------------------------------- 1 | # Arrays II 2 | 3 | Fairly often you will want to have arrays in your program 4 | which you either do not know the initial values for or which 5 | are too big to physically type out every value in an initializer. 6 | 7 | ```java,no_run 8 | String[] everyStudentName = // ??? 9 | char[] everyLetterInEveryAlphabet = // ??? 10 | ``` -------------------------------------------------------------------------------- /src/arrays_ii/initialization_with_size.md: -------------------------------------------------------------------------------- 1 | # Initializion with Size 2 | 3 | The Nintendo GameBoy had a screen resolution of 160 x 144. 4 | To store the value of each pixel[^bw] you would need an array 23,040 items 5 | long. 6 | 7 | To support this without you writing the word `false` 23,040 times, 8 | arrays can be made with just by giving a size and skipping the initializer. 9 | 10 | ```java,no_run 11 | boolean[] pixels = new boolean[23040]; 12 | ``` 13 | 14 | So you have to say `new` followed by the type of element in the array, `[`, the size of the array and `]`. 15 | 16 | 17 | [^bw]: The original GameBoy wasn't actually just black and white. It supported 7 shades of gray, so a `boolean` wouldn't technically to be enough to represent a pixel's state. You'd have to use something with at least 8 states, not just 2. 18 | -------------------------------------------------------------------------------- /src/arrays_ii/populate_arrays.md: -------------------------------------------------------------------------------- 1 | # Populate Arrays 2 | 3 | If the default value for an array is not valid for what you are doing, 4 | you will need to populate the array with better initial values. 5 | 6 | For loops are generally good for this purpose. 7 | 8 | ```java 9 | ~void main() { 10 | char[] letters = new char[26]; 11 | for (int i = 0; i < letters.length; i++) { 12 | letters[i] = (char) ('a' + i); 13 | } 14 | System.out.println(letters); 15 | ~} 16 | ``` 17 | -------------------------------------------------------------------------------- /src/basic_loops.md: -------------------------------------------------------------------------------- 1 | # Basic Loops 2 | -------------------------------------------------------------------------------- /src/boolean.md: -------------------------------------------------------------------------------- 1 | # Booleans 2 | 3 | A `boolean` is either `true` or `false`. 4 | 5 | ```java,no_run 6 | boolean onFleek = true; 7 | boolean badVibes = false; 8 | ``` 9 | 10 | This is used to represent situations where there are exactly two possible states. 11 | -------------------------------------------------------------------------------- /src/boolean/not.md: -------------------------------------------------------------------------------- 1 | # Not 2 | 3 | Booleans can also be "negated" using the "not" operator - `!`. 4 | 5 | ```java,no_run 6 | boolean haveOreosInHouse = true; 7 | boolean stuckToCalorieLimit = !haveOreos; 8 | ``` 9 | 10 | So in this case, I have stuck to my calorie limit if there are _not_ Oreos in the house. 11 | 12 | | haveOreosInHouse | stuckToCalorieLimit | 13 | | ---------------- | ------------------- | 14 | | false | true | 15 | | true | false | 16 | -------------------------------------------------------------------------------- /src/boxed_primitives/boolean.md: -------------------------------------------------------------------------------- 1 | # Boolean 2 | 3 | 4 | The type to use for a `boolean` that might be null is `Boolean`. 5 | 6 | ```java 7 | ~void main() { 8 | Boolean b = null; 9 | System.out.println(b); 10 | b = true; 11 | System.out.println(true); 12 | ~} -------------------------------------------------------------------------------- /src/boxed_primitives/boxing_conversion.md: -------------------------------------------------------------------------------- 1 | # Boxing Conversion 2 | 3 | If you try to assign to a boxed type like `Integer` from some 4 | code that gives you the unboxed version like `int`, then Java will 5 | automatically do that conversion.[^obvious] 6 | 7 | ```java 8 | ~void main() { 9 | int x = 5; 10 | Integer y = x; 11 | 12 | System.out.println(x); 13 | System.out.println(y); 14 | ~} 15 | ``` 16 | 17 | [^obvious]: This might feel obvious, but this is one of the few places in Java where the type of something "magically" changes. `int` and `Integer`, `char` and `Character`, etc. *are* different types. -------------------------------------------------------------------------------- /src/boxed_primitives/character.md: -------------------------------------------------------------------------------- 1 | # Character 2 | 3 | The type to use for a `char` that might be null is `Character`. 4 | 5 | ```java 6 | ~void main() { 7 | Character c = null; 8 | System.out.println(c); 9 | c = '%'; 10 | System.out.println(c); 11 | ~} 12 | ``` 13 | 14 | Unlike a `char[]`, a `Character[]` will not be have its contents 15 | shown when printed. 16 | 17 | ```java 18 | ~void main() { 19 | char[] c1 = new char[] { 'a', 'b', 'c' }; 20 | System.out.println(c1); 21 | 22 | Character[] c2 = new Character[] { 'a', 'b', 'c' }; 23 | System.out.println(c2); 24 | ~} 25 | ``` -------------------------------------------------------------------------------- /src/boxed_primitives/double.md: -------------------------------------------------------------------------------- 1 | # Double 2 | 3 | The type to use for a `double` that might be null is `Double`. 4 | 5 | ```java 6 | ~void main() { 7 | Double d = null; 8 | System.out.println(d); 9 | d = 3.14; 10 | System.out.println(d); 11 | ~} 12 | ``` 13 | 14 | If you try to do any math on a `Double` which holds `null` you will 15 | get a `NullPointerException`. 16 | 17 | ```java,panics 18 | ~void main() { 19 | Double d = null; 20 | System.out.println(d + 1); 21 | ~} 22 | ``` -------------------------------------------------------------------------------- /src/boxed_primitives/equality.md: -------------------------------------------------------------------------------- 1 | # Equality 2 | -------------------------------------------------------------------------------- /src/boxed_primitives/integer.md: -------------------------------------------------------------------------------- 1 | # Integer 2 | 3 | The type to use for an `int` that might be null is `Integer`. 4 | 5 | ```java 6 | ~void main() { 7 | Integer i = null; 8 | System.out.println(i); 9 | i = 5; 10 | System.out.println(i); 11 | ~} 12 | ``` 13 | 14 | If you try to do any math on an `Integer` which holds `null` you will 15 | get a `NullPointerException`. 16 | 17 | ```java,panics 18 | ~void main() { 19 | Integer i = null; 20 | System.out.println(i * 5); 21 | ~} 22 | ``` -------------------------------------------------------------------------------- /src/boxed_primitives/primitive_types.md: -------------------------------------------------------------------------------- 1 | # Primitive Types 2 | -------------------------------------------------------------------------------- /src/boxed_primitives/unboxing_conversion.md: -------------------------------------------------------------------------------- 1 | # Unboxing Conversion 2 | 3 | If you try to use a boxed primitive in a context where 4 | the normal type is expected, it will be implicitly "unboxed." 5 | 6 | This means you can use `Integer`s directly in math expressions. 7 | 8 | ```java 9 | ~void main() { 10 | Integer x = 5; 11 | int y = 3; 12 | int z = x * y; 13 | 14 | System.out.println(z); 15 | ~} 16 | ``` 17 | 18 | As well as `Boolean`s in logical expressions. 19 | 20 | ```java 21 | ~void main() { 22 | Boolean hasHat = true; 23 | if (hasHat) { 24 | System.out.println("You have a hat!"); 25 | } 26 | ~} 27 | ``` 28 | 29 | And so on for `Double`, `Character`, etc. 30 | 31 | But if you use one of these types like this and they happen to be `null` you will 32 | get a `NullPointerException`. 33 | 34 | ```java,panics 35 | ~void main() { 36 | Integer x = null; 37 | // Bool 38 | int y = x; 39 | ~} 40 | ``` -------------------------------------------------------------------------------- /src/branching_l.md: -------------------------------------------------------------------------------- 1 | # Branching Logic 2 | -------------------------------------------------------------------------------- /src/branching_logic.md: -------------------------------------------------------------------------------- 1 | # Branching Logic 2 | 3 | In all the code shown so far, execution has gone from the top of the program to 4 | the bottom. 5 | -------------------------------------------------------------------------------- /src/branching_logic/boolean_expressions.md: -------------------------------------------------------------------------------- 1 | # Boolean Expressions 2 | 3 | A common thing I've seen students do is set the initial value of some 4 | `boolean` variable based on some condition. 5 | 6 | ```java 7 | ~void main() { 8 | int age = 22; 9 | 10 | boolean canRent; 11 | if (age > 25) { 12 | canRent = true; 13 | } 14 | else { 15 | canRent = false; 16 | } 17 | 18 | // or 19 | // boolean canRent = age > 25 ? true : false; 20 | 21 | System.out.println(canRent); 22 | ~} 23 | ``` 24 | 25 | This is valid code, but very often can be made simpler if you remember that the condition 26 | itself already evaluates to a `boolean`. You can directly assign the variable to that value. 27 | 28 | ```java 29 | ~void main() { 30 | int age = 22; 31 | boolean canRent = age > 25; 32 | 33 | System.out.println(canRent); 34 | ~} 35 | ``` 36 | -------------------------------------------------------------------------------- /src/branching_logic/conditional_operator.md: -------------------------------------------------------------------------------- 1 | # Conditional Operator 2 | 3 | When the only operation being performed inside of an `if` and `else` pair 4 | is setting the initial value of a variable, you can use the "conditional operator"[^ternary] 5 | to perform that assignment instead. 6 | 7 | ```java 8 | ~void main() { 9 | int age = 22; 10 | 11 | String message = age < 25 12 | ? "You cannot rent a car!" 13 | : "You might be able to rent a car"; 14 | 15 | System.out.println(message); 16 | ~} 17 | ``` 18 | 19 | You write a condition followed by a `?`, a value to use when that condition evaluates to `true`, a `:`, 20 | and then a value to use when that condition evaluates to `false`. 21 | 22 | ```java,no_run 23 | CONDITION ? WHEN_TRUE : WHEN_FALSE 24 | ``` 25 | 26 | [^ternary]: Some people will call this a ternary expression. Ternary meaning "three things." Same idea as tres leches. 27 | -------------------------------------------------------------------------------- /src/branching_logic/nested_ifs.md: -------------------------------------------------------------------------------- 1 | # Nested Ifs 2 | 3 | The code inside of the `{` and `}` can be anything, including more `if` statments. 4 | 5 | ```java 6 | ~void main() { 7 | int age = 5; // 👶 8 | if (age < 25) { 9 | System.out.println("You are too young to rent a car!"); 10 | if (age == 24) { 11 | System.out.println("(but it was close)"); 12 | } 13 | } 14 | ~} 15 | ``` 16 | 17 | When an `if` is inside another `if` we say that it is "nested". 18 | 19 | If you find yourself nesting more than a few `if`s that might be a sign that 20 | you should reach out for help. 21 | 22 | ```java,no_run 23 | if (...) { 24 | if (...) { 25 | if (...) { 26 | if (...) { 27 | // Seek professional help 28 | } 29 | } 30 | } 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /src/branching_paths.md: -------------------------------------------------------------------------------- 1 | # Branching Paths 2 | 3 | All the code I have shown you so far has run from top to bottom. That is, it has followed a single "path." 4 | 5 | Not all programs can follow a single path though. 6 | 7 | Imagine trying to rent a car online. The first thing you might be asked is your age. 8 | This is because most car rental companies do not want to rent to people under the age of 25.[^insurance]. 9 | 10 | If you enter an age that is less than 25, the program should immediately tell you that you cannot 11 | rent a car. If you enter an age that is greater than or equal to 25, the program should continue to prompt you 12 | for more information. 13 | 14 | There are multiple "branching paths" that the program might take. 15 | 16 | [^insurance]: For insurance reasons. 17 | -------------------------------------------------------------------------------- /src/branching_paths_ii.md: -------------------------------------------------------------------------------- 1 | # Branching Paths II 2 | 3 | -------------------------------------------------------------------------------- /src/characters.md: -------------------------------------------------------------------------------- 1 | # Characters 2 | 3 | A character, represented by the data type `char`, is a single 4 | letter or symbol. 5 | 6 | ```java,no_run 7 | char letter = 'a'; 8 | ``` 9 | 10 | I choose to pronounce it like the "char" in "Charmander." 11 | -------------------------------------------------------------------------------- /src/characters/character_literals.md: -------------------------------------------------------------------------------- 1 | # Character Literals 2 | 3 | In order to write a character in a program, you write that one character surrounded 4 | by single quotes. 5 | 6 | ```java,no_run 7 | 'a' 8 | ``` 9 | 10 | This is called a "character literal." It has the same relationship to `char` that an integer literal like 123 has to `int`. 11 | 12 | ```java,no_run 13 | // Same as this "integer literal" is used to write a number 14 | int sesameStreet = 123; 15 | // A "character literal" is used to write text 16 | char thisEpisodeIsBroughtToYouBy = 'c'; 17 | ``` 18 | -------------------------------------------------------------------------------- /src/characters/common_escape_sequences.md: -------------------------------------------------------------------------------- 1 | # Common Escape Sequences 2 | 3 | While most characters can be written directly into a program, as is the 4 | case for `a`, `b`, or `t`, there are some which cannot. 5 | 6 | For these, you need to use what is called an "escape sequence." 7 | 8 | The most common escape sequence you will use will be the one for a "new line." 9 | Which is a backslash followed by an `n`. 10 | 11 | ```java,no_run 12 | char newline = '\n'; 13 | ``` 14 | 15 | Because a backslash is used for this special syntax, to put a backslash into a character literal 16 | you need to escape it with a backslash of its own. 17 | 18 | ```java,no_run 19 | char backslash = '\\'; 20 | ``` 21 | 22 | And because single quotes are used to mark the start and end of a character literal, they need to be escaped 23 | as well. 24 | 25 | ```java,no_run 26 | char singleQuote = '\''; 27 | ``` 28 | -------------------------------------------------------------------------------- /src/characters/conversion_from_integers.md: -------------------------------------------------------------------------------- 1 | # Conversion from Integers 2 | 3 | An `int` can represent more values than a `char`, so conversion from `int` to 4 | `char` requires the use of the cast operator `(char)`. 5 | 6 | ```java 7 | ~void main() { 8 | int x = 120; 9 | 10 | char xAsChar = (char) x; 11 | 12 | System.out.println(xAsChar); 13 | ~} 14 | ``` 15 | 16 | This conversion is narrowing, so information might be lost if the `int` value is too big or too small to fit into a `char`. 17 | 18 | The initial value of a `char` can also be given by an integer literal if the integer literal represents a small enough letter. 19 | 20 | ```java 21 | ~void main() { 22 | char z = 122; 23 | 24 | System.out.println(z); 25 | ~} 26 | ``` 27 | -------------------------------------------------------------------------------- /src/characters/escaped_characters.md: -------------------------------------------------------------------------------- 1 | # Escaped Characters 2 | -------------------------------------------------------------------------------- /src/class_extension.md: -------------------------------------------------------------------------------- 1 | # Class Extension 2 | -------------------------------------------------------------------------------- /src/classes.md: -------------------------------------------------------------------------------- 1 | # Classes 2 | 3 | Up until now all the data types you have used - `int`, `String`, etc. - 4 | came with Java. This works for awhile, but eventually you will need to define your own types. 5 | 6 | The way to do this is with a "class." 7 | 8 | ```java 9 | class Person { 10 | 11 | } 12 | ``` -------------------------------------------------------------------------------- /src/classes/aliasing.md: -------------------------------------------------------------------------------- 1 | # Aliasing 2 | 3 | 4 | When two variables point to the same instance of a class, those variables will be 5 | aliases for the same data. 6 | 7 | This means that, just like arrays, if you change the value of a field on one that change 8 | will be visible on the other. 9 | 10 | ```java 11 | class Muppet { 12 | String name; 13 | } 14 | 15 | void main() { 16 | Muppet kermit = new Muppet(); 17 | Muppet darkKermit = kermit; 18 | 19 | kermit.name = "Kermit The Frog"; 20 | 21 | // Kermit The Frog 22 | System.out.println(kermit.name); 23 | // Kermit The Frog 24 | System.out.println(darkKermit.name); 25 | } 26 | ``` -------------------------------------------------------------------------------- /src/classes/class_declaration.md: -------------------------------------------------------------------------------- 1 | # Class Declaration 2 | 3 | To declare a class, you say `class` followed by a name for the class and a pair of `{` and `}` 4 | 5 | ```java 6 | class Muppet { 7 | 8 | } 9 | ``` -------------------------------------------------------------------------------- /src/classes/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | To declare a class, you write the word `class` followed by a name for the class. 4 | 5 | You shoul 6 | -------------------------------------------------------------------------------- /src/classes/default_values.md: -------------------------------------------------------------------------------- 1 | # Default Values 2 | -------------------------------------------------------------------------------- /src/classes/field_access.md: -------------------------------------------------------------------------------- 1 | # Field Access 2 | 3 | You can access the value of any field on a class by writing the name of a variable holding an instance 4 | of that class, `.`, then the name of that field. 5 | 6 | ```java 7 | class Muppet { 8 | String name; 9 | } 10 | 11 | void main() { 12 | Muppet kermit = new Muppet(); 13 | kermit.name = "Kermit The Frog"; 14 | 15 | // The .name accesses the "name" field 16 | System.out.println(kermit.name); 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /src/classes/field_declaration.md: -------------------------------------------------------------------------------- 1 | # Field Declaration 2 | -------------------------------------------------------------------------------- /src/classes/field_default_values.md: -------------------------------------------------------------------------------- 1 | # Field Default Values 2 | 3 | Before a field in a class is given a value it will have the same default value as it would 4 | if you made an array of the field's type. 5 | 6 | That is: `0` for `int`, `0.0` for `double`, `false` for `boolean`, and `null` for most all else. 7 | 8 | ```java 9 | class Muppet { 10 | int age; 11 | double salary; 12 | boolean talented; 13 | String name; 14 | } 15 | 16 | void main() { 17 | Muppet kermit = new Muppet(); 18 | 19 | // 0 20 | System.out.println(kermit.age); 21 | // 0.0 22 | System.out.println(kermit.salary); 23 | // false 24 | System.out.println(kermit.talented); 25 | // null 26 | System.out.println(kermit.name); 27 | } 28 | ``` -------------------------------------------------------------------------------- /src/classes/field_initialization.md: -------------------------------------------------------------------------------- 1 | # Field Initialization 2 | 3 | You can set an initial value for a field in a few ways. 4 | 5 | One is to access to assign the field directly on the instance created. 6 | 7 | ```java 8 | class Muppet { 9 | String name; 10 | } 11 | 12 | void main() { 13 | Muppet kermit = new Muppet(); 14 | kermit.name = "Kermit The Frog"; 15 | } 16 | ``` 17 | 18 | Another is to set a default value directly in the field declaration. This makes the most sense 19 | if its a value that most instances will share. 20 | 21 | ```java 22 | class Muppet { 23 | // Most are! 24 | boolean talented = true; 25 | } 26 | 27 | void main() { 28 | Muppet kermit = new Muppet(); 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /src/classes/fields.md: -------------------------------------------------------------------------------- 1 | # Fields 2 | 3 | Classes contain zero or more fields. 4 | 5 | Fields are like variables except they don't live in a method, 6 | they are attached to instances of the class they are a part of. 7 | 8 | To declare a field in a class you say the type of the field, a name for the field, 9 | and then a `;`. 10 | 11 | ```java 12 | class Muppet { 13 | String name; 14 | } 15 | ``` 16 | 17 | One way to think about it is that when you say `new Muppet()`, Java makes a box big enough to hold 18 | all of the fields that a muppet needs.[^box] 19 | 20 | [^box]: This "box" metaphor is part of where the name "boxed primitives" comes from. 21 | -------------------------------------------------------------------------------- /src/classes/instances.md: -------------------------------------------------------------------------------- 1 | # Instances 2 | 3 | Once you've declared a class, you can make an instance 4 | of that class by saying `new` followed by that class's name 5 | and `()`.[^var] 6 | 7 | ```java 8 | class Muppet { 9 | 10 | } 11 | 12 | void main() { 13 | Muppet kermit = new Muppet(); 14 | System.out.println(kermit); 15 | } 16 | ``` 17 | 18 | Very similarly to arrays, the output from printing an instance of a class might seem like gibberish (`Main$Muppet@1be6f5c3`). 19 | You will learn how to make it nicer later. 20 | 21 | [^var]: I haven't used it in many code samples thus far, but if you remember `var` this is one of the times 22 | where it can be aesthetically convenient. `var kermit = new Muppet();` 23 | -------------------------------------------------------------------------------- /src/classes/multiple_return_values.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/classes/multiple_return_values.md -------------------------------------------------------------------------------- /src/classes/naming.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | It is social convention to name classes with the first letter of each word capitalized. So if you wanted to 4 | make a class representing an inch worm, you would say the following.[^fuzzy] 5 | 6 | ```java 7 | class InchWorm { 8 | 9 | } 10 | ``` 11 | 12 | [^fuzzy]: For things that are not English or are acronyms the rules get fuzzy. Use your best judgement. -------------------------------------------------------------------------------- /src/classes/naming_fields.md: -------------------------------------------------------------------------------- 1 | # Naming Fields 2 | 3 | Fields are generally named `camelCase`, the same as local variables.[^break] 4 | 5 | ```java 6 | class Example { 7 | int x; 8 | String name; 9 | int[] timesOfRacers; 10 | String[] namesOfClowns; 11 | } 12 | ``` 13 | 14 | [^break]: If you break a social rule, something Bad happens. 15 | -------------------------------------------------------------------------------- /src/classes/new.md: -------------------------------------------------------------------------------- 1 | # new 2 | -------------------------------------------------------------------------------- /src/classes/null.md: -------------------------------------------------------------------------------- 1 | # null 2 | -------------------------------------------------------------------------------- /src/classes/primitive_classes.md: -------------------------------------------------------------------------------- 1 | # Primitive Classes 2 | -------------------------------------------------------------------------------- /src/classes/reference_classes.md: -------------------------------------------------------------------------------- 1 | # Reference Classes 2 | -------------------------------------------------------------------------------- /src/classes/return_values.md: -------------------------------------------------------------------------------- 1 | # Return Multiple Values 2 | -------------------------------------------------------------------------------- /src/classes/the_meaning_of_the_word_class.md: -------------------------------------------------------------------------------- 1 | # The meaning of Class 2 | 3 | Classes are descriptions of a "classification" of 4 | objects in your program. 5 | 6 | The terminology is analagous to biological classification. 7 | Where Plato would classify any "featherless biped" as a human[^idiot], 8 | a `String` is classified by the set of things you can do to it and the data 9 | it stores. The `String` class would specify all of that.[^heady] 10 | 11 | 12 | [^idiot]: What an [idiot](https://www.shardcore.org/spx/2015/05/15/diogenes-and-the-chicken/) 13 | 14 | [^heady]: If thats a bit too heady of an explanation don't fret. You will likely get it intuitively eventually. 15 | There are like 50 different ways to explain it and eventually one will land for you. -------------------------------------------------------------------------------- /src/code_is_read_more_than_written.md: -------------------------------------------------------------------------------- 1 | # Code is Read more than Written 2 | 3 | Now that you more or less can write a full program, it won't be long 4 | before you write a program of "signficant size." 5 | 6 | This makes it a good time to start drip feeding some of the higher level 7 | concepts around software development. 8 | 9 | The first of these is a statement: Code is read more then it is written. -------------------------------------------------------------------------------- /src/code_is_read_more_than_written/implications.md: -------------------------------------------------------------------------------- 1 | # Implications 2 | 3 | This means that, sometimes, it makes sense to write code in a way that 4 | is "harder" than is absolutely needed. 5 | 6 | That's a bit of a fuzzy statement, but on the more obvious side it means 7 | doing things like spending extra time on code formatting, variable naming, 8 | function contracts, writing comments, etc. 9 | 10 | All of those things make it easier to read that code later on. -------------------------------------------------------------------------------- /src/code_is_read_more_than_written/meaning.md: -------------------------------------------------------------------------------- 1 | # Meaning 2 | 3 | While I'm sure there are some statistics behind this[^ormaybe], its generally accepted that 4 | the majority of a programmer's time is taken up reading existing code rather than writing new code. 5 | 6 | This should make sense intuitively. If you get hired at Microsoft, chances are you won't be given 7 | a blank slate to make a brand new thing. Often you will be thrust into existing codebases. To make a change 8 | to an existing codebase, you need to understand the exisiting code. 9 | 10 | It gets to the point where you might spend a whole day reading a dozen or so files only to make a 6 line change 11 | to one of them. 12 | 13 | 14 | [^ormaybe]: Software Development is still a relatively new field. Some things we take for granted may end up not being true after all. It doesn't help that its also pretty poorly researched. Keep an eye out for that. -------------------------------------------------------------------------------- /src/code_is_read_more_than_written/practice.md: -------------------------------------------------------------------------------- 1 | # Practice 2 | 3 | If you want to do programming as your job or as part of your job, 4 | and you want to be competent, it isn't enough to just practice writing code. 5 | You also need to practice reading. 6 | 7 | There are a lot of ways to go about that, but an easy one is to 8 | read the code of your classmates or of strangers on the internet. 9 | 10 | Read their code, try to understand all the (maybe wacky!) choices they made 11 | while writing it, and try to change it up a little bit. 12 | 13 | This will help you get an intuitive sense for what you like in 14 | a codebase as well as what you do not. It will also, more so than 15 | the early struggles you go through when learning to write, help you 16 | understand if you would actually like to do this for work. -------------------------------------------------------------------------------- /src/command_line_arguments.md: -------------------------------------------------------------------------------- 1 | # Command Line Arguments 2 | 3 | When you run a program like so 4 | 5 | ``` 6 | java src/Main.java 7 | ``` 8 | 9 | Anything you put to the right of `src/Main.java` will be available to your program as a 10 | "command line argument."[^name] 11 | 12 | ``` 13 | java src/Main.java example 14 | ``` 15 | 16 | [^name]: They come from the command line and they are arguments to your program. -------------------------------------------------------------------------------- /src/command_line_arguments/accessing_arguments.md: -------------------------------------------------------------------------------- 1 | # Accessing Arguments 2 | 3 | To access the command line arguments given to your program you need to change your main method. 4 | 5 | Instead of 6 | 7 | ```java 8 | void main() { 9 | 10 | } 11 | ``` 12 | 13 | Have your main method take a string array as an argument. 14 | 15 | ```java 16 | void main(String[] args) { 17 | 18 | } 19 | ``` 20 | 21 | This `String[]` will hold all the arguments passed. 22 | 23 | ``` 24 | java src/Main.java Duck Squirrel 25 | ``` 26 | 27 | ```java 28 | ~class Main { 29 | void main(String[] args) { 30 | for (int i = 0; i < args.length; i++) { 31 | System.out.println( 32 | "Hello Mr. " + args[i] 33 | ); 34 | } 35 | } 36 | ~} 37 | ~// This is a little ugly 38 | ~void main() { 39 | ~ new Main().main(new String[] { "Duck", "Squirrel" }); 40 | ~} 41 | ``` 42 | -------------------------------------------------------------------------------- /src/command_line_arguments/conventions.md: -------------------------------------------------------------------------------- 1 | # Conventions 2 | 3 | As it is just a `String[]`, you can interpret the arguments passed to your 4 | program in any way you choose. 5 | 6 | What you will notice, however, from using other tools in your terminal 7 | is that there are a few socially accepted conventions. 8 | 9 | If your tool takes "options" then you would expect `--option-name VALUE` to 10 | be how you specify it. So two dashes followed by the argument name. 11 | 12 | If you need a shorter version then you allow for one dash and sometimes a single 13 | letter value `-d VALUE`. 14 | 15 | And most importantly, if someone types `--help` you should give them the 16 | available options. Try `java --help` for an example. 17 | 18 | -------------------------------------------------------------------------------- /src/constructors.md: -------------------------------------------------------------------------------- 1 | # Constructors 2 | 3 | When defining a class, you are allowed to make a special kind of method 4 | called a constructor. 5 | 6 | A constructor runs before any code gets access to an instance of the class. 7 | You use it to set up the "initial state" for an object. -------------------------------------------------------------------------------- /src/constructors/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | To declare a constructor you make a method where you don't write any return type 4 | and whose name is the name of the class. 5 | 6 | ```java,no_run 7 | class Muppet { 8 | Muppet() { 9 | 10 | } 11 | } 12 | ``` 13 | 14 | Inside of the constructor's body, you can set the initial values for any fields 15 | in the class. 16 | 17 | ```java 18 | class Muppet { 19 | boolean talented; 20 | 21 | Muppet() { 22 | talented = true; 23 | } 24 | } 25 | 26 | void main() { 27 | Muppet gonzo = new Muppet(); 28 | System.out.println(gonzo.talented); 29 | } 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /src/constructors/multiple_constructors.md: -------------------------------------------------------------------------------- 1 | # Multiple Constructors 2 | -------------------------------------------------------------------------------- /src/constructors/the_default_constructor.md: -------------------------------------------------------------------------------- 1 | # The Default Constructor 2 | 3 | If you don't declare a constructor, it will be the same as declaring an "empty" 4 | constructor. All fields will be initialized to their default values. 5 | 6 | ```java 7 | class Muppet { 8 | String name; 9 | boolean talented; 10 | 11 | Muppet() { 12 | } 13 | } 14 | 15 | void main() { 16 | Muppet gonzo = new Muppet(); 17 | 18 | // null 19 | System.out.println(gonzo.name); 20 | // false 21 | System.out.println(gonzo.talented); 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/constructors/this.md: -------------------------------------------------------------------------------- 1 | # this 2 | -------------------------------------------------------------------------------- /src/drawing_shapes/right_triangles.md: -------------------------------------------------------------------------------- 1 | # Right Triangles 2 | -------------------------------------------------------------------------------- /src/encapsulation.md: -------------------------------------------------------------------------------- 1 | # Encapsulation 2 | 3 | One way of combatting the effects of Hyrum's Law 4 | is encapsulation. 5 | 6 | To encapsulate something is to hide it from the larger world. By doing 7 | so you lower the number of people who are able to observe what we would call 8 | "implementation details." 9 | 10 | -------------------------------------------------------------------------------- /src/encapsulation/abstractions.md: -------------------------------------------------------------------------------- 1 | # Abstractions 2 | 3 | A term closely related to encapsulation is abstraction. 4 | 5 | When you encapsulate something you have made an abstraction on top of it. 6 | 7 | You could say that "abstraction" is the noun and "encapsulation" is the verb. 8 | You encapsulate things, thereby making abstractions. -------------------------------------------------------------------------------- /src/encapsulation/classes.md: -------------------------------------------------------------------------------- 1 | # Classes 2 | -------------------------------------------------------------------------------- /src/encapsulation/implementation_details.md: -------------------------------------------------------------------------------- 1 | # Implementation Details 2 | 3 | Just as there is almost always more than one way 4 | to remove the epidermis of a feline, 5 | there is often more than one way to implement 6 | a program. 7 | 8 | We call properties and choices made when writing a program 9 | that are not related to what that program ultimitely needs 10 | to do "implementation details." 11 | 12 | As an example, imagine you are about to type 13 | a query into Microsoft Bing.[^bingit] The website you go to 14 | and the search box you see are intended parts of the program. 15 | The fact that if you click search you will see results is also 16 | just what the program needs to do. 17 | 18 | But all the mechanics of *how* that query is answered are 19 | implementation details. 20 | 21 | [^bingit]: You know, when you have a question and just have to "bing it?" -------------------------------------------------------------------------------- /src/encapsulation/implicit_interfaces.md: -------------------------------------------------------------------------------- 1 | # Implicit Interfaces 2 | -------------------------------------------------------------------------------- /src/encapsulation/information_hiding.md: -------------------------------------------------------------------------------- 1 | # Information Hiding 2 | 3 | When encapsulating, your fundamental activity is finding 4 | ways to hide information that you consider to be 5 | implementation details. 6 | 7 | If you did not hide this information and 8 | you have a large number of consumers[^if], you would never 9 | be able to change those implementation details. 10 | 11 | Something to be careful of with respect to this is "side channels." 12 | If you use the mechanisms Java gives you to hide a field from people, 13 | .. 14 | 15 | [^if]: Again, if. These concerns do not apply as much to 16 | programs written at smaller scales or programs written 17 | _within_ some encapsulation boundary. Don't get too paranoid 18 | about needing to hide things. -------------------------------------------------------------------------------- /src/encapsulation/leaky_abstractions.md: -------------------------------------------------------------------------------- 1 | # Leaky Abstractions 2 | -------------------------------------------------------------------------------- /src/enums.md: -------------------------------------------------------------------------------- 1 | # Enums 2 | 3 | While you can use `String`, `int`, `boolean`, and friends 4 | alongside your own custom classes to represent many situations, 5 | that is not always enough. 6 | 7 | Consider a stop light. At any given time it is either red, 8 | yellow, or green. 9 | 10 | The tool we use to model that kind of thing is enums. 11 | 12 | ```java,no_run 13 | enum StopLight { 14 | RED, 15 | YELLOW, 16 | GREEN 17 | } 18 | ``` 19 | 20 | Enums are types with fixed sets of allowed values. We call them enums because they enumerate multiple different possibilities. -------------------------------------------------------------------------------- /src/enums/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | To declare an `enum`, you write `enum` followed by a name for the enumeration 4 | and the names of the different possibilities separated by commas. 5 | 6 | ```java 7 | enum StopLight { 8 | RED, 9 | YELLOW, 10 | GREEN 11 | } 12 | ``` -------------------------------------------------------------------------------- /src/enums/equality.md: -------------------------------------------------------------------------------- 1 | # Equality 2 | 3 | You can check if two enums contain the same variant 4 | using the `==` operator. 5 | 6 | ```java 7 | enum StopLight { 8 | RED, 9 | YELLOW, 10 | GREEN 11 | } 12 | 13 | void main() { 14 | StopLight light = StopLight.RED; 15 | 16 | if (light == StopLight.RED) { 17 | System.out.println("You must stop"); 18 | } 19 | else { 20 | System.out.println("Full speed ahead!"); 21 | } 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/enums/naming.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | You are expected to name enums the same as you would regular classes: `WithCapitals`. 4 | 5 | The variants of enums are expected to be named in all capital letters, with underscores[^scream] 6 | 7 | ```java 8 | enum CarSeat { 9 | DRIVER, 10 | SHOTGUN, 11 | BACK_LEFT, 12 | BACK_RIGHT 13 | } 14 | ``` 15 | 16 | [^scream]: We call this convention "`SCREAMING_SNAKE_CASE`", which is silly. Snakes can't speak, let alone scream. I should know. -------------------------------------------------------------------------------- /src/enums/switch.md: -------------------------------------------------------------------------------- 1 | # Switch 2 | 3 | ```java 4 | enum StopLight { 5 | RED, 6 | YELLOW, 7 | GREEN 8 | } 9 | 10 | void main() { 11 | StopLight light = StopLight.RED; 12 | 13 | if (light == StopLight.RED) { 14 | System.out.println("You must stop"); 15 | } 16 | else { 17 | System.out.println("Full speed ahead!"); 18 | } 19 | } 20 | ``` -------------------------------------------------------------------------------- /src/enums/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | To use an enum, first make a variable or field whose type is 4 | the name of the enum. Then assign to it one of the variants. 5 | 6 | You can access the variants of an enum by writing the enum's name, 7 | a `.`, then the name of the variant. 8 | 9 | ```java 10 | enum StopLight { 11 | RED, 12 | YELLOW, 13 | GREEN 14 | } 15 | 16 | void main() { 17 | StopLight light = StopLight.RED; 18 | 19 | System.out.println( 20 | "The light is " + light 21 | ); 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/enums/variants.md: -------------------------------------------------------------------------------- 1 | # Variants 2 | 3 | We call the different possibilities that an enum represents its "variants." 4 | 5 | So in the following code we would say that the `TirePressure` enum has three variants: `LOW`, `NORMAL`, 6 | and `HIGH`. 7 | 8 | ```java,no_run 9 | enum TirePressure { 10 | LOW, 11 | NORMAL, 12 | HIGH 13 | } 14 | ``` -------------------------------------------------------------------------------- /src/exceptions.md: -------------------------------------------------------------------------------- 1 | # Exceptions 2 | 3 | When you do something that Java doesn't know how to handle, like 4 | dividing a number by zero, your program will fail. 5 | 6 | The way that this happens is that an "exception" is thrown. 7 | 8 | Say that in "normal conditions" code will proceed top to bottom, line by line. 9 | In "exceptional conditions" code will no longer be able to proceed. 10 | 11 | ```java,panics 12 | void main() { 13 | int x = 5 / 0; 14 | System.out.println("Won't get here, an exception will occur"); 15 | } 16 | ``` 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/exceptions/exception_messages.md: -------------------------------------------------------------------------------- 1 | # Exception Messages 2 | 3 | -------------------------------------------------------------------------------- /src/exceptions/messages.md: -------------------------------------------------------------------------------- 1 | # Messages 2 | 3 | You can attach a message to an exception to give context to 4 | whoever sees the program crash as to why that happened. 5 | 6 | You do this by putting a `String` in the parentheses when throwing 7 | your exception. 8 | 9 | ```java,panics 10 | void crashesOnFive(int x) { 11 | if (x == 5) { 12 | throw new RuntimeException("5 is an evil number"); 13 | } 14 | } 15 | 16 | void main() { 17 | crashesOnFive(1); 18 | System.out.println("Made it to step 1"); 19 | 20 | crashesOnFive(5); 21 | System.out.println("Will not make it to step 2"); 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/exceptions/throw.md: -------------------------------------------------------------------------------- 1 | # throw 2 | 3 | In order to throw an exception from your own code, you say `throw`, `new`, then the name 4 | of the exception and `()`. 5 | 6 | `RuntimeException` is one of many kinds of exceptions, but you can make do with only 7 | that in your own code for a bit. 8 | 9 | ```java,panics 10 | void crashesOnFive(int x) { 11 | if (x == 5) { 12 | throw new RuntimeException(); 13 | } 14 | } 15 | 16 | void main() { 17 | crashesOnFive(1); 18 | System.out.println("Made it to step 1"); 19 | 20 | crashesOnFive(5); 21 | System.out.println("Will not make it to step 2"); 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/exceptions_ii.md: -------------------------------------------------------------------------------- 1 | # Exceptions II 2 | 3 | Perhaps unsurprisingly, `RuntimeException` is not the only kind of exception 4 | that can be thrown. 5 | 6 | There is a huge variety of exception types out there, but the most important thing to understand is the distinction between checked and unchecked 7 | exceptions. -------------------------------------------------------------------------------- /src/exceptions_ii/main.md: -------------------------------------------------------------------------------- 1 | # main 2 | 3 | The `main` method can be declared to throw any kind of checked exception. 4 | 5 | It is assumed that if an exception makes it all the way there that the way to handle it is crash 6 | the program. 7 | 8 | ```java,panics 9 | void main() throws Exception { 10 | throw new Exception("crash"); 11 | } 12 | ``` -------------------------------------------------------------------------------- /src/exceptions_ii/runtime_exception.md: -------------------------------------------------------------------------------- 1 | # RuntimeException 2 | -------------------------------------------------------------------------------- /src/exceptions_ii/unchecked_exceptions.md: -------------------------------------------------------------------------------- 1 | # Unchecked Exceptions 2 | 3 | When a part of your code might throw a "unchecked" exception, other 4 | parts of your code do not need to account for that possibility. 5 | 6 | ```java 7 | int divide(int x, int y) { 8 | if (y == 0) { 9 | // Will work because you are not forced to handle 10 | // an unchecked exception 11 | throw new RuntimeException(); 12 | } 13 | 14 | return x / y; 15 | } 16 | ~void main() { 17 | ~ 18 | ~} 19 | ``` 20 | 21 | We call them unchecked because you don't need to check for them. -------------------------------------------------------------------------------- /src/fields.md: -------------------------------------------------------------------------------- 1 | # Fields 2 | -------------------------------------------------------------------------------- /src/fields/default_values.md: -------------------------------------------------------------------------------- 1 | # Default Values 2 | -------------------------------------------------------------------------------- /src/files.md: -------------------------------------------------------------------------------- 1 | # Files 2 | 3 | Files are how you store information 4 | on a[^normal] computer so that it can still be there when your program 5 | is done running. 6 | 7 | As such, read files and writing files are tasks you will often want to do. 8 | 9 | [^normal]: *normal -------------------------------------------------------------------------------- /src/files/creating_a_folder.md: -------------------------------------------------------------------------------- 1 | # Creating a Folder 2 | 3 | To create a folder, you can use `Files.createDirectory`. 4 | 5 | ```java 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | 9 | class Main { 10 | void main() throws IOExeption { 11 | Path folderPath = Path.of("example1"); 12 | Files.createDirectory(folderPath); 13 | } 14 | } 15 | ``` 16 | 17 | This, like the other methods in `Files`, might throw an `IOException`. 18 | 19 | `Files.createDirectory` will fail if the folder already exists. 20 | -------------------------------------------------------------------------------- /src/files/deleting_a_file.md: -------------------------------------------------------------------------------- 1 | # Delete a File 2 | -------------------------------------------------------------------------------- /src/files/deleting_a_folder.md: -------------------------------------------------------------------------------- 1 | # Delete a Folder 2 | -------------------------------------------------------------------------------- /src/files/ioexception.md: -------------------------------------------------------------------------------- 1 | # IOException 2 | 3 | If some code is "doing IO" - by which we mean while it is trying to read some Input or write some Output - you should expect it to throw an `IOException`. 4 | 5 | This class lives in the `java.io` package so to use it by its simple name you need an import. 6 | 7 | ```java 8 | import java.io.IOException; 9 | 10 | class Main { 11 | void main() throws IOException { 12 | throw new IOException("Something went wrong"); 13 | } 14 | } 15 | ``` 16 | 17 | Since reading a file is reading some input and writing to a file is writing some output, this exception is relevant to reading and writing files. -------------------------------------------------------------------------------- /src/files/paths.md: -------------------------------------------------------------------------------- 1 | # Paths 2 | 3 | All files and folders on your computer can be located by a "path" 4 | like "`Downloads/movie.mp4`." 5 | 6 | To store a path in a Java program we use the `Path` class from the `java.nio.file`[^nio] 7 | package. You create these `Path`s by giving a `String` to the `Path.of` 8 | static method. 9 | 10 | ```java 11 | import java.nio.file.Path; 12 | 13 | class Main { 14 | void main() { 15 | Path pathToNotes = Path.of("notes.txt"); 16 | 17 | System.out.println(pathToNotes); 18 | } 19 | } 20 | ``` 21 | 22 | [^nio]: `nio` stands for "new IO." So yes, there was an old IO. We will use that too. Its one of many artifacts from Java's interesting and sordid history. -------------------------------------------------------------------------------- /src/files/uncheckedioexception.md: -------------------------------------------------------------------------------- 1 | # UncheckedIOException 2 | 3 | The unchecked version of an `java.io.IOException` is `UncheckedIOException`. 4 | 5 | You can use this if you have a method which you don't want to propagate `IOException` but 6 | also want something more specific than `RuntimeException` to re-throw. 7 | 8 | 9 | And just like `IOException`, if you don't want to write 10 | out `java.io.UncheckedIOException` more than once you need to add an import. 11 | 12 | ```java,no_run 13 | import java.io.IOException; 14 | import java.io.UncheckedIOException; 15 | 16 | class Main { 17 | void main() { 18 | try { 19 | doStuff(); 20 | } 21 | catch (IOException e) { 22 | throw new UncheckedIOException(e); 23 | } 24 | } 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /src/floating_point_numbers.md: -------------------------------------------------------------------------------- 1 | # Floating Point Numbers 2 | 3 | Floating point numbers are used to represent numbers 4 | which cannot be stored as Integers like `2.5` or `3.14`. 5 | 6 | ```java,no_run 7 | double x = 1.5; 8 | double y = 8.0; 9 | double z = -3.14; 10 | ``` 11 | 12 | The type you will use to store a floating point number is `double`. 13 | `double` stands for "double precision floating point." 14 | -------------------------------------------------------------------------------- /src/floating_point_numbers/comparison.md: -------------------------------------------------------------------------------- 1 | # Comparison 2 | 3 | In addition to comparing for equality with `==` and `!=`, `doubles`s can be compared to see if one is bigger than another using 4 | `>`, `<`, `>=`, and `<=`. 5 | 6 | This works the same as it does with `int`s. 7 | 8 | ```java 9 | ~void main() { 10 | double x = 1.5; 11 | double y = 0.2; 12 | 13 | // true 14 | System.out.println(x > y); 15 | // false 16 | System.out.println(x < y); 17 | ~} 18 | ``` 19 | -------------------------------------------------------------------------------- /src/floating_point_numbers/division.md: -------------------------------------------------------------------------------- 1 | # Division 2 | 3 | You can divide any two `double`s using the `/` operator. 4 | 5 | ```java 6 | ~void main() { 7 | double x = 8; 8 | // y will be 4.0 9 | double y = x / 2; 10 | // z will be 1.3333333333333333 11 | double z = y / 3; 12 | 13 | System.out.println(x); 14 | System.out.println(y); 15 | System.out.println(z); 16 | ~} 17 | ``` 18 | 19 | Unlike with integer division, floating point division will include the remainder in the result.[^caveat] 20 | 21 | [^caveat]: With the caveat that the result is now potentially inaccurate. 22 | -------------------------------------------------------------------------------- /src/floating_point_numbers/limits.md: -------------------------------------------------------------------------------- 1 | # Limits 2 | -------------------------------------------------------------------------------- /src/floating_point_numbers/multiplication.md: -------------------------------------------------------------------------------- 1 | # Multiplication 2 | 3 | You can multiply any two `double`s using the `*` operator. 4 | 5 | ```java 6 | ~void main() { 7 | double x = 3; 8 | // y will be 27 9 | double y = x * 9; 10 | // z will be 13.5 11 | double z = y * 0.5; 12 | 13 | System.out.println(x); 14 | System.out.println(y); 15 | System.out.println(z); 16 | ~} 17 | ``` 18 | 19 | Just like with addition and subtraction, it is fine to use both integers and integer literals when doing 20 | multiplication on doubles. So long as any number being used is a `double` the overall result will be a double. 21 | 22 | ```java 23 | ~void main() { 24 | // a will be 3.0 25 | double a = 1.5 * 2; 26 | System.out.println(a); 27 | ~} 28 | ``` 29 | -------------------------------------------------------------------------------- /src/floating_point_numbers/shorthands_for_reassignment.md: -------------------------------------------------------------------------------- 1 | # Shorthands for Reassignment 2 | 3 | All the same shorthands for reassignment work with `double`s the same as they do with `int`s. 4 | 5 | ```java 6 | ~void main() { 7 | double x = 0.5; 8 | // 0.5 9 | System.out.println(x); 10 | 11 | x += 3; 12 | // 3.5 13 | System.out.println(x); 14 | 15 | x -= 1; 16 | // 2.5 17 | System.out.println(x); 18 | 19 | x++; 20 | // 3.5 21 | System.out.println(x); 22 | 23 | x--; 24 | // 2.5 25 | System.out.println(x); 26 | 27 | x *= 5; 28 | // 12.5 29 | System.out.println(x); 30 | 31 | x /= 2; 32 | // 6.25 33 | System.out.println(x); 34 | ~} 35 | ``` 36 | -------------------------------------------------------------------------------- /src/floating_point_numbers_ii.md: -------------------------------------------------------------------------------- 1 | # Floating Point Numbers II 2 | -------------------------------------------------------------------------------- /src/for.md: -------------------------------------------------------------------------------- 1 | # For 2 | 3 | ```java 4 | for (int index = 0; index < array.length; index++) { 5 | char element = array[index]; 6 | } 7 | ``` 8 | -------------------------------------------------------------------------------- /src/generic_growable_arrays.md: -------------------------------------------------------------------------------- 1 | # Generic Growable Arrays 2 | -------------------------------------------------------------------------------- /src/generic_growable_arrays/arraylist.md: -------------------------------------------------------------------------------- 1 | # ArrayList 2 | -------------------------------------------------------------------------------- /src/generic_hash_maps/hash_map: -------------------------------------------------------------------------------- 1 | # HashMap 2 | -------------------------------------------------------------------------------- /src/generics.md: -------------------------------------------------------------------------------- 1 | # Generics 2 | 3 | Certain types of classes, like growable arrays, are simply holders of data. 4 | 5 | That is, almost none of how they work has to change to 6 | store different kinds of data. 7 | 8 | Generics help us make these generically useful containers. 9 | 10 | ```java 11 | class Box { 12 | T value; 13 | } 14 | ``` 15 | 16 | -------------------------------------------------------------------------------- /src/generics/instantiation.md: -------------------------------------------------------------------------------- 1 | # Instantiation 2 | 3 | When you make an instance of a class that takes generic parameters 4 | you are expected to provide the actual concrete types you want to be used 5 | in place of any type variables. 6 | 7 | You do this by writing the name of the types inside a `<>` alongside the call to `new`. 8 | 9 | ```java 10 | class Box { 11 | T data; 12 | } 13 | 14 | void main() { 15 | var boxOfString = new Box(); 16 | 17 | boxOfString.data = "abc"; 18 | 19 | String s = boxOfString.data; 20 | 21 | System.out.println(s); 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/generics/naming.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | Type variables don't have to be only a single letter, though that is common. If you pick a longer name 4 | you are generally expected to name them as if they were classes. 5 | 6 | ```java 7 | class Box { 8 | Data data; 9 | } 10 | ``` -------------------------------------------------------------------------------- /src/generics/soundness.md: -------------------------------------------------------------------------------- 1 | # Soundness 2 | 3 | Even though every `String` is assignable to `Object`, 4 | a `Box` is not assignable to `Box`. 5 | 6 | If that was allowed then you could do something like the following. 7 | 8 | ```java,no_run,does_not_compile 9 | Box stringBox = new Box<>(); 10 | // This might feel innocent 11 | Box objectBox = stringBox; 12 | // But now we can put anything, 13 | // like an Integer, in the Box 14 | objectBox.data = 123; 15 | // Which is a problem since that affects 16 | // stringBox as well 17 | String s = stringBox.data; // But its actually an Integer! Crash! 18 | ``` 19 | 20 | We call this property - that the types don't let you accidentally make 21 | silly situations - soundness. Java isn't _fully_ sound, but its sound enough 22 | for most people. -------------------------------------------------------------------------------- /src/generics/type_variables.md: -------------------------------------------------------------------------------- 1 | # Type Variables 2 | 3 | After the name of a class in the class definition you can put one or more "type variables." 4 | These look like `<` followed by a comma separated list of "type names" and ended by a `>`. 5 | 6 | ```java,no_run 7 | class Box { 8 | 9 | } 10 | ``` 11 | 12 | Inside a class definition you can use these type variables on fields, method arguments, 13 | and method return types. 14 | 15 | ```java,no_run 16 | class Box { 17 | T data; 18 | 19 | void setData(T newData) { 20 | this.data = newData; 21 | } 22 | } 23 | ``` 24 | 25 | This indicates that you would be okay with any type being used in place of the type variable (in the above code `T`). 26 | -------------------------------------------------------------------------------- /src/getting_started/hello_world.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | -------------------------------------------------------------------------------- /src/getting_started/repl_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_1.png -------------------------------------------------------------------------------- /src/getting_started/repl_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_2.png -------------------------------------------------------------------------------- /src/getting_started/repl_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_3.png -------------------------------------------------------------------------------- /src/getting_started/repl_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_4.png -------------------------------------------------------------------------------- /src/getting_started/repl_4_voidmain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_4_voidmain.png -------------------------------------------------------------------------------- /src/getting_started/repl_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_5.png -------------------------------------------------------------------------------- /src/getting_started/repl_5_voidmain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_5_voidmain.png -------------------------------------------------------------------------------- /src/getting_started/repl_signup_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_signup_0.png -------------------------------------------------------------------------------- /src/getting_started/repl_signup_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/getting_started/repl_signup_1.png -------------------------------------------------------------------------------- /src/global_fields.md: -------------------------------------------------------------------------------- 1 | # Global Fields 2 | 3 | You can make field declarations outside of a class. 4 | This makes these fields "global" to the program. 5 | 6 | We call things global when they are available at every point 7 | in the "world" of our program.[^wonthold] 8 | 9 | ```java 10 | int number = 0; 11 | 12 | void main() { 13 | System.out.println(number); 14 | number++; 15 | System.out.println(number); 16 | } 17 | ``` 18 | 19 | [^wonthold]: This explanation is I think a correct description of what it means 20 | to be global, but what I am showing won't really hold up as a global thing the more you learn. -------------------------------------------------------------------------------- /src/global_fields/default_values.md: -------------------------------------------------------------------------------- 1 | # Default Values 2 | 3 | Just like regular fields in classes, global fields will initialize to their default 4 | value unless explicitly initialized. 5 | 6 | ```java 7 | int x; 8 | int y = 5; 9 | 10 | void main() { 11 | System.out.println(x); 12 | System.out.println(y); 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /src/global_fields/field_access.md: -------------------------------------------------------------------------------- 1 | # Field Access 2 | 3 | 4 | You can access global fields by writing their name. This works from within 5 | top level methods as well as instance methods of classes.[^different] 6 | 7 | ```java 8 | final String monster = "Dracula"; 9 | 10 | class Mash { 11 | void itWasThe() { 12 | System.out.println(monster + " and his son"); 13 | } 14 | } 15 | 16 | void main() { 17 | System.out.println(monster + " was there"); 18 | 19 | Mash mash = new Mash(); 20 | mash.itWasThe(); 21 | } 22 | ``` 23 | 24 | [^different]: This is so convenient it is actually going to be a bummer once you learn what is going on here 25 | and can't do it for most of your programs anymore. -------------------------------------------------------------------------------- /src/global_fields/final_fields.md: -------------------------------------------------------------------------------- 1 | # Final Fields 2 | 3 | And just like regular final fields, you always need to give an initial value to 4 | global final fields. 5 | 6 | ```java 7 | final int x = 0; 8 | 9 | void main() { 10 | System.out.println(x); 11 | } 12 | ``` 13 | 14 | Final fields of course cannot be changed. -------------------------------------------------------------------------------- /src/global_fields/inferred_types.md: -------------------------------------------------------------------------------- 1 | # Inferred Types 2 | 3 | Just like other field declarations, `var` cannot be used 4 | for inferring the type of a global field. You need to explicitly write out the type. 5 | 6 | ```java,does_not_compile 7 | var x = 5; 8 | 9 | void main() { 10 | System.out.println(x); 11 | } 12 | ``` -------------------------------------------------------------------------------- /src/growable_arrays.md: -------------------------------------------------------------------------------- 1 | # Growable Arrays 2 | 3 | Arrays are fixed size collections of elements. This means when we make an array 4 | that is 5 elements big it will always be 5 elements big. 5 | 6 | ```java 7 | ~void main() { 8 | int[] numbers = new int[5]; 9 | ~} 10 | ``` 11 | 12 | Something that turns out to be extremely useful is to have something with most of the properties of an array - such as being able quickly get and set arbitrary elements by index - but that can grow over time. 13 | 14 | The rest of this section I will walk you through how we can accomplish that. 15 | 16 | -------------------------------------------------------------------------------- /src/growable_arrays/concept.md: -------------------------------------------------------------------------------- 1 | # Concept 2 | 3 | The concept behind a growable array is that we 4 | store an array as a field and use it for operations like getting 5 | and setting elements. 6 | 7 | The extra wrinkle is that when someone wants to "add" an element 8 | we make a new, bigger, array and copy all the existing elements to it. 9 | Then we put the element you wanted to add at the end. 10 | 11 | -------------------------------------------------------------------------------- /src/hardware.md: -------------------------------------------------------------------------------- 1 | # Hardware 2 | 3 | That was a long stretch of Java, so I think you've earned a bit of a detour into 4 | general computing knowledge. 5 | 6 | I won't be offended if you skim or skip these sections. Depending on who you are, 7 | this might be a bit obvious. 8 | 9 | First lets cover hardware. The actual physical components that make up your computer. -------------------------------------------------------------------------------- /src/hardware/cpu.md: -------------------------------------------------------------------------------- 1 | # CPU 2 | 3 | At the core of every computer is a CPU. 4 | 5 | This stands for "central processing unit." This is the rock that wizards taught how to think. 6 | 7 | If you send the right electrical signals into a CPU it can do all sorts of math and it can do it quickly. 8 | 9 | Inside a computer this looks like a little metal square. -------------------------------------------------------------------------------- /src/hardware/hard_drives.md: -------------------------------------------------------------------------------- 1 | # Hard Drives 2 | 3 | RAM sticks have a few issues in the memory department. 4 | 5 | First, they can only hold around 8-64 gigabytes of 6 | info. Any more than that and they can get pretty slow.[^latency] 7 | 8 | Second, when you turn off the computer they lose anything they are storing. This is a problem when 9 | you are writing an essay and need to turn off the computer half way through. 10 | 11 | Hard drives are like RAM in that they remember stuff. The difference is that hard drives 12 | can store a lot more of it (terrabytes) and the data isn't lost when power is turned off. 13 | 14 | [^latency]: The key word here is "latency". When the CPU needs info in RAM it needs to wait for RAM 15 | to find it. It takes longer to find something in a bigger pile of stuff, no matter how smart you are about it. -------------------------------------------------------------------------------- /src/hardware/motherboard.md: -------------------------------------------------------------------------------- 1 | # Motherboard 2 | 3 | All of these parts, and the parts I didn't mention, are connected to 4 | a big circuit board called a "motherboard." 5 | 6 | The motherboard connects the CPU, RAM, and any hard drive(s) such that they 7 | can "talk" to eachother. The details of how it does this aren't super important, so just imagine 8 | that a tiny wizard lives inside it. -------------------------------------------------------------------------------- /src/hardware/ram.md: -------------------------------------------------------------------------------- 1 | # RAM 2 | 3 | CPUs can do math real fast, but they can't remember much stuff.[^likeme] 4 | 5 | This is what RAM is for. RAM stands for "random access memory." The random access 6 | part just means that a CPU can ask for any bit of info at any time. 7 | 8 | Most computers nowadays have an even number of RAM sticks. This is for interesting reasons I 9 | don't fully understand. 10 | 11 | [^likeme]: In 8th grade I had someone physically hand me a piece of paper with their name and 12 | fun facts about them because I had kept forgetting their name the entire year. I don't know what 13 | Sam is up to now, but I remember that she likes pistachio ice cream. -------------------------------------------------------------------------------- /src/hash_map.md: -------------------------------------------------------------------------------- 1 | # HashMap 2 | -------------------------------------------------------------------------------- /src/hash_maps/function_range.md: -------------------------------------------------------------------------------- 1 | # Function Range 2 | 3 | Once you have a hash function, you need to determine its range. 4 | 5 | The range of a function is the set of values it might return. 6 | 7 | If you have a function that might return any `int` then the range will be 8 | all the values between `Integer.MIN_VALUE` and `Integer.MAX_VALUE`. 9 | 10 | If your hash function only returns a number between `0` and `5`, `0` - `5` 11 | is the range. 12 | -------------------------------------------------------------------------------- /src/hash_maps/hash_collision.md: -------------------------------------------------------------------------------- 1 | # Hash Collision 2 | 3 | It is possible for a hash function to give the same 4 | result for two distinct elements. 5 | 6 | The first letter of both 7 | "Smith" and "Sanders" is "S", so if the hash function takes the first letter 8 | of the last name they will have the same hash. 9 | 10 | We call this situation a "hash collision." All it means is that these two objects 11 | will definitely go into the same bucket. 12 | 13 | That's allowed to happen, but if _everything_ goes into the same bucket then there 14 | isn't much point to using a hash map over a growable array. -------------------------------------------------------------------------------- /src/hash_maps/hash_distribution.md: -------------------------------------------------------------------------------- 1 | # Hash Distribution 2 | 3 | When picking a hash function you also need to be worried 4 | about "hash distribution." 5 | 6 | If you open up a doctor's office in South Boston, you might have an issue 7 | ordering charts by last name only. Your `M` cabinet will be overflowing.[^irish] 8 | 9 | For that scenario, using the first letter of the last name is a non-ideal hash function 10 | because so when many people have last names starting with the same letter, they will 11 | not be evenly distributed amongst the buckets. 12 | 13 | [^irish]: "Mc" and "Mac" are common irish surnames and Boston has a sizable irish population. -------------------------------------------------------------------------------- /src/hash_maps/hash_functions.md: -------------------------------------------------------------------------------- 1 | # Hash Functions 2 | 3 | A hash function is something that takes a piece of data 4 | and extracts a smaller, but predictable, piece of data from it. 5 | 6 | ```java 7 | record CarsCharacter( 8 | String firstName, 9 | String lastName 10 | ) {} 11 | 12 | char hashFunction( 13 | String lastName 14 | ) { 15 | return lastName.charAt(0); 16 | } 17 | 18 | void main() { 19 | var lightning = new CarsCharacter("Lightning", "McQueen"); 20 | 21 | char firstOfLast = hashFunction(lightning.lastName()); 22 | System.out.println(firstOfLast); 23 | } 24 | ``` 25 | 26 | Taking the first letter of a last name is an example of this. You can't 27 | reverse `M` into `McQueen`, but you can take `McQueen` and know to look 28 | in the bucket labeled `M`. 29 | 30 | We need hash functions to decide what "filing cabinet" 31 | a thing should go in. -------------------------------------------------------------------------------- /src/hash_maps/keys_and_values.md: -------------------------------------------------------------------------------- 1 | # Keys and Values 2 | 3 | A Hash Map "maps" keys to values. 4 | 5 | In the filing cabinet analogy we are mapping names to charts 6 | full of all sorts of other information on the person. 7 | 8 | For the rest of these examples assume we are trying to map 9 | `CarsCharacter`s to how many times they won the Piston Cup.[^watchcars] 10 | 11 | [^watchcars]: Cars was a delightful movie. Go to your local second hand store, get 12 | a copy on DVD, and make a night of it. -------------------------------------------------------------------------------- /src/hash_maps/redistribution.md: -------------------------------------------------------------------------------- 1 | # Redistribution 2 | -------------------------------------------------------------------------------- /src/hyrums_law.md: -------------------------------------------------------------------------------- 1 | # Hyrum's Law 2 | 3 | This is Hyrum's Law. 4 | 5 | > With a sufficient number of users of an API, 6 | > it does not matter what you promise in the contract: 7 | > all observable behaviors of your system 8 | > will be depended on by somebody. -------------------------------------------------------------------------------- /src/hyrums_law/authority.md: -------------------------------------------------------------------------------- 1 | # Authority 2 | 3 | Hyrum's Law, and many other "laws" in software development, 4 | are not really laws in the same way as "The Law of Conservation of Energy." 5 | 6 | Those sorts of laws are observed truths about a field. Best we can tell they are always true, no matter what. 7 | 8 | Hyrum's Law is just an aphorism. Its one specific person's view on the field. 9 | 10 | This sounds sketchy, and it is, but the state 11 | of the computing field is such that aphorisms and personal anecdotes are often the best information we have. 12 | -------------------------------------------------------------------------------- /src/hyrums_law/emergent_properties.md: -------------------------------------------------------------------------------- 1 | # Emergent Properties 2 | 3 | Emergent properties are things that simply "emerge" 4 | as a consequence of other factors. 5 | 6 | Hyrum's law is one of those sorts of things. Nobody sat down and agreed 7 | that they will use an API in wacky ways. It just happens when you throw enough 8 | monkeys in a pile and they all reach for a keyboard. 9 | 10 | As such, the way to deal with it isn't to put blame upon the monkeys. Its 11 | to accept it as a naturally occurring phenominon and plan accordingly. -------------------------------------------------------------------------------- /src/identity_types.md: -------------------------------------------------------------------------------- 1 | # Identity Types 2 | -------------------------------------------------------------------------------- /src/identity_types/comparison_with_equalsequals.md: -------------------------------------------------------------------------------- 1 | # Comparison with == 2 | -------------------------------------------------------------------------------- /src/img/armcross.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/img/armcross.webp -------------------------------------------------------------------------------- /src/img/computer_bad.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/img/computer_bad.webp -------------------------------------------------------------------------------- /src/img/duke_armcross.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/img/duke_armcross.webp -------------------------------------------------------------------------------- /src/img/duke_computer.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/img/duke_computer.webp -------------------------------------------------------------------------------- /src/img/duke_finger.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/img/duke_finger.webp -------------------------------------------------------------------------------- /src/img/eyeclose.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/img/eyeclose.webp -------------------------------------------------------------------------------- /src/inner_classes.md: -------------------------------------------------------------------------------- 1 | # Inner Classes 2 | 3 | You can declare a class within another class. 4 | 5 | ```java,no_run 6 | class Car { 7 | class Speedometer { 8 | 9 | } 10 | } 11 | ``` 12 | 13 | We call these inner classes. 14 | -------------------------------------------------------------------------------- /src/inner_classes/instance_new.md: -------------------------------------------------------------------------------- 1 | # Instance New 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/inner_classes/new_operator.md: -------------------------------------------------------------------------------- 1 | # New Operator 2 | 3 | If you want to make an instance of an inner class 4 | without making a method on the class containing it, 5 | you can use the "new operator." 6 | 7 | Whereas you make an instance of a regular class by saying 8 | something like `new ClassName()`, you can make an instance of an 9 | inner class by using `.new` on a variable that holds an instance 10 | of the containing class. 11 | 12 | Thats a confusing verbal description, but it kinda makes sense once you see it. 13 | 14 | ```java 15 | class Car { 16 | class Speedometer { 17 | } 18 | } 19 | ``` 20 | 21 | ```java 22 | ~class Car { 23 | ~ class Speedometer { 24 | ~ } 25 | ~} 26 | class Main { 27 | void main() { 28 | Car car = new Car(); 29 | Car.Speedometer speedometer = car.new Speedometer(); 30 | System.out.println(speedometer); 31 | } 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /src/inner_classes/private_inner_classes.md: -------------------------------------------------------------------------------- 1 | # Private Inner Classes 2 | 3 | Both `static` and regular inner classes can be marked as `private`. 4 | 5 | ```java 6 | class Human { 7 | // No other class can see this human's thoughts 8 | private class Thoughts { 9 | 10 | } 11 | 12 | // Nor can they see their feelings 13 | private static class Feelings { 14 | 15 | } 16 | } 17 | ``` 18 | 19 | Within the class they are defined, a private inner class works as normal. The 20 | difference is that code outside the class cannot make instances of them. -------------------------------------------------------------------------------- /src/inner_classes/type.md: -------------------------------------------------------------------------------- 1 | # Type 2 | 3 | The type of an inner class, when used as a variable or as a field, 4 | is the name of the containing class followed by a `.` and the 5 | name of the inner class. 6 | 7 | ```java,no_run 8 | class Car { 9 | class Speedometer {} 10 | } 11 | ``` 12 | 13 | So a field containing an instance of `Speedometer` would have the type `Car.Speedometer`. 14 | 15 | ```java,no_run 16 | Car.Speedometer speedometer = ...; 17 | ``` 18 | 19 | The exception is if the inner class is referenced within the class that declares it. 20 | In that context you just need to write the name of the class; 21 | 22 | ```java 23 | class Car { 24 | // Car.Speedometer is not required 25 | // (it will work though) 26 | Speedometer speedometer; 27 | 28 | class Speedometer {} 29 | } 30 | ``` -------------------------------------------------------------------------------- /src/instance_methods.md: -------------------------------------------------------------------------------- 1 | # Instance Methods 2 | 3 | In addition to having fields, classes can also have their own method 4 | definitions. 5 | 6 | These look the same as the method definitions you've 7 | seen so far, they are just put within a class definition.[^kermitangry] 8 | 9 | ```java 10 | class Muppet { 11 | String name; 12 | 13 | void freakOut() { 14 | System.out.println("**ANGRY KERMIT NOISES**") 15 | } 16 | } 17 | ``` 18 | 19 | We call these instance methods because you need an instance of the class in order 20 | to call the method. 21 | 22 | [^kermitangry]: If you haven't seen the muppets this might have go over your head, 23 | but Kermit [randomly gets really mad.](https://www.youtube.com/watch?v=SVDgHEg2jnY) -------------------------------------------------------------------------------- /src/instance_methods/aliasing.md: -------------------------------------------------------------------------------- 1 | # Aliasing 2 | -------------------------------------------------------------------------------- /src/instance_methods/arguments.md: -------------------------------------------------------------------------------- 1 | # Arguments 2 | 3 | Instance methods can take arguments the same as the methods you have 4 | seen so far. 5 | 6 | ```java 7 | class Muppet { 8 | String name; 9 | 10 | void singLyric(int verse) { 11 | if (verse == 1) { 12 | System.out.println("Why are there so many"); 13 | } 14 | else if (verse == 2) { 15 | System.out.println("Songs about rainbows"); 16 | } 17 | else { 18 | System.out.println("And what's on the other side?"); 19 | } 20 | } 21 | } 22 | ``` -------------------------------------------------------------------------------- /src/instance_methods/clarity.md: -------------------------------------------------------------------------------- 1 | # Clarity 2 | 3 | Another reason you might want to use `this` is for code clarity. 4 | 5 | It is a lot easier to know that a particular line refers to a field 6 | or method on the same class if there is an explicit `this.` before 7 | the reference.[^preference] 8 | 9 | ```java 10 | class Elmo { 11 | int age; 12 | 13 | void sayHello() { 14 | System.out.println("Hi, I'm Elmo"); 15 | System.out.print("I am "); 16 | System.out.print(this.age); 17 | System.out.println(" years old."); 18 | } 19 | } 20 | 21 | void main() { 22 | Elmo elmo = new Elmo(); 23 | elmo.age = 3; 24 | 25 | elmo.sayHello(); 26 | } 27 | ``` 28 | 29 | [^preference]: This is very much a personal preference thing. I generally choose to write 30 | `this.` whenever I am able to for this reason. -------------------------------------------------------------------------------- /src/instance_methods/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | -------------------------------------------------------------------------------- /src/instance_methods/derived_values.md: -------------------------------------------------------------------------------- 1 | # Derived Values 2 | 3 | A common use for methods is to provide a value that is derived from 4 | the values of other fields. 5 | 6 | ```java 7 | class Elmo { 8 | int age; 9 | 10 | int nextAge() { 11 | return age + 1; 12 | } 13 | } 14 | 15 | void main() { 16 | Elmo elmo = new Elmo(); 17 | elmo.age = 3; 18 | 19 | System.out.println("Elmo is " + elmo.age + " right now,"); 20 | System.out.println("but next year Elmo will be " + elmo.nextAge()); 21 | } 22 | ``` 23 | 24 | Which is useful for situations like where you store someones first and last name -------------------------------------------------------------------------------- /src/instance_methods/disambiguation.md: -------------------------------------------------------------------------------- 1 | # Disambiguation 2 | 3 | One reason you might need to use `this` is if the name 4 | of an argument to a method is the same as the name of a field. 5 | 6 | ```java 7 | class Elmo { 8 | int age; 9 | 10 | boolean isOlderThan(int age) { 11 | return this.age > age; 12 | } 13 | } 14 | 15 | void main() { 16 | Elmo elmo = new Elmo(); 17 | elmo.age = 3; 18 | 19 | // true 20 | System.out.println(elmo.isOlderThan(2)); 21 | } 22 | ``` 23 | 24 | If you didn't do this, it would be ambiguous whether you were referring to the field 25 | or the argument. This removes the ambiguity.[^javanotconfused] 26 | 27 | [^javanotconfused]: Really it isn't ambiguous for Java. It will just think you are referring to the argument. 28 | It is ambiguous from the perspective of a human being reading the code though. -------------------------------------------------------------------------------- /src/instance_methods/field_access.md: -------------------------------------------------------------------------------- 1 | # Field Access 2 | 3 | Within an instance method's definition, you can access the values 4 | of any fields declared in the class by just writing their name. 5 | 6 | ```java 7 | class Elmo { 8 | int age; 9 | 10 | void sayHello() { 11 | System.out.println("Hi, I'm Elmo"); 12 | System.out.print("I am "); 13 | 14 | // You can use elmo's age by just writing "age" 15 | System.out.print(age); 16 | System.out.println(" years old."); 17 | } 18 | } 19 | 20 | void main() { 21 | Elmo elmo = new Elmo(); 22 | elmo.age = 3; 23 | 24 | elmo.sayHello(); 25 | } 26 | ``` -------------------------------------------------------------------------------- /src/instance_methods/field_updates.md: -------------------------------------------------------------------------------- 1 | # Field Updates 2 | 3 | You can also update the value of any field from within an instance 4 | method the same as if it were a local variable. 5 | 6 | ```java 7 | class Elmo { 8 | int age; 9 | 10 | void sayHello() { 11 | System.out.println("Hi, I'm Elmo"); 12 | System.out.print("I am "); 13 | System.out.print(age); 14 | System.out.println(" years old."); 15 | } 16 | 17 | void haveBirthday() { 18 | age = age + 1; 19 | } 20 | } 21 | 22 | void main() { 23 | Elmo elmo = new Elmo(); 24 | elmo.age = 3; 25 | 26 | elmo.sayHello(); 27 | elmo.haveBirthday(); 28 | elmo.sayHello(); 29 | } 30 | ``` -------------------------------------------------------------------------------- /src/instance_methods/invocation.md: -------------------------------------------------------------------------------- 1 | # Invocation 2 | 3 | To invoke an instance method you first need an instance of the class. 4 | 5 | You then write `.` followed by the name of the instance method and a list of arguments.[^elmo] 6 | 7 | ```java 8 | class Elmo { 9 | void talkAboutRocko() { 10 | System.out.println("ROCKO'S NOT ALIVE!!") 11 | } 12 | } 13 | 14 | void main() { 15 | Elmo elmo = new Elmo(); 16 | elmo.talkAboutRocko(); 17 | } 18 | ``` 19 | 20 | [^elmo]: Daily reminder that Elmo absolutely [hates Rocko](https://www.youtube.com/watch?v=DFBMcwaSdns) -------------------------------------------------------------------------------- /src/instance_methods/invoke_other_methods.md: -------------------------------------------------------------------------------- 1 | # Invoke Other Methods 2 | 3 | Inside of an instance method you can invoke other instance methods 4 | on the same class by writing their name and providing any needed arguments. 5 | 6 | ```java 7 | class Elmo { 8 | int age; 9 | 10 | void sayHello() { 11 | System.out.println("Hi, I'm Elmo"); 12 | System.out.print("I am "); 13 | System.out.print(age); 14 | System.out.println(" years old."); 15 | } 16 | 17 | void startTheShow(String showName) { 18 | sayHello(); 19 | System.out.println("Welcome to " + showName); 20 | } 21 | } 22 | 23 | void main() { 24 | Elmo elmo = new Elmo(); 25 | elmo.age = 3; 26 | 27 | elmo.startTheShow("Sesame Street"); 28 | } 29 | ``` -------------------------------------------------------------------------------- /src/instance_methods/this.md: -------------------------------------------------------------------------------- 1 | # this 2 | 3 | Within an instance method, you have access to a magic variable called `this`. 4 | 5 | `this` is a variable that contains the current instance of the class. 6 | 7 | You can use `this` to access fields or invoke any method. 8 | 9 | ```java 10 | class Elmo { 11 | int age; 12 | 13 | void sayHello() { 14 | System.out.println("Hi, I'm Elmo"); 15 | System.out.print("I am "); 16 | System.out.print(this.age); 17 | System.out.println(" years old."); 18 | } 19 | 20 | void startTheShow(String showName) { 21 | this.sayHello(); 22 | System.out.println("Welcome to " + showName); 23 | } 24 | } 25 | 26 | void main() { 27 | Elmo elmo = new Elmo(); 28 | elmo.age = 3; 29 | 30 | elmo.startTheShow("Sesame Street"); 31 | } 32 | ``` -------------------------------------------------------------------------------- /src/integer_ii/integer_to_a_base_16_string.md: -------------------------------------------------------------------------------- 1 | # Integer to a Base 16 String 2 | -------------------------------------------------------------------------------- /src/integers.md: -------------------------------------------------------------------------------- 1 | # Integers 2 | 3 | [An integer is any number in the set `{ ..., -2, -1, 0, 1, 2, ... }.`](https://www.khanacademy.org/math/cc-sixth-grade-math/cc-6th-expressions-and-variables/whole-numbers-integers/a/whole-numbers-integers) 4 | 5 | ```java 6 | int x = 1; 7 | int y = 8; 8 | int z = -4; 9 | ``` 10 | -------------------------------------------------------------------------------- /src/integers/addition.md: -------------------------------------------------------------------------------- 1 | # Addition 2 | 3 | You can add any two `int`s using the `+` operator. 4 | 5 | ```java 6 | ~void main() { 7 | int x = 5; 8 | // y will be 6 9 | int y = x + 1; 10 | // z will be 11 11 | int z = x + y; 12 | 13 | System.out.println(x); 14 | System.out.println(y); 15 | System.out.println(z); 16 | ~} 17 | ``` 18 | 19 | Adding a negative number does the same thing as subtraction. 20 | 21 | ```java 22 | ~void main() { 23 | int x = 5; 24 | // y will be 1 25 | int y = x + -4; 26 | 27 | System.out.println(x); 28 | System.out.println(y); 29 | ~} 30 | ``` 31 | -------------------------------------------------------------------------------- /src/integers/chained_comparisons.md: -------------------------------------------------------------------------------- 1 | # Chained Comparisons 2 | 3 | When writing an expression in math to say something along the lines of 4 | "`x` is greater than zero and less than 5," it is natural to put that `x` 5 | in the middle of both operators like so. 6 | 7 | ```text,no_run 8 | 0 < x < 5 9 | ``` 10 | 11 | This does not work in Java. In order to "chain" comparisons like this, you should combine 12 | the results of comparisons using the `&&` operator. 13 | 14 | ```java,no_run 15 | boolean xInRange = 0 < x && x < 5; 16 | ``` 17 | -------------------------------------------------------------------------------- /src/integers/division.md: -------------------------------------------------------------------------------- 1 | # Division 2 | 3 | You can divide any two `int`s using the `/` operator. 4 | 5 | ```java 6 | ~void main() { 7 | int x = 8; 8 | // y will be 4 9 | int y = x / 2; 10 | 11 | System.out.println(x); 12 | System.out.println(y); 13 | ~} 14 | ``` 15 | 16 | Division with integers gives results in only the [quotient](https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/the-quotient-remainder-theorem) of the result, not the remainder. 17 | 18 | So `5 / 2` does not result in `2.5`, but instead just `2`. 19 | 20 | ```java 21 | ~void main() { 22 | // 5 / 2 is not 2.5, but instead 2. 23 | int x = 5 / 2; 24 | // 13 / 3 is not 4.3333, but instead 4. 25 | int y = 13 / 3; 26 | 27 | System.out.println(x); 28 | System.out.println(y); 29 | ~} 30 | ``` 31 | -------------------------------------------------------------------------------- /src/integers/integer_literals.md: -------------------------------------------------------------------------------- 1 | # Integer Literals 2 | 3 | In order to write an integer in a program, you write an "integer literal." 4 | 5 | ```java 6 | 789 7 | ``` 8 | 9 | We call them this because the integer is literally written down in the program. 10 | 11 | ```java 12 | int trueCrime = 789; 13 | ``` 14 | -------------------------------------------------------------------------------- /src/integers/multiplication.md: -------------------------------------------------------------------------------- 1 | # Multiplication 2 | 3 | You can multiply any two `int`s using the `*` operator. 4 | 5 | ```java 6 | ~void main() { 7 | // x will be 15 8 | int x = 3 * 5; 9 | // y will be 75 10 | int y = x * 5; 11 | // z will be 1125 12 | int z = x * y; 13 | 14 | System.out.println(x); 15 | System.out.println(y); 16 | System.out.println(z); 17 | ~} 18 | ``` 19 | -------------------------------------------------------------------------------- /src/integers/reassignment.md: -------------------------------------------------------------------------------- 1 | # Reassignment 2 | 3 | When the value of a variable is reassigned, the value stored in the variable 4 | before the reassignment can be used to compute the new value. 5 | 6 | This is true for all data types, but it is easiest to demonstrate with numbers. 7 | 8 | ```java 9 | ~void main() { 10 | int x = 1; 11 | System.out.println(x); 12 | 13 | // x starts as 1, 1 + 1 is 2. 14 | // 2 is the new value of x. 15 | x = x + 1; 16 | System.out.println(x); 17 | 18 | // x is now 2, 2 * 2 * 3 is 12 19 | // 12 is the new value of x. 20 | x = x * x * 3; 21 | System.out.println(x); 22 | ~} 23 | ``` 24 | 25 | This property was used in the previous example for the `%` operator, but I think it worth calling attention to even if it is "intuitive". 26 | -------------------------------------------------------------------------------- /src/integers/subtraction.md: -------------------------------------------------------------------------------- 1 | # Subtraction 2 | 3 | You can subtract any two `int`s using the `-` operator. 4 | 5 | ```java 6 | ~void main() { 7 | int x = 5; 8 | // y will be 4 9 | int y = x - 1; 10 | // z will be 1 11 | int z = x - y; 12 | 13 | System.out.println(x); 14 | System.out.println(y); 15 | System.out.println(z); 16 | ~} 17 | ``` 18 | 19 | Subtracting a negative number does the same thing as addition. 20 | 21 | ```java 22 | ~void main() { 23 | int x = 5; 24 | // y will be 9 25 | int y = x - -4; 26 | 27 | System.out.println(x); 28 | System.out.println(y); 29 | ~} 30 | ``` 31 | -------------------------------------------------------------------------------- /src/integers_ii.md: -------------------------------------------------------------------------------- 1 | # Integers II 2 | 3 | Integers never stop being relevant and, now that we 4 | have covered static methods, we are ready to cover 5 | some of the more useful ones that exist for working with integers. -------------------------------------------------------------------------------- /src/integers_ii/integer_to_a_base_16_string.md: -------------------------------------------------------------------------------- 1 | # Integer to a Base 16 String 2 | 3 | If you have an integer you want to turn into a `String` in base 16 4 | integer you can use the `toHexString` method on `Integer`. 5 | 6 | ```java 7 | ~void main() { 8 | int x = 29411; 9 | String xStr = Integer.toHexString(x); 10 | 11 | // 72e3 12 | System.out.println(xStr); 13 | ~} 14 | ``` -------------------------------------------------------------------------------- /src/integers_ii/integer_to_a_string.md: -------------------------------------------------------------------------------- 1 | # Integer to a String 2 | 3 | If you have an integer you want to turn into a `String` you have two options. 4 | 5 | One is to "add it" to an empty string. 6 | 7 | ```java 8 | ~void main() { 9 | int x = 4; 10 | String xStr = "" + x; 11 | 12 | System.out.println(xStr); 13 | ~} 14 | ``` 15 | 16 | The other is to use the `toString` static method on `Integer`. 17 | 18 | 19 | ```java 20 | ~void main() { 21 | int x = 4; 22 | String xStr = Integer.toString(x); 23 | 24 | System.out.println(xStr); 25 | ~} 26 | ``` 27 | 28 | I personally find the second one more direct, but opinions can reasonably vary. -------------------------------------------------------------------------------- /src/integers_ii/underscores_in_integer_literals.md: -------------------------------------------------------------------------------- 1 | # Underscores in Integer Literals 2 | 3 | When you are writing large numbers `1000000000` isn't very 4 | visually distinct from `10000000000`. 5 | 6 | To help with the legibility you are allowed to insert underscores 7 | between digits in an integer literal. 8 | 9 | ```java 10 | ~void main() { 11 | int x = 1_000_000_000; 12 | int y = 10_000_000_000; 13 | 14 | System.out.println(x); 15 | System.out.println(y); 16 | ~} 17 | ``` 18 | 19 | This works with hexadecimal integer literals as well. 20 | 21 | ```java 22 | ~void main() { 23 | int white = 0xFF_FF_FF; 24 | 25 | System.out.println(Integer.toHexString(white)); 26 | ~} 27 | ``` -------------------------------------------------------------------------------- /src/interface_extension.md: -------------------------------------------------------------------------------- 1 | # Interface Extension 2 | -------------------------------------------------------------------------------- /src/interfaces.md: -------------------------------------------------------------------------------- 1 | # Interfaces 2 | 3 | Generics let you write code that doesn't care 4 | what is different between different things - you would accept a `String` 5 | or an `Integer`, doesn't matter what is diferent between them. 6 | 7 | Interfaces do a related thing. They let you write code that takes advantage 8 | of commonalities. 9 | 10 | ```java 11 | inteface Dog { 12 | void bark(); 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /src/interfaces/fields.md: -------------------------------------------------------------------------------- 1 | # Fields 2 | -------------------------------------------------------------------------------- /src/interfaces/instances.md: -------------------------------------------------------------------------------- 1 | # Instances 2 | -------------------------------------------------------------------------------- /src/interfaces/interface_declaration.md: -------------------------------------------------------------------------------- 1 | # Interface Declaration 2 | 3 | To declare an interface you write the word `interface` followed by the name of the interface 4 | and `{}`. 5 | 6 | ```java 7 | interface Dog {} 8 | ``` 9 | 10 | Inside of the `{}` you can write the signatures for methods followed by a `;`. That means 11 | no method body and no `public` or `private` modifiers. 12 | 13 | ```java,no_run 14 | interface Dog { 15 | void bark(); 16 | 17 | String fetch(String ball); 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /src/interfaces/methods.md: -------------------------------------------------------------------------------- 1 | # Methods 2 | -------------------------------------------------------------------------------- /src/interfaces/naming.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | Interfaces are named in the same way as classes - `LikeThis`. 4 | 5 | In the wild west of the real world you might see people prefix any interface 6 | name with `I`, for interface. 7 | 8 | In these cases instead of `Dog` you would see `IDog`. Instead of `PartyAnimal` you would 9 | see `IPartyAnimal` and so on. 10 | 11 | The reason someone might do this is if they think it is worthwhile to have a visual indicator 12 | of whether a type represents an interface or an actual class. Personally, I don't think that is 13 | too useful, but there is nothing horrible about it. 14 | 15 | Just judge the social context you are in and don't hold it against people too hard if they do it a way 16 | you don't like. -------------------------------------------------------------------------------- /src/interfaces/override.md: -------------------------------------------------------------------------------- 1 | # @Override 2 | 3 | Just like when defining your own `equals`, `hashCode`, and `toString` you 4 | can use `@Override` when implementing methods that come from an interface. 5 | 6 | ```java 7 | interface Dog { 8 | void bark(); 9 | 10 | String fetch(String ball); 11 | } 12 | 13 | class Mutt implements Dog { 14 | @Override 15 | public void bark() { 16 | System.out.println("Bark"); 17 | } 18 | 19 | @Override 20 | public String fetch(String ball) { 21 | return ball + " (with drool)"; 22 | } 23 | } 24 | ``` 25 | 26 | 27 | Right now there isn't a mechanical use for this since Java will yell at you if 28 | you defined the interface method wrong anyways, but there will be later. A small benefit 29 | is that it makes it easier to tell at a glance which methods come from an interface 30 | and which do not. -------------------------------------------------------------------------------- /src/iterable_and_iterator.md: -------------------------------------------------------------------------------- 1 | # Iterable and Iterator 2 | -------------------------------------------------------------------------------- /src/limits.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/src/limits.md -------------------------------------------------------------------------------- /src/loops.md: -------------------------------------------------------------------------------- 1 | # Loops 2 | 3 | `if` and `else` let you write programs which can take branching paths, 4 | but they will still run from the beginning to the end. 5 | 6 | Not all programs can just _end_ though. 7 | Video games should draw their world at one second and do it again the next. 8 | If you enter the wrong password on your phone, it should ask you for your password again. 9 | 10 | This is what "loops" are for. You run code starting from some point and then 11 | loop back to that same point and run that code again. 12 | -------------------------------------------------------------------------------- /src/loops/continue.md: -------------------------------------------------------------------------------- 1 | # Continue 2 | 3 | Unless there is a `break`, while loops will usually run all the code in their body from top to bottom. 4 | 5 | The only other situation this will not happen is if a `continue` statement is reached. 6 | 7 | ```java 8 | ~void main() { 9 | // Will output a message for every number except 4 10 | int x = 5; 11 | while (x > 0) { 12 | if (x == 4) { 13 | continue; 14 | } 15 | System.out.println(x + " is a good number"); 16 | x--; 17 | } 18 | ~} 19 | ``` 20 | 21 | If a `continue` is reached the code in the loop stops running immediately but, unlike `break`, 22 | the condition of the loop _is_ checked again. If it still evaluates to `true` then the code 23 | in the loop will run again. 24 | -------------------------------------------------------------------------------- /src/loops/endless_loops.md: -------------------------------------------------------------------------------- 1 | # Endless Loops 2 | 3 | If a while loop will never end, we call that an endless loop. 4 | 5 | This can happen if the condition is a constant like `while (true)` 6 | 7 | ```java,no_run 8 | ~void main() { 9 | while (true) { 10 | System.out.println("This is the song that never ends"); 11 | } 12 | ~} 13 | ``` 14 | 15 | Or if the variables tested in the condition are not updated inside of the loop. 16 | 17 | ```java,no_run 18 | ~void main() { 19 | // x is never changed 20 | int x = 0; 21 | while (x != 1) { 22 | System.out.println("It goes on and on my friends"); 23 | } 24 | ~} 25 | ``` 26 | 27 | Many games should never really "finish" so at the very start of that sort of program it is not uncommon 28 | to see a `while (true)`. 29 | -------------------------------------------------------------------------------- /src/loops/iterate_over_a_string.md: -------------------------------------------------------------------------------- 1 | # Iterate over a String 2 | 3 | This general pattern of counting up and counting down becomes 4 | especially useful when you want to iterate over each character in 5 | a `String`. 6 | 7 | ```java 8 | ~void main() { 9 | String name = "Avril"; 10 | 11 | int index = 0; 12 | while (index < name.length()) { 13 | System.out.println(name.charAt(index)); 14 | index++; 15 | } 16 | ~} 17 | ``` 18 | -------------------------------------------------------------------------------- /src/loops/iteration.md: -------------------------------------------------------------------------------- 1 | # Iteration 2 | 3 | Loops potentially run code multiple times. Each time one goes from its top to its bottom 4 | we call that an "iteration" of the loop. 5 | 6 | ```java 7 | ~void main() { 8 | int x = 0; 9 | while (x < 5) { 10 | // On the 1st iteration x will be 0 11 | // On the 2nd iteration x will be 1 12 | // ... 13 | // On the final iteration x will be 4 14 | System.out.println(x); 15 | x++ 16 | } 17 | ~} 18 | ``` 19 | 20 | When the purpose of a loop is to run for every thing in some sequence of things, 21 | we say that the loop is "iterating over" those things. 22 | -------------------------------------------------------------------------------- /src/loops/labeled_continue.md: -------------------------------------------------------------------------------- 1 | # Labeled Continue 2 | 3 | In the same way a labeled break can break out of a nested loop, a labeled continue 4 | can jump back to the start of a nested loop. 5 | 6 | You just write `continue` followed by the label name. 7 | 8 | ```java,no_run 9 | ~void main() { 10 | // Will keep going back to the top of the outer loop 11 | outerLoop: 12 | while (true) { 13 | System.out.println("inside outer loop"); 14 | while (true) { 15 | System.out.println("inside inner loop"); 16 | continue outerLoop; 17 | } 18 | } 19 | ~} 20 | ``` 21 | -------------------------------------------------------------------------------- /src/loops/unreachable_code.md: -------------------------------------------------------------------------------- 1 | # Unreachable Code 2 | 3 | If you write some code directly after a `break` or `continue` 4 | that code will be "unreachable." 5 | 6 | Java knows this and so won't let any code like that run. 7 | 8 | ```java,does_not_compile 9 | ~void main() { 10 | // This will not work 11 | while (true) { 12 | continue; 13 | 14 | System.out.println("this is unreachable"); 15 | } 16 | ~} 17 | ``` 18 | -------------------------------------------------------------------------------- /src/loops_ii.md: -------------------------------------------------------------------------------- 1 | # Loops II 2 | 3 | `while` loops are enough to make any looping logic that you might want, but 4 | they aren't the only kind of loops you will see. 5 | 6 | There are tasks which would require a `while` loop, but are common enough that there are other kinds 7 | of loops that are shortcuts to writing them. 8 | -------------------------------------------------------------------------------- /src/loops_ii/break.md: -------------------------------------------------------------------------------- 1 | # Break 2 | 3 | `break` works the same with `for` loops as it does with `while` loops. 4 | Any time you hit a line with `break` you will immediately exit the loop. 5 | 6 | ```java 7 | ~void main() { 8 | for (int i = 0; i < 1000; i++) { 9 | if (i == 5) { 10 | break; 11 | } 12 | System.out.println(i); 13 | } 14 | System.out.println("Over"); 15 | 16 | // 0 17 | // 1 18 | // 2 19 | // 3 20 | // 4 21 | // Over 22 | ~} 23 | ``` 24 | -------------------------------------------------------------------------------- /src/loops_ii/empty_expressions.md: -------------------------------------------------------------------------------- 1 | # Empty Expressions 2 | 3 | You are also allowed to leave the expression part of a `for` loop blank. 4 | 5 | ```java 6 | ~void main() { 7 | for (int i = 0;;i++) { 8 | System.out.println(i); 9 | } 10 | // 0 11 | // 1 12 | // 2 13 | // 3 14 | // ... and so on 15 | ~} 16 | ``` 17 | 18 | This means that each time through there is no check to see if the loop will exit. 19 | The loop will only exit if there is an explicit `break` somewhere. 20 | 21 | ```java 22 | ~void main() { 23 | for (int i = 0;;i++) { 24 | if (i == 5) { 25 | break; 26 | } 27 | System.out.println(i); 28 | } 29 | // 0 30 | // 1 31 | // 2 32 | // 3 33 | // 4 34 | ~} 35 | ``` 36 | -------------------------------------------------------------------------------- /src/loops_ii/empty_initializers.md: -------------------------------------------------------------------------------- 1 | # Empty Initializers 2 | 3 | You are allowed to leave the initializer part of a `for` loop blank 4 | so long as you still have the `;`. 5 | 6 | ```java 7 | ~void main() { 8 | int number = 0; 9 | for (;number < 5; number++) { 10 | System.out.println(number); 11 | } 12 | ~} 13 | ``` 14 | 15 | You might choose to do this for the same reasons you might choose to split the declaration 16 | and assignment of the "loop variable." So that the variable will be accessible after the end of the loop. 17 | 18 | This way its initialization and declaration can be on the same line, which might be desirable. 19 | 20 | ```java 21 | ~void main() { 22 | int number = 0; 23 | for (;number < 5; number++) { 24 | System.out.println(number); 25 | } 26 | System.out.println("Still have number: " + number); 27 | ~} 28 | ``` 29 | -------------------------------------------------------------------------------- /src/loops_ii/for.md: -------------------------------------------------------------------------------- 1 | # For 2 | 3 | The `for` loop is a shortcut to writing a `while` loop which 4 | has distinct steps that 5 | 6 | - Declare a variable 7 | - Check that variable to know whether to stop iterating 8 | - Update the variable at the end of each iteration 9 | 10 | As with many things, this might be easiest to see by looking at an example. 11 | 12 | ```java 13 | ~void main() { 14 | // Will run 10 times 15 | for (int number = 0; number < 10; number++) { 16 | System.out.println(number); 17 | } 18 | ~} 19 | ``` 20 | 21 | That `for` loop works about the same as this `while` loop. 22 | 23 | ```java 24 | ~void main() { 25 | int number = 0; 26 | while (number < 10) { 27 | System.out.println(number); 28 | 29 | number++; 30 | } 31 | ~} 32 | ``` 33 | -------------------------------------------------------------------------------- /src/loops_ii/inferred_types.md: -------------------------------------------------------------------------------- 1 | # Inferred Types 2 | 3 | The initializer of a `for` loop works the same as any variable assignment, so 4 | you still are allowed to use `var` so that the type of the declared variable is inferred. 5 | 6 | ```java 7 | ~void main() { 8 | for (var i = 0; i < 10; i++) { 9 | System.out.println(i); 10 | } 11 | ~} 12 | ``` 13 | 14 | `var` is the same number of letters as `int` so you aren't gaining much when your `for` loop 15 | is just counting over numbers. 16 | 17 | But if your `for` loop is doing something more exotic, it might make sense. 18 | 19 | ```java 20 | ~void main() { 21 | for (var repeated = ""; repeated.length() < 5; repeated = repeated + "a") { 22 | System.out.println(repeated); 23 | } 24 | 25 | // a 26 | // aa 27 | // aaa 28 | // aaaa 29 | ~} 30 | ``` 31 | -------------------------------------------------------------------------------- /src/loops_ii/iterate_over_a_string.md: -------------------------------------------------------------------------------- 1 | # Iterate over a String 2 | 3 | As was shown with `while` loops, being able to count up and down lets 4 | you iterate over each character in a `String`. 5 | 6 | ```java 7 | ~void main() { 8 | String name = "Lavigne"; 9 | 10 | for (int index = 0; index < name.length(); index++) { 11 | System.out.println(name.charAt(index)); 12 | } 13 | ~} 14 | ``` 15 | -------------------------------------------------------------------------------- /src/loops_ii/iterate_over_an_array.md: -------------------------------------------------------------------------------- 1 | # Iterate over an Array 2 | 3 | In the same way you can use a `for` loop to go through each character of a `String`, 4 | you can use it to go through each element in an array. 5 | 6 | ```java 7 | ~void main() { 8 | int[] numbers = { 4, 1, 6, 9 }; 9 | 10 | for (int index = 0; index < numbers.length; index++) { 11 | System.out.println(numbers[index]); 12 | } 13 | ~} 14 | ``` 15 | 16 | The only difference from `String`s is that instead of `.length()` and `.charAt(...)`, you use `.length` and `[]`. 17 | -------------------------------------------------------------------------------- /src/loops_ii/labeled_break.md: -------------------------------------------------------------------------------- 1 | # Labeled Break 2 | 3 | Labeled breaks work the same with `for` loops as they do with `while` loops. 4 | 5 | ```java,no_run 6 | outerLoop: 7 | for (;;) { 8 | for (;;) { 9 | break outerLoop; 10 | } 11 | } 12 | ``` 13 | 14 | This applies also to when `while` loops are nested within `for` loops or the other way around. 15 | 16 | ```java 17 | ~void main() { 18 | outerForLoop: 19 | for (int i = 0; i < 10; i++) { 20 | System.out.println(i); 21 | while (i < 100) { 22 | if (i == 5) { 23 | break outerForLoop; 24 | } 25 | i++; 26 | } 27 | System.out.println(i); 28 | } 29 | 30 | // 0 31 | ~} 32 | ``` 33 | -------------------------------------------------------------------------------- /src/loops_ii/labeled_continue.md: -------------------------------------------------------------------------------- 1 | # Labeled Continue 2 | 3 | Labeled continues also work the same in `for` loops as `while` loops, but with the hopefully expected caveat that 4 | the statement of a `for` loop will always run when you get to the top of it.[^uncommon] 5 | 6 | ```java 7 | ~void main() { 8 | label: 9 | for (int i = 0; i < 4; i++) { 10 | for (int j = 0; j < 3; j++) { 11 | System.out.println ("" + i + ", " + j); 12 | if (i == 2) { 13 | // i++ will run 14 | continue label; 15 | } 16 | } 17 | } 18 | // 0, 0 19 | // 0, 1 20 | // 0, 2 21 | // 1, 0 22 | // 1, 1 23 | // 1, 2 24 | // 2, 0 25 | // 3, 0 26 | // 3, 1 27 | // 3, 2 28 | ~} 29 | ``` 30 | -------------------------------------------------------------------------------- /src/loops_iii.md: -------------------------------------------------------------------------------- 1 | # Loops III 2 | 3 | Counting indexes of elements is, while effective, a tad 4 | exhausting to do every time you want to loop through something. 5 | 6 | ```java 7 | ~void main() { 8 | String[] shirts = new String[] { 9 | "T-Shirt", 10 | "Polo Shirt", 11 | "Dress Shirt" 12 | }; 13 | 14 | for (int i = 0; i < shirts.length; i++) { 15 | String shirt = shirts[i]; 16 | 17 | System.out.println(shirt); 18 | } 19 | ~} 20 | ``` 21 | 22 | This is where "for-each" loops come in. 23 | 24 | ```java 25 | ~void main() { 26 | String[] shirts = new String[] { 27 | "T-Shirt", 28 | "Polo Shirt", 29 | "Dress Shirt" 30 | }; 31 | 32 | for (String shirt : shirts) { 33 | System.out.println(shirt); 34 | } 35 | ~} 36 | ``` 37 | -------------------------------------------------------------------------------- /src/loops_iii/concurrent_modifications.md: -------------------------------------------------------------------------------- 1 | # Concurrent Modifications 2 | -------------------------------------------------------------------------------- /src/loops_iii/for_each_loops.md: -------------------------------------------------------------------------------- 1 | # For-each loops 2 | -------------------------------------------------------------------------------- /src/methods.md: -------------------------------------------------------------------------------- 1 | # Methods 2 | 3 | All the code you have seen up until this point has lived inside of `void main() {}`. 4 | 5 | ```java 6 | void main() { 7 | System.out.println("CODE GO HERE"); 8 | } 9 | ``` 10 | 11 | This isn't sustainable for a few reasons. One is that code can get big. Putting a thousand lines inside of one place can be a lot, let 12 | alone the hundreds of thousands you need to be Minecraft or the millions you need to be Google. 13 | 14 | Another is that there is almost always code that you will want to run at multiple places in a program. 15 | Copy pasting that code can get old. 16 | 17 | This is what methods are for. Methods let you split up your code into smaller, reusable chunks.[^def] 18 | 19 | [^def]: The word method comes from a "method of getting things done." You might also hear methods referred to as "functions". 20 | -------------------------------------------------------------------------------- /src/methods/arguments.md: -------------------------------------------------------------------------------- 1 | # Arguments 2 | 3 | If methods always had to do the same thing each time they were run, they wouldn't be that useful. 4 | 5 | The way to customize what happens when a method is called is to have them take "arguments." 6 | Arguments let the caller of the method change what happens when a method runs. 7 | As part of a method declaration, you can include a comma separated list of "arguments" 8 | to that method. These arguments let the caller of the method change what happens when a method runs. 9 | 10 | ```java 11 | void sayHello(String name) { 12 | System.out.println("Hello " + name + "!"); 13 | } 14 | 15 | void main() { 16 | // Hello Joshua! 17 | sayHello("Joshua"); 18 | // Hello Claire! 19 | sayHello("Claire"); 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /src/methods/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | The simplest kind of method is declared by writing `void` followed by some name, `()`, and some code inside of a `{` and `}`. 4 | 5 | ```java 6 | void doThing() { 7 | System.out.println("Hello from inside a method!"); 8 | } 9 | ~ 10 | ~void main() { 11 | ~ doThing(); 12 | ~} 13 | ``` 14 | -------------------------------------------------------------------------------- /src/methods/invocation.md: -------------------------------------------------------------------------------- 1 | # Invocation 2 | 3 | Once you've declared a method you can run the code inside of it by writing the 4 | name of the method followed by `()` in a statement. 5 | 6 | ```java 7 | void doThing() { 8 | System.out.println("Hello from inside a method!"); 9 | } 10 | 11 | void main() { 12 | doThing(); 13 | } 14 | ``` 15 | 16 | Running the code in a method can be called a few things. "Running a method", "Calling a method", or "Invoking a method."[^wizard] 17 | 18 | You can call a method multiple times. If you do, then the code inside of it will be run multiple times. 19 | 20 | ```java 21 | void doThing() { 22 | System.out.println("Hello from inside a method!"); 23 | } 24 | 25 | void main() { 26 | doThing(); 27 | doThing(); 28 | } 29 | ``` 30 | 31 | [^wizard]: I like that last one because "invoking" makes me sound like a Wizard. 32 | -------------------------------------------------------------------------------- /src/methods/main.md: -------------------------------------------------------------------------------- 1 | # main 2 | 3 | The `main` method works the same as any other method. Java just treats it special by choosing to 4 | call it in order to start your programs. 5 | 6 | ```java 7 | void main() { 8 | System.out.println("Java will start here"); 9 | } 10 | ``` 11 | 12 | This means you can do anything in your `main` method you can do in any other method, including returning early. 13 | 14 | ```java 15 | void main() { 16 | int x = 5; 17 | 18 | if (x == 5) { 19 | return; 20 | } 21 | 22 | System.out.println("WONT RUN"); 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /src/methods/pure_functions.md: -------------------------------------------------------------------------------- 1 | # Pure Functions 2 | 3 | When a method only uses its arguments in order to compute a return value 4 | but doesn't otherwise change the outside world, we call those methods 5 | "pure functions." 6 | 7 | ```java 8 | // square just uses x to compute the square of x 9 | int square(int x) { 10 | return x * x; 11 | } 12 | ``` 13 | 14 | If a method changes any values non-local to it, such as by assigning values to an array, 15 | we consider it to be "impure." 16 | 17 | ```java 18 | void multiplyAllByTwo(int[] numbers) { 19 | for (int i = 0; i < numbers.length; i++) { 20 | // 21 | numbers[i] = numbers[i] * 2; 22 | } 23 | } 24 | 25 | The term "pure" comes from the notion of "pure mathematics." 26 | ``` 27 | -------------------------------------------------------------------------------- /src/methods/void.md: -------------------------------------------------------------------------------- 1 | # void 2 | 3 | All methods have to declare some return type. `void` is what you write when a method won't return any value. 4 | 5 | ```java 6 | // Returns a String 7 | String title() { 8 | return "All Night"; 9 | } 10 | 11 | // Returns an int 12 | int views() { 13 | return 4071; 14 | } 15 | 16 | // Doesn't return any value. 17 | void talkAboutVideo() { 18 | System.out.println(title() + " only has " + views() + " views."); 19 | } 20 | 21 | void main() { 22 | talkAboutVideo(); 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /src/multi_dimensional_arrays.md: -------------------------------------------------------------------------------- 1 | # Multi-Dimensional Arrays 2 | 3 | When you make an array in which each element is itself an array 4 | we call that array of arrays a "multi-dimensional array." 5 | 6 | ```java 7 | class Main { 8 | void main() { 9 | int width = 30; 10 | int height = 30; 11 | int[][] pixels = new int[width][height]; 12 | 13 | for (int i = 0; i < width; i++) { 14 | for (int j = 0; j < height; j++) { 15 | pixels[i][j] = 0; 16 | } 17 | } 18 | } 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /src/multi_file_programs.md: -------------------------------------------------------------------------------- 1 | # Multi-File Programs 2 | 3 | For many reasons, it makes sense to split programs into multiple files. 4 | 5 | This is one of those things that is easier to show than tell, so to follow along 6 | make a blank folder on your computer. 7 | 8 | ``` 9 | $ mkdir program 10 | $ cd program 11 | ``` -------------------------------------------------------------------------------- /src/multi_file_programs/file_names.md: -------------------------------------------------------------------------------- 1 | # File names 2 | 3 | When you make a file called `Ball.java` you should expect to find a class named `Ball` inside of it. 4 | 5 | This is a general rule. When you split code into multiple files each file should be 6 | a class and the name of the class should match the name of the file. 7 | 8 | So if I want to write a `Position` class 9 | 10 | ```java 11 | class Position { 12 | int x; 13 | int y; 14 | } 15 | ``` 16 | 17 | That should go in its own file named `Position.java`. -------------------------------------------------------------------------------- /src/multi_file_programs/global_fields.md: -------------------------------------------------------------------------------- 1 | # Global Fields 2 | 3 | Global fields, accordingly, were always a lie. 4 | 5 | ```java 6 | int number = 0; 7 | 8 | void main() { 9 | System.out.println(number); 10 | number++; 11 | System.out.println(number); 12 | } 13 | ``` 14 | 15 | They are just normal fields in the anonymous main class. 16 | 17 | ```java 18 | class Main { 19 | int number = 0; 20 | 21 | void main() { 22 | System.out.println(number); 23 | number++; 24 | System.out.println(number); 25 | } 26 | } 27 | ``` 28 | 29 | This means that once you move to programs in multiple files they are no longer global 30 | to your program - just the code in the main class.[^bummer] 31 | 32 | [^bummer]: Huge bummer, but we will learn how to make actually global things later. -------------------------------------------------------------------------------- /src/multi_file_programs/the_main_file.md: -------------------------------------------------------------------------------- 1 | # The Main file 2 | 3 | Inside your `src` folder make a file called `Main.java`. This is the file where 4 | we are going to write the "start" of the program. 5 | 6 | All the Java code you've written up until now will work if you put it into this file. 7 | 8 | ```java 9 | void main() { 10 | System.out.println("Hello, world!"); 11 | } 12 | ``` 13 | 14 | So you should now have something that looks like this. 15 | 16 | ``` 17 | project/ 18 | src/ 19 | Main.java 20 | ``` 21 | 22 | To run your program, use the `java` command. 23 | 24 | ``` 25 | $ java src/Main.java 26 | Hello, world! 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /src/multi_file_programs/the_sources_folder.md: -------------------------------------------------------------------------------- 1 | # The Sources folder 2 | 3 | When people work on "a project" - meaning a program made to 4 | accomplish some task - there will often be more than just Java code involved. 5 | 6 | To deal with this its common to make a folder to put Java code into. I prefer the name 7 | `src` for this. 8 | 9 | ``` 10 | $ mkdir src 11 | ``` 12 | 13 | And inside this `src` folder we will put the code.[^layouts] 14 | 15 | So you should have this 16 | 17 | ``` 18 | project/ <- Open this in your text editor 19 | src/ <- Code will go here 20 | ``` 21 | 22 | [^layouts]: There are different ways to layout a project. All are valid. You can call the `src` folder `STUFF` - it ultimately doesn't matter. This is just another one of those social conventions. 23 | 24 | -------------------------------------------------------------------------------- /src/multiple_files.md: -------------------------------------------------------------------------------- 1 | # Multiple Files 2 | -------------------------------------------------------------------------------- /src/null.md: -------------------------------------------------------------------------------- 1 | # null 2 | 3 | There is a special value called `null` which is assignable to most types. 4 | 5 | ```java 6 | void main() { 7 | String name = null; 8 | int[] numbers = null; 9 | 10 | System.out.println(name); 11 | System.out.println(numbers); 12 | } 13 | ``` 14 | 15 | The only types which `null` cannot be assigned to are `int`, `double`, `char`, and `boolean`.[^aswellas] 16 | 17 | ```java 18 | void main() { 19 | // Will not work 20 | int x = null; 21 | } 22 | ``` 23 | 24 | [^aswellas]: As well as `long`, `short`, `byte`, and `float` but I haven't shown you those yet. 25 | -------------------------------------------------------------------------------- /src/null/checking_for_null.md: -------------------------------------------------------------------------------- 1 | # Checking for null 2 | 3 | If you are unsure whether something is null, you can 4 | check by using `==`. 5 | 6 | ```java 7 | void sayHello(String firstName, String lastName) { 8 | if (lastName == null) { 9 | System.out.println("Hello " + firstName); 10 | } 11 | else { 12 | System.out.println("Hello " + firstName + " " + lastName); 13 | } 14 | } 15 | 16 | void main() { 17 | sayHello("Sonny", "Bono"); 18 | sayHello("Cher", null); 19 | } 20 | ``` -------------------------------------------------------------------------------- /src/null/field_access.md: -------------------------------------------------------------------------------- 1 | # Field Access 2 | -------------------------------------------------------------------------------- /src/null/instance_methods.md: -------------------------------------------------------------------------------- 1 | # Instance Methods 2 | -------------------------------------------------------------------------------- /src/null/null_as_absence.md: -------------------------------------------------------------------------------- 1 | # Null as Absence 2 | 3 | One way to use `null` is to have it be a stand in for when there is 4 | an "absence" of a value. 5 | 6 | Consider [Cher](https://en.wikipedia.org/wiki/Cher). Unlike most people, 7 | Cher does not have a last name. 8 | 9 | `null` is an appropriate value to use when there is such an absense. 10 | 11 | ```java 12 | ~void main() { 13 | String firstName = "Cher"; 14 | String lastName = null; 15 | 16 | System.out.println(firstName); 17 | System.out.println(lastName); 18 | ~} 19 | ``` 20 | -------------------------------------------------------------------------------- /src/null/null_as_unknown.md: -------------------------------------------------------------------------------- 1 | # Null as Unknown 2 | 3 | Another equally valid way to use `null` is to have it 4 | stand in for information that you do not yet know. 5 | 6 | If you have a program ask someone for their name, 7 | between the time you start the program and you get 8 | a response, their name is unknown to you. 9 | 10 | ```java,no_run 11 | String firstName = null; 12 | 13 | // Some lines of code 14 | 15 | firstName = askForName(); 16 | ``` 17 | 18 | This is subtly different than delayed assignment. Between when 19 | you don't know the information and when you learn it you are actually allowed 20 | to use a variable initialized to `null`. 21 | 22 | The difference between this kind of situation and a "known absence" is also subtle. 23 | In this situation you do not know what a value would be. In the other you know that there 24 | is no value to get. 25 | -------------------------------------------------------------------------------- /src/null/null_pointerexception.md: -------------------------------------------------------------------------------- 1 | # NullPointerException 2 | -------------------------------------------------------------------------------- /src/numbers/float_and_double.md: -------------------------------------------------------------------------------- 1 | # float and double 2 | -------------------------------------------------------------------------------- /src/objects.md: -------------------------------------------------------------------------------- 1 | # Object 2 | 3 | You may have heard the phrase "everything is an object" 4 | parroted about. 5 | 6 | It sounds very silly. Of course things are things, what else would they be? 7 | 8 | In Java it has a very specific meaning. There is a class named 9 | `java.lang.Object` (`Object` for short) which all other classes are 10 | derived from. 11 | 12 | Everything "is" an `Object`. -------------------------------------------------------------------------------- /src/objects/array_subtypes.md: -------------------------------------------------------------------------------- 1 | # Array Subtypes 2 | -------------------------------------------------------------------------------- /src/objects/recover_types.md: -------------------------------------------------------------------------------- 1 | # Recover Types 2 | -------------------------------------------------------------------------------- /src/objects/subclasses.md: -------------------------------------------------------------------------------- 1 | # Subclasses 2 | 3 | In the same way that all types are sub-types of `Object`, 4 | all classes are sub-classes of `Object`. -------------------------------------------------------------------------------- /src/objects/subtypes.md: -------------------------------------------------------------------------------- 1 | # Subtypes 2 | 3 | We consider most everything to be a "subtype" 4 | of `Object`. 5 | 6 | This means that if you have a variable or field that holds an `Object` 7 | you can assign any data you want into it. 8 | 9 | ```java 10 | ~void main() { 11 | String oak = "oak"; 12 | Object tree = oak; 13 | System.out.println(tree); 14 | ~} 15 | ``` 16 | 17 | If something is a subtype of `Object`, we would call `Object` 18 | its "supertype."[^super] 19 | 20 | [^super]: Super meaning above and Sub meaning below. God how I feel for people who learn 21 | english as a second language. -------------------------------------------------------------------------------- /src/objects/toString.md: -------------------------------------------------------------------------------- 1 | # toString 2 | 3 | All `Object`s have a `toString` method. 4 | 5 | This is intended to be a suitable representation for debugging, 6 | although one may choose to favor different concerns. 7 | 8 | For built-in classes the result of their `toString` method is likely 9 | what you'd expect. 10 | 11 | ```java 12 | ~class Apple {} 13 | ~void main() { 14 | Object o = "123"; 15 | 16 | // If its already a String, toString() doesn't 17 | // have to do much work 18 | System.out.println(o.toString()); 19 | 20 | o = 123; 21 | // Integers, Longs, etc. all have a representation 22 | // which looks the same as they do in literal form. 23 | System.out.println(o.toString()); 24 | 25 | o = new Apple(); 26 | // And custom classes will, by default, just have the 27 | // class name followed by gibberish 28 | System.out.println(o.toString()); 29 | ~} 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /src/objects/variance_and_casting.md: -------------------------------------------------------------------------------- 1 | # Variance and Casting 2 | 3 | While every `String` is an `Object`, not 4 | all `Object`s are `String`s. 5 | 6 | -------------------------------------------------------------------------------- /src/operating_systems.md: -------------------------------------------------------------------------------- 1 | # Operating Systems 2 | 3 | The exact electrical signals you need to send to make a computer "work" 4 | are, obviously, a bit complicated. 5 | 6 | This is where operating systems come in. Operating systems are programs that "operate" 7 | all the parts that make up your computer. -------------------------------------------------------------------------------- /src/operating_systems/game_consoles.md: -------------------------------------------------------------------------------- 1 | # Game Consoles 2 | 3 | Game Consoles generally always do their own wacky thing. 4 | 5 | For the same reasons as mobile devices, you will have a lot of trouble 6 | trying to program on a game console. They are special made to run Halo.[^age] 7 | 8 | [^age]: Yeah, Halo sucks now. Halo 3 was art. Obtuse, beautiful, orchestral art. I am old enough to have lived 9 | in the age of dreams and to know of their dimming. 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/operating_systems/mobile_phones.md: -------------------------------------------------------------------------------- 1 | # Mobile Phones 2 | 3 | Android and iOS are the major players in the mobile device world. 4 | 5 | You will find doing the tasks a programmer needs to exceedingly difficult on these. 6 | This is because the interfaces made by these operating systems are designed for use 7 | by the general public on small devices. Working with a keyboard and editing a Java 8 | program aren't tasks that are prioritized. 9 | -------------------------------------------------------------------------------- /src/operating_systems/personal_computers.md: -------------------------------------------------------------------------------- 1 | # Personal Computers 2 | 3 | For "personal computers", which I am defining as the sort of computers that have a keyboard 4 | and a screen, the most common operating system is Windows. The second most common is Mac OS. 5 | 6 | These are both produced by massive corporations in order to sell pre-installed on computers. 7 | As such, they give you a graphical interface that you navigate with a mouse/touchpad and keyboard. 8 | This is what people have found comfortable and what most are used to. 9 | 10 | To write code and do other programmer things you have to install programs but once you know what 11 | you need to install its pretty easy. -------------------------------------------------------------------------------- /src/operating_systems/servers.md: -------------------------------------------------------------------------------- 1 | # Servers 2 | 3 | For servers, the kind of machines you run in a datacenter 4 | to host websites, the most common operating system is Linux. 5 | 6 | Because so many jobs are writing websites to host on servers, you will eventually 7 | need to learn how to work with Linux. 8 | 9 | That will be a fun adventure. An adventure I implore you not to explore by bricking[^def] 10 | your family's or a school's computer trying to install Linux on it. Only mess with your own stuff. 11 | 12 | [^def]: I.E. making useless -------------------------------------------------------------------------------- /src/packages.md: -------------------------------------------------------------------------------- 1 | # Packages 2 | 3 | Every class in Java "lives" in a package. 4 | 5 | A package is a way to group individual classes. 6 | 7 | ```java,no_run 8 | package dungeon; 9 | 10 | class BugBear { 11 | 12 | } 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /src/packages/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | To put a class into a package you need to do two things. 4 | 5 | First, put a "package declaration" at the top of the file. This looks like the word `package` followed by the name of the package and a `;` 6 | 7 | ```java,no_run 8 | package dungeon; 9 | 10 | class BugBear { 11 | 12 | } 13 | ``` 14 | 15 | Then you need to make sure that the `.java` file is in a folder matching the name of 16 | that package. 17 | 18 | So, for the example above, if your code was previously laid out like this 19 | 20 | ``` 21 | src/ 22 | BugBear.java 23 | ``` 24 | 25 | It needs to be changed to this. 26 | 27 | ``` 28 | src/ 29 | dungeon/ 30 | BugBear.java 31 | ``` -------------------------------------------------------------------------------- /src/packages/import.md: -------------------------------------------------------------------------------- 1 | # Import 2 | 3 | If you don't want to write out the fully qualified class name everywhere, and few do, 4 | then you can use an `import`. 5 | 6 | To import a class you write `import` followed by the fully qualified class name. 7 | This makes it so that the "simple" class name will be usable. 8 | 9 | ```java,no_run 10 | package village; 11 | 12 | public class Villager {} 13 | ``` 14 | 15 | ```java,no_run 16 | package dungeon; 17 | 18 | // For the rest of the file, you can 19 | // just write "Villager" and Java will know 20 | // what you mean. 21 | import village.Villager; 22 | 23 | class Dwarf { 24 | Villager meet() { 25 | return new Villager(); 26 | } 27 | } 28 | ``` -------------------------------------------------------------------------------- /src/packages/package_private_constructors.md: -------------------------------------------------------------------------------- 1 | # Package-Private Constructors 2 | 3 | A constructor without any other modifier is "package-private" in the 4 | same way as methods and fields.[^private] 5 | 6 | ```java 7 | package dungeon; 8 | 9 | public class Slime { 10 | final int size; 11 | 12 | // This constructor is public, 13 | // code in other packages can use it. 14 | public Slime() { 15 | this.size = 5; 16 | } 17 | 18 | // This constructor is package-private, 19 | // code in other packages cannot use it. 20 | Slime(int size) { 21 | this.size = size; 22 | } 23 | } 24 | ``` 25 | 26 | [^private]: Your spider-sense might be tingling wondering if `private` constructors 27 | are a thing. They are! I'll talk about them more in-depth later, but they can be 28 | surprisingly useful. -------------------------------------------------------------------------------- /src/packages/package_private_fields.md: -------------------------------------------------------------------------------- 1 | # Package-Private Fields 2 | 3 | Fields that are marked neither `public` nor `private` are "package-private." 4 | 5 | ```java 6 | package village; 7 | 8 | public class Well { 9 | // Neither of these can be used outside of the "village" package 10 | static final int NUMBER_OF_DEMONS = 4; 11 | boolean exorcismPerformed; 12 | } 13 | ``` -------------------------------------------------------------------------------- /src/packages/package_private_methods.md: -------------------------------------------------------------------------------- 1 | # Package-Private Methods 2 | 3 | If a method is neither `public` or `private` then it can 4 | be used only by code in the same package. 5 | 6 | We call these methods "package-private" because they are 7 | "private" to code outside the package. 8 | 9 | ```java 10 | package village; 11 | 12 | public class Villager { 13 | void isNotVisible() { 14 | System.out.println(""" 15 | This method can be called from code in the 'village' 16 | package, but not from other packages. 17 | """); 18 | } 19 | } 20 | ``` 21 | 22 | Which again applies to static methods as well. 23 | -------------------------------------------------------------------------------- /src/packages/public_classes.md: -------------------------------------------------------------------------------- 1 | # Public Classes 2 | 3 | To be able to use a class in one package from a different package, 4 | you must first mark that class as `public`. 5 | 6 | ```java,no_run 7 | package village; 8 | 9 | // Now other packages will be able to see it 10 | public class Villager {} 11 | ``` -------------------------------------------------------------------------------- /src/packages/public_constructors.md: -------------------------------------------------------------------------------- 1 | # Public Constructors 2 | 3 | For a constructor you write to be usable across packages[^youguessed] it needs 4 | to be marked `public`. 5 | 6 | ```java,no_run 7 | package dungeon; 8 | 9 | public class Skeleton { 10 | public final int bones; 11 | 12 | public Skeleton() { 13 | this.bones = 206; 14 | } 15 | } 16 | ``` 17 | 18 | ```java,no_run 19 | package village; 20 | 21 | import dungeon.Skeleton; 22 | 23 | class Main { 24 | void main() { 25 | // Now this works 26 | var skeleton = new Skeleton(); 27 | 28 | // And we get the right number of bones! 29 | System.out.println(skeleton.bones); 30 | } 31 | } 32 | ``` 33 | 34 | 35 | [^youguessed]: You guessed it! -------------------------------------------------------------------------------- /src/packages/public_fields.md: -------------------------------------------------------------------------------- 1 | # Public Fields 2 | 3 | Similarly to methods, for a field to be used from a different package 4 | it must be marked `public`. 5 | 6 | ```java 7 | package village; 8 | 9 | public class Well { 10 | // Both of these you can use from a different package 11 | public static final int DEPTH = 10; 12 | public int remainingWater; 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /src/packages/subpackages.md: -------------------------------------------------------------------------------- 1 | # Subpackages 2 | 3 | Packages can also have subpackages. 4 | 5 | What this looks like is for any package with a `.` in its name - say `my.fun.project` - 6 | you need a new folder. 7 | 8 | So if you have a class like this 9 | 10 | ```java 11 | package my.fun.project; 12 | 13 | public class Apple {} 14 | ``` 15 | 16 | It should be in a folder structure like this 17 | 18 | ``` 19 | src/ 20 | my/ 21 | fun/ 22 | project/ 23 | Apple.java 24 | ``` 25 | 26 | And the fully qualified class name would be `my.fun.project.Apple`. -------------------------------------------------------------------------------- /src/packages/the_anonymous_main_class.md: -------------------------------------------------------------------------------- 1 | # The Anonymous Main Class 2 | 3 | You are only allowed to make an anonymous main class 4 | inside the default package. 5 | 6 | ```java,no_run 7 | // Allowed 8 | void main() { 9 | System.out.println("Hello, world"); 10 | } 11 | ``` 12 | 13 | ```java,does_not_compile 14 | // Not Allowed 15 | package myprogram; 16 | 17 | void main() { 18 | System.out.println("Hello, world"); 19 | } 20 | ``` 21 | 22 | This means that for classes in packages you have to wrap them in 23 | an explicitly named class like everything else. 24 | 25 | ```java,no_run 26 | // Allowed 27 | package myprogram; 28 | 29 | class Main { 30 | void main() { 31 | System.out.println("Hello, world"); 32 | } 33 | } 34 | ``` -------------------------------------------------------------------------------- /src/packages/the_default_package.md: -------------------------------------------------------------------------------- 1 | # The Default Package 2 | 3 | When your classes don't have a package declaration, we say those are in the "default package." 4 | 5 | ```java,no_run 6 | // No package declaration means default package 7 | public class Elf { 8 | 9 | } 10 | ``` 11 | 12 | Classes in the default package cannot be imported by classes 13 | in named packages, regardless of if those classes are public. 14 | 15 | ```java,no_run 16 | package villager; 17 | 18 | public class Villager { 19 | // No way to reference Elf directly, 20 | // even if Elf is public 21 | } 22 | ``` 23 | 24 | Because of this restriction[^andmore] you will mostly use the default package 25 | when you are feeling lazy or are making a smaller program. 26 | 27 | [^andmore]: And more to come! -------------------------------------------------------------------------------- /src/packages/visibility.md: -------------------------------------------------------------------------------- 1 | # Visibility 2 | 3 | By default, a class can only see the other classes 4 | in its package. 5 | 6 | ```java,no_run 7 | package dungeon; 8 | 9 | class BugBear { 10 | 11 | } 12 | ``` 13 | 14 | ```java,no_run 15 | package village; 16 | 17 | class Villager { 18 | 19 | } 20 | ``` 21 | 22 | ```java,no_run 23 | package dungeon; 24 | 25 | class Dwarf { 26 | BugBear fight() { 27 | // Can "see" BugBear and thus call its constructor, 28 | // access visible fields and methods, etc. 29 | return new BugBear(); 30 | } 31 | 32 | // Cannot see Villager because it is in a different package. 33 | } 34 | ``` -------------------------------------------------------------------------------- /src/prelude/lies.md: -------------------------------------------------------------------------------- 1 | # Lies 2 | 3 | At various points in this book I am also going to lie to you. Specifically I will 4 | make lies of omission. 5 | 6 | If there are five ways to do something, I might pretend that there is only one 7 | way to do it until I give you enough context so that I can talk about the other 8 | four. 9 | 10 | This can be particularly annoying if you are in a course that is teaching things 11 | in a different order or if you feel rushed to just get some project done. 12 | 13 | I get that. I just ask that you trust me and go in the sequence I am laying out. 14 | I am honestly trying to make it so that you end with a stronger understanding than 15 | you would have otherwise. 16 | 17 | There is the question mark in the top right of every page. 18 | -------------------------------------------------------------------------------- /src/prelude/toy_problems.md: -------------------------------------------------------------------------------- 1 | # Toy Problems 2 | 3 | As you go through this book there will be a lot of what can be considered "toy problems." 4 | 5 | That is, you will be shown or asked to write programs that have no obvious real world use. 6 | They will be similar in spirit to math problems like "if you have 8 apples and I take 3, how many apples do you have left?" 7 | 8 | The intent is not for these to be annoying, although I am sure they will be. The intent is for these problems to help you build an understanding of mechanics and structure. 9 | -------------------------------------------------------------------------------- /src/primitive_types.md: -------------------------------------------------------------------------------- 1 | # Primitive Types 2 | -------------------------------------------------------------------------------- /src/records.md: -------------------------------------------------------------------------------- 1 | # Records 2 | 3 | If you have a class whose only purpose is to ferry data around, 4 | you can instead use a `record`. 5 | 6 | ```java 7 | record Person(String name, int age) {} 8 | ``` -------------------------------------------------------------------------------- /src/records/check_for_equality.md: -------------------------------------------------------------------------------- 1 | # Check for Equality 2 | 3 | To check if the components of a record match with another, you can use the `equals` 4 | method. 5 | 6 | ```java 7 | record Elf(boolean pretentious) {} 8 | ``` 9 | ```java 10 | ~record Elf(boolean pretentious) {} 11 | class Main { 12 | void main() { 13 | var elfOne = new Elf(true); 14 | var elfTwo = new Elf(true); 15 | 16 | System.out.println(elfOne.equals(elfTwo)); 17 | } 18 | } 19 | ``` 20 | 21 | This is similar to how you check whether `String`s are equal. -------------------------------------------------------------------------------- /src/records/component_accessor_visibility.md: -------------------------------------------------------------------------------- 1 | # Component Accessor Visibility 2 | 3 | The accessor methods of a record are always public, so all the packages 4 | that can see the class can access its components. 5 | 6 | ```java,no_run 7 | package dungeon; 8 | 9 | public record Dragon(double wingspan) {} 10 | ``` 11 | 12 | ```java,no_run 13 | import dungeon.Dragon; 14 | 15 | void main() { 16 | var dragon = new Dragon(224.5); 17 | System.out.println( 18 | // Method is visible. 19 | dragon.wingspan() 20 | ); 21 | } 22 | ``` -------------------------------------------------------------------------------- /src/records/component_accessors.md: -------------------------------------------------------------------------------- 1 | # Component Accessors 2 | 3 | For each record component, an accessor 4 | method will be available that has the name of that component. 5 | 6 | You use these to access the values of components. 7 | 8 | ```java,no_run 9 | record Dog(String name) {} 10 | ``` 11 | 12 | ```java 13 | ~record Dog(String name) {} 14 | class Main { 15 | void main() { 16 | var dog = new Dog("Hunter"); 17 | 18 | // .name() accessor is available 19 | String name = dog.name(); 20 | 21 | System.out.println(name); 22 | } 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /src/records/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | To declare a record you write the word `record` followed by a 4 | class name, a list of "record components" in parentheses, and a pair of `{}`. 5 | 6 | The list of record components should be reminiscent of function arguments. 7 | 8 | ```java 9 | record Person(String name, int age) {} 10 | ``` 11 | 12 | Having an empty list of record components is also allowed.[^astowhy] 13 | 14 | ```java 15 | record Pants() {} 16 | ``` 17 | 18 | [^astowhy]: As to why you might want to give an empty list of record components, 19 | its nuanced. For now its just for fun. -------------------------------------------------------------------------------- /src/records/printing_a_record.md: -------------------------------------------------------------------------------- 1 | # Printing a Record 2 | 3 | When printing out a record, the output will include 4 | each of the components of the record. 5 | 6 | ```java 7 | record Goblin(String name, int hp) {} 8 | ``` 9 | ```java 10 | ~record Goblin(String name, int hp) {} 11 | class Main { 12 | void main() { 13 | var goblin = new Goblin("Gobbo", 11); 14 | 15 | System.out.println(goblin); 16 | } 17 | } 18 | ``` 19 | ``` 20 | Goblin[name=Gobbo, hp=11] 21 | ``` 22 | 23 | This is more intelligable than what you would get by default from a regular class.[^possible] 24 | 25 | ``` 26 | Goblin@609db43b 27 | ``` 28 | 29 | [^possible]: It is possible to make a regular class print differently, but we'll get to that later. -------------------------------------------------------------------------------- /src/records/the_canonical_constructor.md: -------------------------------------------------------------------------------- 1 | # The Canonical Constructor 2 | 3 | A record is always given a constructor which matches 4 | its list of record components. 5 | 6 | ```java,no_run 7 | record Person(String name, int age) {} 8 | 9 | void main() { 10 | // This call to new Person(...) matches up with 11 | // the record declaration. 12 | var person = new Person("Ancient Dragon Man", 2000); 13 | } 14 | ``` 15 | 16 | Similar to the "default constructor" given to regular classes, this 17 | is what you get for "free" with the declaration of a record. -------------------------------------------------------------------------------- /src/records/why.md: -------------------------------------------------------------------------------- 1 | # Why 2 | -------------------------------------------------------------------------------- /src/recur: -------------------------------------------------------------------------------- 1 | # Accumulators 2 | -------------------------------------------------------------------------------- /src/recursion.md: -------------------------------------------------------------------------------- 1 | # Recursion 2 | 3 | In a method you can call another method. 4 | 5 | ```java 6 | void doOtherThing() { 7 | System.out.println("B"); 8 | } 9 | 10 | void doThing() { 11 | System.out.println("A"); 12 | } 13 | 14 | void main() { 15 | doThing(); 16 | } 17 | ``` 18 | 19 | This is at the foundation of most code so should, at this point, 20 | be a given. 21 | 22 | What might not be obvious is that you can call the method currently running. 23 | 24 | ```java 25 | void countDown(int value) { 26 | System.out.println(value); 27 | if (value > 0) { 28 | countDown(value - 1); 29 | } 30 | } 31 | 32 | void main() { 33 | countDown(10); 34 | } 35 | ``` 36 | 37 | This is what we call "recursion." -------------------------------------------------------------------------------- /src/recursion/base_case.md: -------------------------------------------------------------------------------- 1 | # Base Case 2 | 3 | The general structure of a recursive method is that 4 | it will sometimes call itself and sometimes not. 5 | 6 | This makes sense if you think about it. If it always called 7 | itself, it would never stop calling itself and run forever. 8 | 9 | We call the case where the function will not call itself 10 | a "base case" 11 | 12 | ```java,no_run 13 | if () { 14 | 15 | } 16 | else { 17 | // The base case 18 | return ; 19 | } 20 | ``` -------------------------------------------------------------------------------- /src/recursion/base_cases.md: -------------------------------------------------------------------------------- 1 | # Base Cases 2 | -------------------------------------------------------------------------------- /src/recursion/comparison_to_delegation.md: -------------------------------------------------------------------------------- 1 | # Comparison to Delegation 2 | 3 | A related technique to recursion is "delegation." 4 | 5 | This is when you have one method call a different airity 6 | version of itself. 7 | 8 | ```java 9 | // This method is delegated to 10 | void seasonFood(int shakes) { 11 | for (int i = 0; i < shakes; i++) { 12 | System.out.println("1 shake of pepper"); 13 | } 14 | } 15 | 16 | // by this method, which provides a "default" value of 2 17 | void seasonFood() { 18 | seasonFood(2); 19 | } 20 | 21 | void main() { 22 | seasonFood(); 23 | } 24 | ``` 25 | 26 | This is distinct from recursion since, while the method delegated to 27 | might have the same name as the one delegating, different 28 | overloads of methods are considered distinct methods. 29 | 30 | `void seasonFood()` is therefore a different method than `void seasonFood(int)`. -------------------------------------------------------------------------------- /src/recursion/disclaimer.md: -------------------------------------------------------------------------------- 1 | # Disclaimer 2 | 3 | Recursion will be annoying to learn. 4 | 5 | Sorry. 6 | 7 | Its not because its particuarly hard or because its 8 | beyond your ken. Its just that when you learn loops first, recursion 9 | tends to be harder to learn than if you started with it. 10 | 11 | The good news is that once you get it, after however much 12 | mental anguish, you won't forget it. And it will be useful, however occasionally. -------------------------------------------------------------------------------- /src/recursion/recursing_over_arrays.md: -------------------------------------------------------------------------------- 1 | # Recurse Over an Array 2 | -------------------------------------------------------------------------------- /src/recursion/recursing_over_strings.md: -------------------------------------------------------------------------------- 1 | # Recurse Over a String 2 | 3 | To write a recursive function which acts over each character 4 | of a `String` you need to do much the same task as with regular loops, 5 | just by having your "current index" be a parameter to the -------------------------------------------------------------------------------- /src/reflection.md: -------------------------------------------------------------------------------- 1 | # Reflection 2 | 3 | Reflection is the what we call it when a program 4 | uses information about how it - the program - is structured 5 | in order to do things while running. 6 | 7 | We call it reflection because its as if your code 8 | looks into a mirror and sees its own reflection.[^whenhumans] 9 | 10 | [^whenhumans]: When a human looks into a mirror they might see their own eye color. 11 | If a mirror weren't there it would be difficult to know such things. -------------------------------------------------------------------------------- /src/return_values.md: -------------------------------------------------------------------------------- 1 | # Return 2 | 3 | If the only thing you could do with methods was to call them, 4 | they would have limited uses. 5 | 6 | This is why methods can also "return" results to the code that calls 7 | them. 8 | 9 | ```java,no_run 10 | int plusOne(int x) { 11 | return x + 1; 12 | } 13 | ``` 14 | -------------------------------------------------------------------------------- /src/return_values/conversion.md: -------------------------------------------------------------------------------- 1 | # Conversion 2 | 3 | When a value is returned, Java will want to coerce it into 4 | the type of value that the method says it returns. 5 | 6 | If Java knows how to do that conversion, then it can happen automatically. 7 | 8 | ```java 9 | // This method declares a return type of double. 10 | double returnFive() { 11 | // x is an int 12 | int x = 5; 13 | // When it is returned, it will be turned into a double 14 | return x; 15 | } 16 | ``` 17 | 18 | But if that conversion might potentially be lossy or, as with converting `double`s to `int`s, 19 | you must do it yourself. 20 | 21 | ```java 22 | double returnNine() { 23 | double nine = 9.0; 24 | // The (int) explicitly converts the double to an int 25 | return (int) nine; 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /src/return_values/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | 4 | The return type of a method is written to the left of the name of the method. 5 | 6 | To have a method which returns an `int`, you write `int methodName`. 7 | 8 | ```java,no_run 9 | int returnsEight() { 10 | return 8; 11 | } 12 | ``` 13 | 14 | To have a method with returns a `String`, you write `String methodName`. 15 | 16 | ```java,no_run 17 | String getName() { 18 | return "bob"; 19 | } 20 | ``` 21 | 22 | And so on for any type in Java. -------------------------------------------------------------------------------- /src/return_values/early_return.md: -------------------------------------------------------------------------------- 1 | # Early Return 2 | 3 | -------------------------------------------------------------------------------- /src/return_values/exhaustiveness.md: -------------------------------------------------------------------------------- 1 | # Exhaustiveness 2 | 3 | 4 | When a method returns data, Java needs to know that no matter what happens 5 | in the method there will be some `return` line reached. 6 | 7 | 8 | ```java,no_run,does_not_compile 9 | int compute(int x) { 10 | if (x < 0) { 11 | return 5; 12 | } 13 | // Error! No return if x >= 0 14 | } 15 | ``` 16 | 17 | ```java,no_run 18 | int compute(int x) { 19 | // Both "branches" have returns, so all is well 20 | if (x < 0) { 21 | return 5; 22 | } 23 | else { 24 | return 1; 25 | } 26 | } 27 | ``` 28 | 29 | We call this property, whether in every situation a method will return a value, "exhaustiveness." 30 | If there could be cases where no return statement is reached, that is "non-exhaustive" and Java 31 | won't accept your code. 32 | -------------------------------------------------------------------------------- /src/return_values/impure_functions.md: -------------------------------------------------------------------------------- 1 | # Impure Functions 2 | -------------------------------------------------------------------------------- /src/return_values/return.md: -------------------------------------------------------------------------------- 1 | # Return 2 | -------------------------------------------------------------------------------- /src/return_values/return_in_void_methods.md: -------------------------------------------------------------------------------- 1 | # Return in void methods 2 | 3 | In `void` methods, you can still exit early with a `return` statement, but you do not give any 4 | value after it. 5 | 6 | ```java 7 | void doStuff() { 8 | int i = 0; 9 | while (true) { 10 | if (i == 8) { 11 | return; 12 | } 13 | 14 | System.out.println(i); 15 | } 16 | } 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /src/return_values/return_statement.md: -------------------------------------------------------------------------------- 1 | # Return Statement 2 | 3 | Whenever the code in a method reaches a line that looks like `return ;`, that method 4 | will immediately exit. 5 | 6 | This will exit out of any loops, similarly to a `break`. 7 | 8 | ```java,no_run 9 | int doMath() { 10 | int x = 0; 11 | while (true) { 12 | x++; 13 | 14 | if (x == 8) { 15 | return x; 16 | } 17 | } 18 | 19 | // Needed because Java isn't smart enough to know 20 | // that the while loop will always reach the return x; 21 | // line. 22 | return 0; 23 | } 24 | ``` 25 | 26 | We call this kind of line a return statement. 27 | -------------------------------------------------------------------------------- /src/return_values/return_values.md: -------------------------------------------------------------------------------- 1 | # Return Values 2 | 3 | You can use a method call on the right hand side of an `=` to get the value returned by the method. 4 | 5 | ```java 6 | int returnsEight() { 7 | return 8; 8 | } 9 | 10 | void main() { 11 | int value = returnsEight(); 12 | System.out.println(value); 13 | } 14 | ``` 15 | 16 | The method call can also be used directly in expressions without assigning the value to a variable first. 17 | 18 | ```java 19 | String returnsName() { 20 | return "Mariah"; 21 | } 22 | 23 | void main() { 24 | System.out.println(returnsName() + " is my name"); 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /src/return_values/unreachable_statements.md: -------------------------------------------------------------------------------- 1 | # Unreachable Statements 2 | 3 | If Java can figure out that some line of code is unreachable because it will always come after a 4 | `return`, then it will not run your code. 5 | 6 | ```java 7 | void doThing() { 8 | System.out.println("A"); 9 | return; 10 | // unreachable statement 11 | System.out.println("B"); 12 | } 13 | 14 | void main() { 15 | doThing(); 16 | } 17 | ``` 18 | 19 | Java is easy to trick though.[^trick] 20 | 21 | ```java 22 | void doThing() { 23 | System.out.println("A"); 24 | if (true) { 25 | return; 26 | } 27 | System.out.println("B"); 28 | } 29 | 30 | void main() { 31 | doThing(); 32 | } 33 | ``` 34 | 35 | [^trick]: This _will_ always return before the `println`, but Java chooses to not figure that out. It can't be smart enough to see through every `if`, so it doesn't try for any of them. 36 | -------------------------------------------------------------------------------- /src/return_values/void.md: -------------------------------------------------------------------------------- 1 | # void 2 | 3 | All methods have to declare some return type. `void` is what you write when a method won't return any value. 4 | 5 | ```java 6 | // Returns a String 7 | String title() { 8 | return "All Night"; 9 | } 10 | 11 | // Returns an int 12 | int views() { 13 | return 4071; 14 | } 15 | 16 | // Doesn't return any value. 17 | void talkAboutVideo() { 18 | System.out.println(title() + " only has " + views() + " views."); 19 | } 20 | 21 | // This is what the void in "void main()" means 22 | void main() { 23 | talkAboutVideo(); 24 | } 25 | ``` -------------------------------------------------------------------------------- /src/standard_input.md: -------------------------------------------------------------------------------- 1 | # Standard Input 2 | 3 | Programs are pretty boring if they just make a machine warm and do some math. 4 | 5 | There are a lot of ways to make a program interactive, but the easiest is to read 6 | from what is called "standard input." 7 | 8 | This function will be added to Java in a future version, but until then 9 | copy paste this at the very top of all the code in this section. 10 | 11 | ```java,no_run 12 | import java.util.Scanner; 13 | 14 | Scanner scanner = new Scanner(System.in); 15 | 16 | String input(String message) { 17 | System.out.print(message); 18 | return scanner.nextLine(); 19 | } 20 | ``` -------------------------------------------------------------------------------- /src/standard_input/interpreting_input.md: -------------------------------------------------------------------------------- 1 | # Interpreting Input 2 | 3 | When you call `input` the human on the other side can type whatever they want. 4 | 5 | This means that, depending on the question you asked, you might need to interpret 6 | what they typed as something other than a generic `String`. 7 | 8 | In its most basic form this will look like seeing if one `String` equals another `String`. 9 | 10 | ```java,no_run 11 | ~import java.util.Scanner; 12 | ~ 13 | ~Scanner scanner = new Scanner(System.in); 14 | ~ 15 | ~String input(String message) { 16 | ~ System.out.print(message); 17 | ~ return scanner.nextLine(); 18 | ~} 19 | ~ 20 | void main() { 21 | while (true) { 22 | String shouldExit = input("Exit the program? (y/n)"); 23 | if (shouldExit.equals("y")) { 24 | break; 25 | } 26 | } 27 | } 28 | ``` -------------------------------------------------------------------------------- /src/standard_input/prompting.md: -------------------------------------------------------------------------------- 1 | # input 2 | 3 | To prompt a user for information you use the `input` function. 4 | 5 | The `input` function takes a `String` to output as a prompt. This will 6 | work the same as if the `String` was passed to `System.out.print`. 7 | 8 | The program will then wait until a human types some text and clicks the enter key. 9 | Whatever they typed will be returned to the program as a `String`. 10 | 11 | ```java,no_run 12 | ~import java.util.Scanner; 13 | ~ 14 | ~Scanner scanner = new Scanner(System.in); 15 | ~ 16 | ~String input(String message) { 17 | ~ System.out.print(message); 18 | ~ return scanner.nextLine(); 19 | ~} 20 | ~ 21 | void main() { 22 | String name = input("What is your name? "); 23 | System.out.println("Hello, " + name); 24 | } 25 | ``` -------------------------------------------------------------------------------- /src/static_fields.md: -------------------------------------------------------------------------------- 1 | # Static Fields 2 | 3 | To have a field be truly global for your program you can mark it as static. 4 | 5 | ```java 6 | class Count { 7 | static int value; 8 | } 9 | ``` 10 | 11 | -------------------------------------------------------------------------------- /src/static_fields/constants.md: -------------------------------------------------------------------------------- 1 | # Constants 2 | 3 | Because static fields are global to the entire program, they are the 4 | preferred mechanism for storing "constants." 5 | 6 | Constants are things that you don't expect to change, so you would also 7 | mark such fields as `final`. 8 | 9 | ```java 10 | class MathConstants { 11 | static final double PI = 3.14; 12 | } 13 | 14 | // Then in other parts of your code you can reference MathConstants.PI 15 | ``` 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/static_fields/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | To declare a field as static, add the `static` keyword to its declaration. 4 | 5 | ```java 6 | class Count { 7 | static int value; 8 | } 9 | ``` 10 | 11 | -------------------------------------------------------------------------------- /src/static_fields/meaning.md: -------------------------------------------------------------------------------- 1 | # Meaning 2 | -------------------------------------------------------------------------------- /src/static_fields/naming.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | For static final fields people generally name them the same way you would an enum - `LIKE_THIS`. 4 | 5 | ```java 6 | class Constants { 7 | static final int DAYS_IN_A_WEEK = 7; 8 | static final int WEEKS_IN_A_YEAR = 52; 9 | } 10 | ``` 11 | 12 | Because you will get yelled at for using a non-final static field no matter what you do, the rules there are less strict. You can name them in all caps or like a normal variable 13 | depending on personal preference. 14 | 15 | ```java 16 | class Counter { 17 | // The people who would be mad at you for the first 18 | // will probably already be mad at you for the second. 19 | static int value = 0; 20 | static int VALUE = 0; 21 | } 22 | ``` -------------------------------------------------------------------------------- /src/static_fields/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | To use a static field within the class it is declared you just need to write the name of the field. 4 | 5 | ```java 6 | class Main { 7 | static int count = 0; 8 | 9 | void main() { 10 | System.out.println(count); 11 | } 12 | } 13 | ``` 14 | 15 | To use it from another class or to disambiguate it from a regular field with the same 16 | name, you should prefix it with the name of the class it is declared in plus a `.`. 17 | 18 | 19 | ```java 20 | class Main { 21 | static int count = 0; 22 | 23 | void main() { 24 | System.out.println(Main.count); 25 | } 26 | } 27 | ``` -------------------------------------------------------------------------------- /src/static_methods.md: -------------------------------------------------------------------------------- 1 | # Static Methods 2 | 3 | If you want to be able to call a method from anywhere in your program you 4 | can use a `static` method. 5 | 6 | ```java,no_run 7 | class MyMath { 8 | static int add(int a, int b) { 9 | return a + b; 10 | } 11 | } 12 | ``` 13 | ```java 14 | ~class MyMath { 15 | ~ static int add(int a, int b) { 16 | ~ return a + b; 17 | ~ } 18 | ~} 19 | class Main { 20 | void main() { 21 | int result = MyMath.add(1, 2); 22 | System.out.println(result); 23 | } 24 | } 25 | ``` -------------------------------------------------------------------------------- /src/static_methods/declaration.md: -------------------------------------------------------------------------------- 1 | # Declaration 2 | 3 | Same as `static` fields, to mark a method as `static` you write the word `static` 4 | before it. 5 | 6 | ```java,no_run 7 | class MyMath { 8 | static int add(int a, int b) { 9 | return a + b; 10 | } 11 | } 12 | ``` -------------------------------------------------------------------------------- /src/static_methods/math.md: -------------------------------------------------------------------------------- 1 | # Math 2 | 3 | One of the most "obvious" usages for static methods is when doing things 4 | that are math or math-like. 5 | 6 | ```java,no_run 7 | class MyMath { 8 | static int add(int a, int b) { 9 | return a + b; 10 | } 11 | } 12 | ``` 13 | 14 | These sorts of methods have a result computed solely from their inputs, so needing 15 | an instance of a class to call them would be silly. 16 | 17 | The `Math` class that comes with Java has methods that work in this way. `Math.max(a, b)` 18 | is `static` and therefore usable everywhere you want the maximum of two numbers.[^more] 19 | 20 | [^more]: There are way more on there. [Take a look](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Math.html). -------------------------------------------------------------------------------- /src/static_methods/naming.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | Unlike static fields, which get new socially accepted naming rules, 4 | you name static methods the same as any other method. 5 | 6 | ```java 7 | class Naming { 8 | static void nameLikeNormal() { 9 | 10 | } 11 | } 12 | ``` -------------------------------------------------------------------------------- /src/static_methods/scope.md: -------------------------------------------------------------------------------- 1 | # Scope 2 | 3 | In the definition of a static method you can use variables like normal 4 | and you can reference other static fields and methods. 5 | 6 | ```java,no_run 7 | class ScopeExample { 8 | static final int CAN_ACCESS = 3.14; 9 | 10 | static void canCall() { 11 | } 12 | 13 | static void doStuff() { 14 | canCall(); 15 | System.out.println(ScopeExample.CAN_ACCESS); 16 | } 17 | } 18 | ``` 19 | 20 | But you cannot access any non-static methods or fields. They are not in scope. 21 | 22 | ```java,no_run,does_not_compile 23 | class ScopeExample2 { 24 | final int CANNOT_ACCESS = 3.14; 25 | 26 | void cannotCall() { 27 | } 28 | 29 | static void doStuff() { 30 | cannotCall(); 31 | System.out.println( 32 | CANNOT_ACCESS 33 | ); 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /src/static_methods/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | You use a static method by writing the name of the class where it is 4 | defined followed by `.` and the method name. 5 | 6 | ```java 7 | class StuffDoer { 8 | static void doStuff() { 9 | System.out.println("Doing stuff"); 10 | } 11 | } 12 | ``` 13 | 14 | ```java 15 | ~class StuffDoer { 16 | ~ static void doStuff() { 17 | ~ System.out.println("Doing stuff"); 18 | ~ } 19 | ~} 20 | ~ 21 | void main() { 22 | StuffDoer.doStuff(); 23 | } 24 | ``` -------------------------------------------------------------------------------- /src/string_builder.md: -------------------------------------------------------------------------------- 1 | # StringBuilder 2 | 3 | When you add `String`s together, the result is a new `String`. 4 | 5 | ```java 6 | void main() { 7 | String a = "a"; 8 | String b = "b"; 9 | String ab = a + b; 10 | 11 | System.out.println(ab); 12 | } 13 | ``` 14 | 15 | This is perfectly fine and what you would expect, but if you are adding strings 16 | together in a loop it can become an issue. 17 | 18 | ```java 19 | ``` -------------------------------------------------------------------------------- /src/strings.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | The `String` data type is used to represent text. 4 | 5 | ```java,no_run 6 | String shortStory = "Everyone lived happily ever after, the end." 7 | ``` 8 | 9 | The word "string" comes from the fact that text is just individual characters "strung together". 10 | 11 | As a concrete example `j`, `o`, and `e` can be "strung together" into the "string" 12 | `joe`. 13 | -------------------------------------------------------------------------------- /src/strings/accessing_characters.md: -------------------------------------------------------------------------------- 1 | # Accessing Characters 2 | -------------------------------------------------------------------------------- /src/strings/characters.md: -------------------------------------------------------------------------------- 1 | # Characters 2 | 3 | `String`s can represent any "string of characters", there is a seperate data type 4 | for individual characters. 5 | 6 | ```java 7 | char c = 'a'; 8 | ``` 9 | -------------------------------------------------------------------------------- /src/strings/equality.md: -------------------------------------------------------------------------------- 1 | # Equality 2 | 3 | You can check if two `String`s have the same contents by using `.equals`. 4 | 5 | ```java 6 | ~void main() { 7 | String lyricOne = "Green, Green, Dress"; 8 | String lyricTwo = "Green, Green, Dress"; 9 | 10 | boolean areSameLyric = lyricOne.equals(lyricTwo); 11 | boolean isMyName = lyricOne.equals("Bop Bop"); 12 | 13 | System.out.println(areSameLyric); 14 | System.out.println(isMyName); 15 | ~} 16 | ``` 17 | 18 | You write one `String` on the left, `.equals`, and then the `String` you want to check it 19 | against inside of parentheses. 20 | 21 | To see if strings have different contents, you need to use the not operator (`!`) on 22 | the result of `.equals`. 23 | 24 | ```java 25 | ~void main() { 26 | String bow = "bow"; 27 | String wow = "WOW"; 28 | 29 | boolean areNotSame = !bow.equals(wow); 30 | 31 | System.out.println(areNotSame); 32 | ~} 33 | ``` 34 | -------------------------------------------------------------------------------- /src/strings/escaped_characters.md: -------------------------------------------------------------------------------- 1 | # Escaped Characters 2 | -------------------------------------------------------------------------------- /src/strings/length.md: -------------------------------------------------------------------------------- 1 | # Length 2 | 3 | The number of `char`s which comprise a `String` can be accessed by using `.length()`.[^codepoints] 4 | 5 | ```java 6 | ~void main() { 7 | String fruit = "strawberry"; 8 | int numberOfChars = fruit.length(); 9 | 10 | // strawberry is 10 characters long 11 | System.out.println( 12 | fruit + " is " + numberOfChars + " characters long" 13 | ); 14 | ~} 15 | ``` 16 | 17 | [^codepoints]: This is different from the number of unicode codepoints. 18 | -------------------------------------------------------------------------------- /src/strings/string_literals.md: -------------------------------------------------------------------------------- 1 | # String Literals 2 | 3 | In order to write text in a program, you surround it with 4 | double quotes. 5 | 6 | ```java,no_run 7 | "Hello, World" 8 | ``` 9 | 10 | This is called a "string literal." It has the same relationship to `String` 11 | that an integer literal like `123` has to `int`. 12 | 13 | ```java 14 | ~void main() { 15 | // Same as this "integer literal" is used to write a number 16 | int abc = 123; 17 | // A "string literal" is used to write text 18 | String name = "penelope"; 19 | ~} 20 | ``` 21 | -------------------------------------------------------------------------------- /src/strings_ii.md: -------------------------------------------------------------------------------- 1 | # Strings II 2 | 3 | If you haven't already, you will eventually realize that `String`s are 4 | one of the most common data types you will use. 5 | 6 | As such, its worth it to keep revisiting the things you can do with them. 7 | Expect more sections like this the deeper you get. -------------------------------------------------------------------------------- /src/strings_ii/UPPERCASE.md: -------------------------------------------------------------------------------- 1 | # UPPERCASE 2 | 3 | Similarly, if you have a `String` which potentially contains lower-cased letters, you can get a new `String` with everything 4 | transformed into lower-case using the `.toUpperCase()` method. 5 | 6 | ```java 7 | void main() { 8 | String message = "Happy Valentines Day"; 9 | 10 | String upperCased = message.toUpperCase(); 11 | System.out.println(upperCased); 12 | } 13 | ``` 14 | 15 | This does not change the original `String` in place. It just makes a new `String` with all upper-case letters. -------------------------------------------------------------------------------- /src/strings_ii/check_if_blank.md: -------------------------------------------------------------------------------- 1 | # Check if blank 2 | 3 | You can check if a `String` is blank by using the `.isBlank` method. 4 | 5 | The difference is that an empty `String` has actually zero characters. A blank `String` 6 | is can have characters, so long as those characters are what we would consider whitespace. 7 | That is, things like spaces and newlines. 8 | 9 | ```java 10 | void main() { 11 | String brainSounds = """ 12 | 13 | 14 | 15 | """; 16 | 17 | // false 18 | System.out.println(brainSounds.isEmpty()); 19 | 20 | // true 21 | System.out.println(brainSounds.isBlank()); 22 | } 23 | ``` -------------------------------------------------------------------------------- /src/strings_ii/check_if_empty.md: -------------------------------------------------------------------------------- 1 | # Check if empty 2 | 3 | You can check if a `String` is empty in a few ways. 4 | 5 | The one you should already have been able to figure out[^noshame] is that you can get the `.length` of a `String` 6 | and see if that is zero. 7 | 8 | ```java 9 | void main() { 10 | String textMessages = ""; 11 | System.out.println( 12 | textMessages.length() == 0 13 | ); 14 | } 15 | ``` 16 | 17 | But another is to use the explicitly defined `.isEmpty()` method. 18 | 19 | ```java 20 | void main() { 21 | String textMessages = ""; 22 | System.out.println( 23 | textMessages.isEmpty() 24 | ); 25 | } 26 | ``` 27 | 28 | This can be more convenient. Both to write, as it is fewer characters to type, and to read later on. 29 | 30 | [^noshame]: Again, no shame if not. I didn't exactly call attention to it. -------------------------------------------------------------------------------- /src/strings_ii/equality_ignoring_case.md: -------------------------------------------------------------------------------- 1 | # Equality ignoring case 2 | 3 | If you want to check if two `String`s contain the same contents 4 | but you do not care if those contents differ in the casing of letters, you can use the `.equalsIgnoreCase` 5 | method. 6 | 7 | ```java 8 | void main() { 9 | String historicalFigureOne = "St. Valentines"; 10 | String historicalFigureTwo = "st. valentines"; 11 | 12 | System.out.println( 13 | historicalFigureOne.equalsIgnoreCase(historicalFigureTwo) 14 | ); 15 | } 16 | ``` 17 | 18 | This is different from the result the `.equals` method will give you. That method will return `false` if there 19 | are any differences in the two `String`s. -------------------------------------------------------------------------------- /src/strings_ii/lowercase.md: -------------------------------------------------------------------------------- 1 | # lowercase 2 | 3 | In English[^otherlangs] letters can be either lower-cased (`a`, `b`, `c`) or upper-cased (`A`, `B`, `C`). 4 | 5 | If you have a `String` which potentially contains upper-cased letters, you can get a new `String` with everything 6 | transformed into lower-case using the `.toLowerCase()` method. 7 | 8 | ```java 9 | void main() { 10 | String message = "Happy Valentines Day"; 11 | 12 | String lowerCased = message.toLowerCase(); 13 | System.out.println(lowerCased); 14 | } 15 | ``` 16 | 17 | This does not change the original `String` in place. It just makes a new `String` with all lower-case letters. 18 | 19 | 20 | [^otherlangs]: Other languages also have a notion of case. I am not a polyglot though, so I'm not qualified 21 | to talk about them. -------------------------------------------------------------------------------- /src/switch/combining_cases.md: -------------------------------------------------------------------------------- 1 | # Combining Cases 2 | 3 | If you have multiple constant values that should be handled in the same way, you can combine 4 | case labels by separating their values with a comma. 5 | 6 | ```java 7 | String scientificName(String vegetable) { 8 | switch (vegetable) { 9 | case "apple" -> { 10 | return "Malus pumila"; 11 | } 12 | case "cabbage", "brussel sprouts", "kale", "cauliflower" -> { 13 | // Look it up. Kinda wild. 14 | return "Brassica oleracea"; 15 | } 16 | default -> { 17 | return "unknown"; 18 | } 19 | } 20 | } 21 | ~ 22 | ~void main() { 23 | ~ System.out.println(scientificName("cabbage")); 24 | ~} 25 | ``` -------------------------------------------------------------------------------- /src/switch/enums.md: -------------------------------------------------------------------------------- 1 | # Enums 2 | 3 | Switches really shine with enums. 4 | 5 | For each case label you need to use the name of the variant, not prefixed with 6 | the name of the enum. 7 | 8 | ```java 9 | enum StopLight { 10 | RED, 11 | YELLOW, 12 | GREEN 13 | } 14 | 15 | void main() { 16 | StopLight light = StopLight.GREEN; 17 | switch (light) { 18 | case RED -> { 19 | System.out.println("Stop!"); 20 | } 21 | case YELLOW -> { 22 | System.out.println("Speed up, coward!"); 23 | } 24 | case GREEN -> { 25 | System.out.println("Go!"); 26 | } 27 | } 28 | } 29 | ``` -------------------------------------------------------------------------------- /src/switch/ints.md: -------------------------------------------------------------------------------- 1 | # ints 2 | 3 | You can also use `int`s with switches. 4 | 5 | ```java 6 | ~void main() { 7 | int year = 2024; 8 | switch (year) { 9 | case 2023 -> { 10 | System.out.println("The Chiefs"); 11 | } 12 | case 2024 -> { 13 | System.out.println("The Chiefs"); 14 | } 15 | default -> { 16 | System.out.println("I don't know"); 17 | } 18 | } 19 | ~} 20 | ``` -------------------------------------------------------------------------------- /src/switch/omitted_default.md: -------------------------------------------------------------------------------- 1 | # Omitted Default 2 | 3 | If you have no logic to put in it, you can omit the `default` case from a `switch`. This is the same conceptually as omitting a final `else` from a chain of `if`s and `else if`s. 4 | 5 | 6 | ```java 7 | void react(String fruit) { 8 | switch (fruit) { 9 | case "apple" -> { 10 | System.out.println("WOW"); 11 | } 12 | case "orange" -> { 13 | System.out.println("Zoinks!"); 14 | } 15 | case "grape" -> { 16 | System.out.println("Zoopers!"); 17 | } 18 | } 19 | } 20 | 21 | void main() { 22 | react("passionfruit"); // 🤷 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /src/switch/strings.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | As already shown, you can use a case to match `String` values. 4 | 5 | ```java 6 | ~void main() { 7 | String veggie = "cucumber"; 8 | switch (veggie) { 9 | case "cabbage" -> { 10 | System.out.println("A cabbage"); 11 | } 12 | case "brussel sprout" -> { 13 | System.out.println("A brussel sprout"); 14 | } 15 | case "cucumber" -> { 16 | System.out.println("A cucumber"); 17 | } 18 | default -> { 19 | System.out.println("Other"); 20 | } 21 | } 22 | ~} 23 | ``` -------------------------------------------------------------------------------- /src/switch_ii.md: -------------------------------------------------------------------------------- 1 | # Switch II 2 | 3 | A common thing to do is have a `switch` statement which assigns a value 4 | to a variable in each branch. 5 | 6 | ```java 7 | enum StopLight { 8 | RED, 9 | YELLOW, 10 | GREEN 11 | } 12 | 13 | enum Action { 14 | STOP, 15 | SLOW_DOWN, 16 | GO 17 | } 18 | 19 | void main() { 20 | StopLight light = StopLight.GREEN; 21 | 22 | Action action = null; // Delayed assignment rules are funky here. 23 | switch (light) { 24 | case RED -> { 25 | action = Action.STOP; 26 | } 27 | case YELLOW -> { 28 | action = Action.SLOW_DOWN; 29 | } 30 | case GREEN -> { 31 | action = Action.GO; 32 | } 33 | } 34 | 35 | System.out.println(action); 36 | } 37 | ``` 38 | 39 | For this purpose, you can instead use a switch "as an expression." -------------------------------------------------------------------------------- /src/switch_ii/exhaustive_switches_with_enums.md: -------------------------------------------------------------------------------- 1 | # Exhaustive Switches with Enums 2 | -------------------------------------------------------------------------------- /src/switch_ii/exhaustive_switches_with_strings.md: -------------------------------------------------------------------------------- 1 | # Exhaustive Switches with Strings 2 | -------------------------------------------------------------------------------- /src/switch_ii/exhaustiveness.md: -------------------------------------------------------------------------------- 1 | # Exhaustiveness 2 | 3 | When a switch is used as an expression it needs to be exhaustive. 4 | 5 | ```java 6 | ~void main() { 7 | String name = "bob"; 8 | 9 | boolean cool = switch (name) { 10 | case "bob" -> false; 11 | default -> true; 12 | }; 13 | 14 | System.out.println(cool); 15 | ~} 16 | ``` 17 | 18 | If you attempt to make a non-exhaustive switch expression, Java will not let you. 19 | 20 | ```java,does_not_compile 21 | ~void main() { 22 | String name = "bob"; 23 | 24 | boolean cool = switch (name) { 25 | case "bob" -> false; 26 | }; 27 | 28 | System.out.println(cool); 29 | ~} 30 | ``` 31 | -------------------------------------------------------------------------------- /src/switch_ii/return_a_switch.md: -------------------------------------------------------------------------------- 1 | # Return a Switch 2 | 3 | If you choose to, you do not need to assign the result of a switch expression into a variable. You can directly return the result from a method. 4 | 5 | ```java,no_run 6 | enum Bird { 7 | TURKEY, 8 | EAGLE, 9 | WOODPECKER 10 | } 11 | 12 | boolean isScary(Bird bird) { 13 | return switch (bird) { 14 | case TURKEY -> true; 15 | case EAGLE -> true; 16 | case WOODPECKER -> false; 17 | }; 18 | } 19 | ``` -------------------------------------------------------------------------------- /src/switch_iii/break.md: -------------------------------------------------------------------------------- 1 | # break 2 | -------------------------------------------------------------------------------- /src/switch_iii/default.md: -------------------------------------------------------------------------------- 1 | # default 2 | -------------------------------------------------------------------------------- /src/switch_iii/fallthrough.md: -------------------------------------------------------------------------------- 1 | # Fallthrough 2 | 3 | If the code for a given label does not `break` 4 | or `return` then -------------------------------------------------------------------------------- /src/switch_iii/return.md: -------------------------------------------------------------------------------- 1 | # return 2 | -------------------------------------------------------------------------------- /src/switch_iii/yield.md: -------------------------------------------------------------------------------- 1 | # yield 2 | -------------------------------------------------------------------------------- /src/tcp: -------------------------------------------------------------------------------- 1 | # Low Level versus High Level 2 | -------------------------------------------------------------------------------- /src/tcp_over_ip.md: -------------------------------------------------------------------------------- 1 | # TCP over IP 2 | 3 | Most of the internet is built on top of something called "TCP over IP" 4 | or "Transmission Control Protocol over Internet Protocol." 5 | 6 | If those words don't make it immediately obvious what that means, thats normal. 7 | The short version is that the "IP" part refers to how computers find eachother 8 | on the internet and the "TCP" part refers to the how those computers 9 | speak to eachother once they've found eachother. 10 | 11 | For the long version, I'll defer to this youtube video. 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tcp_over_ip/sockets.md: -------------------------------------------------------------------------------- 1 | # Sockets 2 | 3 | To communicate with a server using TCP over IP you use the `Socket` 4 | class. 5 | 6 | // ---- 7 | Th -------------------------------------------------------------------------------- /src/the_terminal.md: -------------------------------------------------------------------------------- 1 | # The Terminal 2 | 3 | Early computers didn't have graphical interfaces with windows or buttons you could "click." 4 | Instead, they offered a text based interface. 5 | 6 | We call this sort of interface a "terminal," though you might hear the terms "shell" 7 | and "terminal emulator" used interchangibly. 8 | -------------------------------------------------------------------------------- /src/the_terminal/bash.md: -------------------------------------------------------------------------------- 1 | # Bash 2 | 3 | If you are programming on a computer running either Mac or Linux you should have easy access 4 | to a bash terminal. Just search your applications for something called "terminal" or that has the word "term" in it. 5 | 6 | This is the most common kind of terminal for working professionals to use.[^asterisk] 7 | 8 | [^asterisk]: Asterisks apply, of course. I didn't run or try to find a survey so this is mostly anecdotal. -------------------------------------------------------------------------------- /src/the_terminal/changing_directories.md: -------------------------------------------------------------------------------- 1 | # Changing Directories 2 | 3 | You can change what your working directory is using the `cd` command. 4 | 5 | After the name of the command, you write the name of the directory you want to change in to. 6 | 7 | ```bash 8 | $ pwd 9 | /Users/emccue 10 | $ cd Downloads 11 | $ pwd 12 | /Users/emccue/Downloads 13 | ``` 14 | 15 | If you want to go to a "parent" directory, you can write `..`. This means "one directory up". 16 | 17 | ```bash 18 | $ pwd 19 | /Users/emccue 20 | $ cd .. 21 | $ pwd 22 | /Users 23 | ``` 24 | 25 | [^cd]: Short for "change directory" -------------------------------------------------------------------------------- /src/the_terminal/chromebooks_and_school_computers.md: -------------------------------------------------------------------------------- 1 | # Chromebooks and School Computers 2 | 3 | A very common thing that school systems will do is prevent students from accessing a terminal. 4 | 5 | This is a good thing if your goal is to prevent high schoolers from committing shenanigans. Less so if your goal is to learn how to program. 6 | 7 | There are also computer types, like chromebooks, which aren't really built with programming in mind. While you could access a terminal, the sorts of programs you would generally install to 8 | work with Java will be out of reach. It's a similar case for things like iPads. 9 | 10 | If you are in one of these situations I would reccomend getting a "normal" computer if at all possible. You can make do for a time, but eventually it will be required to continue in this field.[^thems] 11 | 12 | [^thems]: Thems the ropes, kid. 🤷 -------------------------------------------------------------------------------- /src/the_terminal/commands.md: -------------------------------------------------------------------------------- 1 | # Commands 2 | 3 | The primary way you interact with a terminal is by running commands. 4 | 5 | You start with a blank prompt and write something like the following. 6 | 7 | ```bash 8 | $ echo Hello 9 | Hello 10 | ``` 11 | 12 | The first word is the name of the program to run. In this case `echo`. Everything after 13 | that is an "argument" to the program. -------------------------------------------------------------------------------- /src/the_terminal/creating_directories.md: -------------------------------------------------------------------------------- 1 | # Creating Directories 2 | 3 | In order to create a directory you can use the `mkdir`[^mkdir] command. 4 | 5 | ```bash 6 | $ mkdir project 7 | $ ls 8 | project 9 | ``` 10 | 11 | [^mkdir]: Make Directory. -------------------------------------------------------------------------------- /src/the_terminal/creating_files.md: -------------------------------------------------------------------------------- 1 | # Creating Files 2 | 3 | To create a blank file you can use the `touch`[^no_clue] command. 4 | 5 | ```bash 6 | $ touch hello.txt 7 | ``` 8 | 9 | This is situationally useful, but more often than not you will create files 10 | using a program called a "text editor." 11 | 12 | There are some text editors, like [`vim`](https://www.vim.org/), which run entirely 13 | inside the terminal.[^diehard] 14 | 15 | One of the more popular ones at time of writing is [Visual Studio Code](https://code.visualstudio.com/). If you weren't otherwise shown a different option, that is a decent default. Install it and then you can use it to create and edit files. 16 | 17 | [^no_clue]: I have no clue why this is called `touch`. 18 | [^diehard]: These have their die hard supporters. The lunatics. 19 | [^thisbook]: This book has been written inside Visual Studio Code. 20 | -------------------------------------------------------------------------------- /src/the_terminal/directories.md: -------------------------------------------------------------------------------- 1 | # Directories 2 | 3 | Directories, also known as folders, are the places where files are in a computer. 4 | 5 | When you open a terminal, you are "inside" a particular directory. 6 | 7 | You can see the directory you are in by running the `pwd`[^pwd] command. 8 | 9 | ```bash 10 | $ pwd 11 | /Users/emccue 12 | ``` 13 | 14 | 15 | [^pwd]: "Print Working Directory" -------------------------------------------------------------------------------- /src/the_terminal/getting_used_to_it.md: -------------------------------------------------------------------------------- 1 | # Getting Used to it 2 | 3 | So far this is only a shallow dive. It will take a good amount of time for you to get 4 | comfortable using the terminal for things. 5 | 6 | Thats normal. You'll get there eventually. Just know that at least some familiarity with the terminal is going to be needed. 7 | 8 | We'll get back to it relatively soon, but feel free to seek out some bash/terminal specific resources online in the meantime. -------------------------------------------------------------------------------- /src/the_terminal/java_programs.md: -------------------------------------------------------------------------------- 1 | # Run Java Programs 2 | -------------------------------------------------------------------------------- /src/the_terminal/listing_files.md: -------------------------------------------------------------------------------- 1 | # Listing Files 2 | 3 | You can list the files in your current working directory with the `ls`[^ls] command. 4 | 5 | ```bash 6 | $ ls 7 | Applications 8 | Camera 9 | Desktop 10 | Development 11 | Documents 12 | Downloads 13 | ``` 14 | 15 | This is useful for getting your bearings, but also to find a file you forget the name of or similar. 16 | 17 | 18 | [^ls]: Short for "List" 19 | -------------------------------------------------------------------------------- /src/the_terminal/run_java_programs.md: -------------------------------------------------------------------------------- 1 | # Run Java Programs 2 | 3 | If you've properly set up Java on your machine you should be able to use the `java` command 4 | to run any code on your machine. 5 | 6 | Just write `java` followed by the path to a file containing Java code.[^eventually] 7 | 8 | Say we had this code in a file named `Main.java` 9 | 10 | ```java 11 | void main() { 12 | System.out.println("Hello"); 13 | } 14 | ``` 15 | 16 | To run this, say `java Main.java`. 17 | 18 | ```bash 19 | $ java Main.java 20 | Hello 21 | ``` 22 | 23 | If the file is in a directory that is not your current working directory, you 24 | should include the full path. 25 | 26 | ```bash 27 | $ java src/Main.java 28 | Hello 29 | ``` 30 | 31 | [^eventually]: You can get away with just using your editor's run button for awhile, but this 32 | will eventually become important to know. -------------------------------------------------------------------------------- /src/the_terminal/windows_subsystem_for_linux.md: -------------------------------------------------------------------------------- 1 | # Windows Subsystem for Linux 2 | 3 | If you are using Windows there are two terminals that come preinstalled. One is `cmd.exe`, where 4 | you write in a language called batch, and the other is "PowerShell." 5 | 6 | Both of these differ in significant ways from bash so, if at all possible, you should get set up with the [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/about). 7 | 8 | This will let you follow along with the bash snippets you'll see later in this book.[^other_shells] 9 | 10 | [^other_shells]: It is certainly possible for me to also include instruction for PowerShell and batch but it doesn't feel practical. I spend most of my working hours using batch and can test commands on the machine I use to write this. It would be hard for me to do that with the Windows specific shells -------------------------------------------------------------------------------- /src/time.md: -------------------------------------------------------------------------------- 1 | # Time 2 | 3 | Wikipedia defines "time" as "The continued sequence of existence and events that occurs in an apparently irreversible succession from the past, through the present, and into the future."[^source] 4 | 5 | Most everything that interacts with the real world needs to understand information about time. 6 | As such, Java has various ways to work with data that holds information about time. 7 | 8 | [^source]: https://en.wikipedia.org/wiki/Time -------------------------------------------------------------------------------- /src/time/date.md: -------------------------------------------------------------------------------- 1 | # Date 2 | -------------------------------------------------------------------------------- /src/time/instant.md: -------------------------------------------------------------------------------- 1 | # Instant 2 | 3 | A `java.time.Instant` stores information on a particular moment in time. 4 | 5 | You can get the current "instant" with `Instant.now`. 6 | 7 | ```java 8 | import java.time.Instant; 9 | 10 | void main() { 11 | var now = Instant.now(); 12 | System.out.println(now); 13 | } 14 | ``` 15 | 16 | But if you happen to know a number milliseconds after January 1, 1970 UTC[^epoch] you 17 | can get an `Instant` which represents that point in time with `Instant.ofEpochMilli`. 18 | 19 | ```java 20 | import java.time.Instant; 21 | 22 | void main() { 23 | var january2nd = Instant.ofEpochMilli(86400000); 24 | System.out.println(january2nd); 25 | } 26 | ``` 27 | 28 | [^epoch]: https://en.wikipedia.org/wiki/Unix_time 29 | 30 | -------------------------------------------------------------------------------- /src/time/local_date.md: -------------------------------------------------------------------------------- 1 | # LocalDate 2 | 3 | A local date is something like "January 10th, 2024." 4 | 5 | This just records a day, month, and year. It doesn't know 6 | in what part of the world it was January 10th 2024, just 7 | that somewhere the "local" date was that. 8 | 9 | You can make a `LocalDate` with `LocalDate.of`. 10 | 11 | ```java 12 | import java.time.LocalDate; 13 | 14 | void main() { 15 | var jan10 = LocalDate.of(2024, 10, 1); 16 | System.out.println(jan10); 17 | } 18 | ``` 19 | 20 | And you can get the current `LocalDate` in whatever timezone 21 | your computer is programmed to be in with `LocalDate.now();` 22 | 23 | ```java 24 | import java.time.LocalDate; 25 | 26 | void main() { 27 | var now = LocalDate.now(); 28 | System.out.println(now); 29 | } 30 | ``` -------------------------------------------------------------------------------- /src/time/local_date_time.md: -------------------------------------------------------------------------------- 1 | # LocalDateTime 2 | 3 | What do you get if you combine a `LocalDate` and a `LocalTime`? A `LocalDateTime`! 4 | 5 | A `LocalDateTime` stores dates and times. 6 | 7 | If you have both a `LocalDate` and a `LocalTime` you can combine them 8 | with `LocalDateTime.of`. 9 | 10 | ```java 11 | import java.time.LocalDate; 12 | import java.time.LocalTime; 13 | import java.time.LocalDateTime; 14 | 15 | class Main { 16 | void main() { 17 | var jan10 = LocalDate.of(2024, 10, 1); 18 | var tenTwentyFour = LocalTime.of(10, 24, 0); 19 | System.out.println(LocalDateTime.of(jan10, tenTwentyFour)); 20 | } 21 | } 22 | ``` -------------------------------------------------------------------------------- /src/time/local_time.md: -------------------------------------------------------------------------------- 1 | # LocalTime 2 | 3 | In the same way a local date leaves off context about where 4 | it was and what time it was, a local time just stores the time. 5 | 6 | This means it will hold the exact time during the day, down to the nanoseconds. 7 | 8 | You can make a `LocalTime` with `LocalTime.of` giving it the hours, minutes, and 9 | seconds into the day. 10 | 11 | ```java 12 | import java.time.LocalTime; 13 | 14 | void main() { 15 | var tenTwentyFour = LocalTime.of(10, 24, 0); 16 | System.out.println(tenTwentyFour); 17 | } 18 | ``` 19 | 20 | And similarly you can get the current time your computer thinks it is with `LocalName.now()` 21 | 22 | ```java 23 | import java.time.LocalTime; 24 | 25 | void main() { 26 | var now = LocalTime.now(); 27 | System.out.println(now); 28 | } 29 | ``` -------------------------------------------------------------------------------- /src/time/offset_date_time.md: -------------------------------------------------------------------------------- 1 | # OffsetDateTime 2 | -------------------------------------------------------------------------------- /src/variables/naming.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | It is a social convention[^perry] that local variables be named `likeThis`. 4 | 5 | That is if their name is one word, that word should be in lowercase. 6 | 7 | ```java 8 | String apple = "Red Delicious"; 9 | ``` 10 | 11 | If it is multiple words, the first word should be lowercase 12 | and the others should start with a capital letter. 13 | 14 | This convention is called `camelCase` because the capitals looks like the humps on a Camels back. 15 | 16 | Just like proper formatting, sticking to this style will increase your chances of 17 | someone online being able to help you with your code. 18 | 19 | [^perry]: [Trapped! By societal convention!](https://youtu.be/CnOWLuN37D8?t=64) 20 | 21 | -------------------------------------------------------------------------------- /src/visibility.md: -------------------------------------------------------------------------------- 1 | # Visibility 2 | 3 | When code is all in one file, everything is "visible." This means that 4 | if there is a method you are always allowed to call it. 5 | 6 | ```java 7 | class Main { 8 | void canCallThis() { 9 | System.out.println("of course!") 10 | } 11 | 12 | void main() { 13 | canCallThis(); 14 | } 15 | } 16 | ``` 17 | 18 | And if there is a field you can read it, if there is a class you can make an instance of it, etc. 19 | 20 | Once we split into multiple files, you are allowed to make things less visible. 21 | -------------------------------------------------------------------------------- /src/visibility/private.md: -------------------------------------------------------------------------------- 1 | # Private 2 | 3 | -------------------------------------------------------------------------------- /src/visibility/private_constructor.md: -------------------------------------------------------------------------------- 1 | # Private Fields 2 | -------------------------------------------------------------------------------- /src/visibility/private_fields.md: -------------------------------------------------------------------------------- 1 | # Private Fields 2 | 3 | Similar to private methods, you can also mark a field as private. 4 | 5 | ```java 6 | class Kaiju { 7 | private int timesLostToGodzilla; 8 | 9 | Kaiju() { 10 | this.timesLostToGodzilla = 0; 11 | } 12 | 13 | void fightGodzilla() { 14 | this.timesLostToGodzilla++; 15 | } 16 | 17 | boolean isLoser() { 18 | return this.timesLostToGodzilla > 0; 19 | } 20 | } 21 | ``` 22 | 23 | This makes it so that code in other files cannot see or change the field directly. 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/visibility/private_methods.md: -------------------------------------------------------------------------------- 1 | # Private Methods 2 | 3 | If a class has a method that it uses but that you do not want other code to see, 4 | you can mark it `private`. 5 | 6 | ```java,no_run 7 | class RiceCooker { 8 | int temperature; 9 | 10 | private boolean shouldTurnOff() { 11 | return temperature > 100; 12 | } 13 | 14 | void operate() { 15 | if (shouldTurnOff()) { 16 | turnOff(); 17 | } 18 | else { 19 | // ... 20 | } 21 | } 22 | } 23 | ``` 24 | 25 | This makes it so that code in `RiceCooker.java` can see and call the `shouldTurnOff` method but code in other files cannot. 26 | 27 | This is useful if you want to box up some logic but don't want to have to think about 28 | what happens if other code calls it. -------------------------------------------------------------------------------- /src/visibility/the_game.md: -------------------------------------------------------------------------------- 1 | # The Game 2 | 3 | The only reason you would care about how visible a particular method or field is 4 | if you were playing what I call "the game[^that]" 5 | 6 | In the game you take some unit of code, like a class, and pretend that someone is going to 7 | try and do every possible thing that you can do with it. 8 | 9 | If you have methods named `stepOne()`, `stepTwo()` and `stepThree()` - what happens if someone calls them in the wrong order. If you have a field named `denominator` - what happens if someone sets it to zero. That sort of thing. 10 | 11 | [^that]: Not the game that you just lost by remembering you were playing the game. -------------------------------------------------------------------------------- /src/visibility_ii.md: -------------------------------------------------------------------------------- 1 | # Visibility II 2 | -------------------------------------------------------------------------------- /theme/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Together-Java/ModernJava/54a40793348e797bc2bcc11e563dc3aff25d5fef/theme/favicon.png --------------------------------------------------------------------------------