--- title: "Jam 02 - Exercise 1 - Understanding Java Types" tags: - 3 ๐Ÿงช in testing - 4 ๐Ÿฅณ done - jam02 - types - objects - performance --- <!-- markdownlint-disable line-length single-h1 no-inline-html --> <!-- markdownlint-configure-file { "ul-indent": { "indent": 4 }, "link-fragments": {"ignore_case": true} } --> # Exercise 1 - Understanding Java Types {%hackmd dJZ5TulxSDKme-3fSY4Lbw %} ## Overview - Exercise 1 Let's explore a fundamental difference between Python and Java that will impact how you write code. In Python, everything is an object - integers, floats, strings, and even functions. But Java takes a different approach by having two distinct categories of types: 1. **Primitive Types**: Basic data types like `int`, `double`, etc. 2. **Class Types**: Objects that have both data and methods :::info ๐Ÿ”‘ **Key Concept** A primitive type variable holds exactly one value and nothing else - no methods, no extra data. An object, on the other hand, can store multiple values and has methods to work with that data. ::: This distinction will become particularly important when we learn about Java's Collections API. Collections (which you'll use for storing groups of data, like lists and sets) can only work with objects, not primitive types. We'll dive deeper into Collections later, but for now, this limitation raises an interesting question: if we want to store primitive values in these collections, how can we convert our primitive types into objects? Java's solution is **wrapper classes** - special classes that "wrap" primitive values into objects. Each primitive type has a corresponding wrapper class: | Primitive Type | Wrapper class in `java.lang` | | -------------- | ---------------------------- | | byte | Byte | | short | Short | | int | Integer | | long | Long | | float | Float | | double | Double | | char | Character | | boolean | Boolean | Take a moment to read through the [Oracle Java Tutorial on Number classes](https://docs.oracle.com/javase/tutorial/java/data/numberclasses.html) to understand how these wrapper classes work. :::info ๐Ÿ”‘ **Auto-boxing and Auto-unboxing** Java provides a convenient feature called **auto-boxing** and **auto-unboxing** that automatically converts between primitive types and their wrapper objects. For example: ```java= // auto-boxing: int literal being stored in Integer object Integer objX = 10; // auto-unboxing: Integer object stored in an int variable int x = objX; ``` While this makes coding more convenient, it's important to understand that these conversions are happening behind the scenes and can impact your program's performance! ::: ## Required Steps - Working with Wrapper Classes Let's explore the differences between primitive types and wrapper classes hands-on using JShell - a cool interactive Java interpreter that's great for learning and experimenting with Java (similar to how you used Python's interactive interpreter with the `python` or `python3` command): 1. Open a terminal and start JShell: ```bash jshell ``` 2. Create both a primitive and wrapper variable: ```java= int x = 10; // primitive type Integer objX = 10; // wrapper class ``` JShell usually gives you some indication of what you just did. Your screen should look something like this: ![jshell example](https://hackmd.io/_uploads/ryDR8NYuJx.png) Think about what you just created. You have TWO variables that both appear to hold the value 10, but they are fundamentally ***very*** different: - `x` is a primitive type `int` that just holds the value 10 - `objX` is an *object* of type `Integer` that contains a "boxed up" or "wrapped" int value, plus it has methods to work with that value. 3. Explore what you can do with the wrapper class: ```java // Type objX. and press TAB to see all available methods - JShell will autocomplete! objX.doubleValue(); // converts to double objX.toString(); // converts to String ``` :::warning ๐Ÿ”ง **Troubleshooting**: If autocomplete (TAB) isn't working in IntelliJ's terminal, try running JShell in your system's terminal app (Terminal on Mac, Git Bash on Windows) instead. You will need to repeat the `jshell` command to start JShell and create the variables again. ::: Remember how you learned to use the Java 21 API documentation in Jam01? Look up the Integer class in the `java.lang` package as another way to see all available methods. You can use both the API documentation and JShell's tab completion to discover what methods are available - the documentation gives you detailed explanations, while JShell lets you try them out right away! 4. Try the same with the primitive type: ```java // This will cause an error - primitives don't have methods! x.doubleValue() ``` 5. Exit JShell when done: ```bash /exit ``` :::warning ๐Ÿšง **Important Distinction** - A primitive variable (like `x`) directly stores its value - A wrapper object (like `objX`) stores a reference to an object that contains the value - This difference affects both memory usage and performance ::: >[!Important] Questions for answers.txt > >(1.1) What error message did you receive when trying to call `doubleValue()` on the primitive variable `x`? Copy and paste the exact error message. What do you think this message means? > >(1.2) List two methods available to the Integer wrapper class that you found interesting (other than doubleValue and toString which we already discussed). For each method, briefly explain what it does. > >(1.3) In your own words, explain the difference between how primitive types and wrapper class objects are stored in memory. Why might this difference matter for performance? ## Why Performance Matters Before we move on to our next exercise, let's consider why we're spending time understanding these details about primitive types and wrapper classes. Why not just use wrapper classes everywhere and not worry about the difference? :::info ๐Ÿ”‘ **Standing Out as a Software Engineer** Right now, you're making a crucial career choice: You could be a **mediocre developer** who: - Copies solutions without understanding them - Relies on ChatGPT without questioning its output - Takes the easy way out without considering implications - Gets rejected in technical interviews - Struggles to maintain long-term employment Or you could be an **exceptional engineer** who: - Deeply understands how their code works - Makes informed design decisions - Considers performance implications - Writes maintainable, efficient code - Gets noticed by top employers - Advances quickly in their career The difference? It's in the details - like understanding primitives vs wrappers. **This is your chance to build the foundation that will set you apart.** ::: Consider these real-world scenarios where your choice between primitive types and wrapper classes matters: 1. **Mobile and IoT Devices** - Many applications run on devices with limited resources - Mobile phones and IoT devices often have: - Restricted memory - Limited CPU power - Battery life constraints - Every small optimization counts! 2. **Large-Scale Applications** - Data science and machine learning applications process millions of values - Even tiny performance differences multiply at scale - Efficient code can mean the difference between: - A program that runs in minutes vs hours - An app that fits in memory vs crashes - A battery that lasts all day vs dies by lunch :::warning ๐Ÿšง **Key Takeaway** Understanding low-level details like the difference between primitives and wrappers isn't just academic - it's about writing code that performs well in the real world, whether on a tiny IoT sensor or a massive data processing system. ::: ## Save Your Work - Exercise 1 Verify what files are uncommited: ```bash git status ``` Stage your changes (This should be the file shown in `git status` as modified) Feel free to use a different message as long as it's descriptive ```bash git add src/main/java/jam02/answers.txt ``` Commit your work ```bash git commit -m "jam02: Complete wrapper class exploration and questions" ``` Your working directory should be now be clean.