Skip to content

Latest commit

 

History

History
606 lines (413 loc) · 31.2 KB

File metadata and controls

606 lines (413 loc) · 31.2 KB

2. Data Types

[toc]


2.1. Data Types

2.1.1. Static vs. Dynamic Typing

In a dynamically typed programming language (like JavaScript or Python), a variable or parameter can refer to a value of any type (string, number, object, etc.) at any time. When the variable is used, the interpreter figures out what type is and behaves accordingly.

Java is a statically typed language. When a variable or parameter is declared in a statically typed language, the data type for the value must be specified. Once the declaration is made, the variable or parameter cannot refer to a value of any other type.

😫 We've kinda gone over this. So, let's come back to this later.

2.1.2. Strings and Single Characters

2.1.2.1. Immutability

Strings in JavaScript are immutable, which means that the characters withing a string cannot be changed.

2.1.2.2. Single vs. Double Quotation Marks

Java Sytnax requires double quotations marks when declaring strings.

Java also has another caraible type, char, which is used for a single charcater. char uses single quotation marks. The single character can be a ltter, digit, punctuation, or whitespace like tab ('\t'). (It can be assumed that you want to do your escape sequences like this.)

String staticVariable = "dog";
char charVariable = 'd';

2.1.2.3. Manipulation

The table below summaried some of the most common string methods available in Java. For example, we use the string variable String str = "Rutabaga".

String methods in Java

NOTE: The full list of methods can be found here.

Java Syntax Descrption
str.charAt(3) Returns the character at index 3. ('a').
str.substring(2,4) Returns the charcters from index 2 through 4, ("tab")
str.length() Return the length of the string. (8)
str.indexOf('a') Return the index of the first occurrence of 'a'. (3)
str.split("") Split the string into sections at each delimiter, and stores the selections as elements in an array. If you use an empty string ("") it should split the string into an array.
str.concat(str2).str(str3) Concatenate two strings. In Java, you can only do this with two strings. To do this with more strings, you need to use method chaining.
str.trim() Removes any whitespace at the beginning or end of a the string.
str.toUpperCase() Changes all alphabetic characters in the string to uppercase.
str.toLowerCase() Changes all alphabetic characters in the string to lowercase.
str.contains("text") Search for the specified text within a string and returns true or false.
str.equals(otherString) Compares strings for equality and returns a boolean. This is case sensitive.
str.equalsIgnoreCase(otherString) Compares strings for equality and returns a boolean. This is case insensitive.

NOTE: We will explore the difference between using == and .equals() when we discuss Javaoperators. For now, use .equals() if you need to compare two strings.

2.1.3. Primitive Types

A primvative data type (PDT) is a basic building block. Using PDTs, we can open more complex data structires called object data types (ODTs).

Java uses its own set of PDTs. The table below shows the most common types that beginners are like to use:

Java Primative Data Types

Data Type Examples Notes
int 42 Represents positive and negative whole nubmers.
float 3.14159 Represents positve and negative decimal numbers with up to 7 digts.
double 3.14159265358979 Represents postive and negative decimal numbers with 15 to 16 digits.
char 'a', '9', and '\n' A single unicode character encluded in single quotes.
boolean true and false Booleans in Java are NOT capitalized!

⚠️ WARNING! As we will see in a later section, the float data type sacrifices some accuracy for speed of calculation. Thus, evaluating 1.11111 + 3 results in an answer of 4.1111097 instead of 4.11111.

Anytime you need to perform calculations with decimal values, consider using the double type instead of float.

2.1.4. Non-primitive Types

PDTs are immutable and can be combined to build larger data structures. One xample is forming the String "LaunchCode" from multiple char characters ('L','a','u',etc.)

String is a non-primative data type (NPDT), also called a object type. As we saw in the String table above, object types have methods which we can call usuing dot notations. PDTs do not have methods.

Note: PDTs in Java begin with a lower case letter while object data types betwin with a capital letter.

Later in this chater, we will explore the Array and Class object types.

2.1.5. Autoboxing

"Auto-box, roll out!" --Boximus Prime :3

There may be situations when we call a method that expects and object as an argument, but we pass a primative type instead (or vice versa). In these cases, we need to convert the PDT to an object, or convert an object into a primative.

In older versions of Java, it was the programmer's responsibility to convert back and forth between PDTs and object types whenever necessary. Converting from a PDT to an object type was called boxing, and the reverse process (object to primative) was called unboxing.

Example:

Boxing

int someInteger = 5;
Integer someIntegerObject = Integer.valueOf(someInteger);
ClassName.methodName(someIntegerObject);
  1. Line 1 declares an initializes the variable someInteger.
  2. Line 2 converts the primitive int to the Integer object type.
  3. Line 3 calls methodName and passes someIntegerObject as the argument. If methodName expects an object type and we tried sending an int instead, we would generate an error message.

Unboxing

Let's assume that a method returns a random number of Integer type, and we want to combine it with a value of int type.

int ourNumber = 5;
Integer randomNumber = ClassName.randomNumberGenerator();
int randomInt = (int) randomNumber;
int sum = ourNumber + randomInt;
  1. Line 2 declares and initializes randomNubmer as an Integer type.
  2. Line 3 converts randomNumber to an int and stores the value in the randomInt variable.

Converting between data types in order to pass values between methods quickly became tedius and error prone. In newer version of Java, the compiler is smart enough to know when to convert back and forth. This is called autoboxing.

For us, the consequences of autoboxing is that in many situations, we can use primitive and object types interchangeably when calling methods or returning data from those methods.

Tip: It's a best practice to use primitives whenever possible. The primary exception to this occurs when storing values in collections, which we will learn about in a future lesson.

Each of the PDTs has a corresponding object type:

  1. int → Integer
  2. float → Float
  3. double → Double
  4. char → Character
  5. boolean → Boolean

2.1.6. References

[^pdt ]: Primitive Data Types [^ box ]: Autoboxing and Unboxing [^ var ]: Variables

2.1.7. Check Your Understanding

2.2. Some Java Practice

🎗️ TODO: Take more notes on this section later.

2.2.1. Temperature Conversion

package org.launchcode.java.demos.lsn1datatypes;

import java.util.Scanner;

public class TempConverter {
   public static void main(String[] args) {
      double fahrenheit;
      double celsius;
      Scanner input;

      input = new Scanner(System.in);
      System.out.println("Enter the temperature in Fahrenheit: ");
      fahrenheit = input.nextDouble();
      input.close();

      celsius = (fahrenheit - 32) * 5/9;
      System.out.println("The temperature in Celsius is: " + celsius + "°C");
   }
}

2.2.2. Java Packages

Line 1 of of the program above, package org.launchcode.java.demos.lsn1datatypes; declares the package in which the file resides. For this simple program, your code could run without this line. However, you want to get used to always declaring the package of your Java classes.

Packages help to encapsulate your code. Encapsulation refers to the practice of shielding your code from outside influences. It’s an essential component of good object oriented programming, and package declaration in Java is just one application of this principle. Without declaring a package, a Java class exists within the default package. In larger applications, leaving all classes in the default package risks naming conflicts and bugs.

2.2.3. import

The import statement in Java allows us to access the class, methods, and data stored a different file. import tells the compiler that we are going to use a shortened version of the class name. In this example, we are going to use the class java.util.Scanner, but we can refer to it as just Scanner. We could use the java.util.Scanner class without any problem and without any import statement, provided that we always refer to it by its full name.

This idea bears repeating. In Java, you can use any available class WITHOUT having to import it, but you must use the full name of the class. “Available” classes include:

  1. All the classes you define in the .java (source) and .class (compiled) files in your current working directory.
  2. All the classes that get shipped with the software.

Try It: In the sample code, remove the import statement in line 3, and change Scanner on lines 9 & 11 to java.util.Scanner. The program should still compile and run.

The class naming system in Java is very hierarchical. The full name of the Scanner class is really java.util.Scanner. You can think of this name as having two parts:

  1. java.util is called the package,
  2. Scanner is the class name.

We’ll talk more about the class naming system a bit later.

2.2.4. Declaring Variables

In the example above, lines 7 - 9 contain variable declarations:

double fahrenheit;	// line 7
double celsius;		// line 8
Scanner input;		// line 9

Since Java is a statically typed language, we must always declare the data type for any variable. Lines 7 & 8 establish that fahrenheit and celsius will hold values of type double. In line 9, the variable input references a Scanner object.

If later in the code we try to initialize fahrenheit with a string:

fahrenheit = "xyz"

the compiler throws an error because fahrenheit is declared to be a double.

The following error is common for new Java programmers. Suppose we forget to include the declaration for celsius. What happens when we try to compile and run our program?

Try It:

  1. Edit your TempConverter class by removing line 8, which declares the variable celsius.
  2. Click any of the “Run” options in IntelliJ. Alternatively, use the terminal to navigate to the parent directory of your TempConverter.java class and run java TempConverter.java.

Your terminal will return some errors that resemble these:

Error:(16, 9) java: cannot find symbol
symbol:   variable celsius
location: class TempConverter

Error:(17, 64) java: cannot find symbol
symbol:   variable celsius
location: class TempConverter

These two compiler errors occur before the program runs. The values in the parentheses () give the line number and text column where the error was found. In the first description (line 16, column 9), the celsius variable before the = is flagged. When this type of error happens, it usually means that the variable was not declared before we tried to initialize it with a value.

The second error message (line 17, column 64) occurs because we use celsius before it has been assigned a value.

Note: When using an IDE such as IntelliJ, your work is typically checked by the IDEs built-in compiler as you write your code. Errors are often visually indicated by the IDE as you type. This avoids having to explicitly compile your code before finding errors. Nice, huh?

red colored text usually indicates and error.

The general rule in Java is that you must decide on the data type for your variable first, and then declare that variable before you use it. There is much more to say about the static typing of Java, but for now this is enough.

Note: As in other languages, Java allows you to declare and initialize your variables in the same line:

double celsius = (fahrenheit - 32) * 5/9;

2.2.5. Add Comments to Your Code

As programs get bigger and more complicated, they get more difficult to read. Good programmers try to make their code understandable to others, but it is still tricky to look at a large program and figure out what it is doing and why.

Also, there are times when programmers need to isolate or ignore certain portions of their code as they are testing it. In the "Try It" box above, you were instructed to remove a line of code in order to create compiler errors. However, programmers are usually reluctant to delete lines that they might need to bring back.

Best practice encourages us to add comments to our programs. These are notes that clearly explain what the code is doing.

A comment is text within a program intended only for a human reader—–it is completely ignored by the compiler or interpreter. In Java, the // token indicates the start of a comment, and the rest of the line gets ignored. For comments that stretch over multiple lines, the text falls between the symbols /* */.

Comments can also be used to temporarily skip a portion of the code when a program runs. Instead of removing double celsius; in TempConverter, we could comment out the line. This would create the same compiler errors we wanted to witness, but it would preserve the original code and allow us to easily reactivate it by removing the // token from the line.

Example:

import java.util.Scanner;

// Here is an example of a comment.

/* Here is how
to have
multi-line
comments. */

/*
Or
like
this.
*/

public class HelloWorld {
   public static void main(String[] args) {
      Scanner input; // Comments do not have to start at the beginning of a line.

      input = new Scanner(System.in);
      System.out.println("Please enter your first name: ");
      String name = input.next(); //Declares the 'name' variable and initializes it with text from the command line.
      input.close();

      System.out.println("Hello, " + name + "!");

      // System.out.println("This line will NOT print!");
   }
}

2.2.6. Collect Input with the Scanner Class

In Java, Scanner objects make getting input from the user, a file, or even over the network relatively easy. For our temperature conversion program, we declared the variable input to be of type Scanner.

Scanner input;	// line 9

We want our program to prompt the user to enter in a number in the command line. We accomplish this by creating a Scanner instance using the word new and then calling the constructor and passing it the System.in object:

input = new Scanner(System.in);	// line 11

Notice that this Scanner object is assigned to the name input, which we declared to be a Scanner object earlier.

And you know those System statements we’ve been using? Like System.in above here, and System.out.println() for print statements. Well, System itself is a java class. System.in is similar to System.out except, as the name implies, it is used for input.

Note: If you are wondering why we must create a Scanner object to read data from System.in when we can write data directly to System.out using println, you are not alone. We will talk about the reasons why this is so when we dive into Java streams.

Next, line 12 asks the user to enter a number, and in line 13 we use input to read the value from the command line:

// lines 12 and 13
System.out.println("Enter a temperature in Fahrenheit: ");
fahrenheit = input.nextDouble();

Here again we see the implications of Java being a strongly typed language. Notice that we must call the method nextDouble, because the variable fahrenheit was declared as a double.

Because Java is a statically typed language, we must call the appropriate method on the Scanner object to ensure the entered data is of the correct type. In this case, the compiler compares the types for fahrenheit and input.nextDouble() and throws an error if the two do not match.

Scanner methods

Note: For a full list of Scanner methods, see the docs.

Return Type Method Description
boolean hasNext() Returns true if more data is present.
boolean hasNextInt() Returns true if the next item to read is an int data type.
boolean hasNextFloat() Returns true if the next item to read is a float data type.
boolean hasNextDouble() Returns true if the next item to read is a double data type.
int nextInt() Returns the next item to read as int data type.
float nextFloat() Returns the next item to read as float data type.
double nextDouble() Returns the next item to read as double data type.
String next() Returns the next item to read as String data type.
String nextLine() Returns the next line to read as String data type.

2.2.6.1. Closing Scanner

To collect data from the command line or other source, create a Scanner object. This opens up resources in your machine to manage the input, and these resources remain open even after the required data is loaded into your program.

Leaving a Scanner open is like keeping a window open in your house 24/7. Anyone can climb into your home, and you lose (a lot of) money by trying to heat and cool your space while it is open to the outside air. Similarly, an open Scanner can allow unintended access to your program, and it ties up resources that might be needed elsewhere.

Best practice states that if you open a Scanner object, close it after it finishes its job. Line 14 does this in our TempConverter program:

input.close();		// Line 14

The general sytanx is scannerObjectName.close().

2.2.6.2. Moving Beyond the Command Line

The Scanner class serves as a kind of adapter that gathers primitive data types as input and converts them into object types (e.g. it converts an int into Integer). We will discuss the purpose of this later, but for now, know that this adaptation makes low-level data types easier to use.

For the temperature conversion program, we collected user input from the command line, but there are other options for collecting data for our programs. In future examples, we will create a Scanner object by passing a File object as a parameter instead of System.in.

2.2.7. Check Your Understanding ✅

2.3. More Data Types

2.3.1. Arrays

In Java, ==an array is an ordered, fixed-size collection of elements.== To comply with static typing, the items stored in an array must all be the same data type. We can create an array of integers or an array of strings, but we may NOT create an array that holds both integers and strings.

The syntax for creating an array capable of holding 10 integers is:

int[] someInts = new int[10];

Note the square brackets next to int. This tells Java that we want someInts to store a collection of integers instead of a single number.

To create an array of a different size, replace the number 10 in the brackets with the desired size. To create an array holding a different type, replace int (on both sides of the assignment) with the desired type, like double or String.

In addition to the example above, we can initialize an array using a literal expression:

int[] someOtherInts = {1, 1, 2, 3, 5, 8};

Here, the size of the array is implied by the number of elements in the literal expression {1, 1, 2, 3, 5, 8}. Also note the use of curly braces { } instead of square brackets [ ].

==To access array elements, we use square brackets and zero-based indexing.==

int anInt = someOtherInts[4];
// anInt stores the integer 5.

==Arrays in Java may NOT change size once created.== This is limiting and not very practical. Thankfully, Java provides more flexible ways to store data, which we will explore in a later lesson. These objects will allow us to rearrange, add to, or remove data.

Aside from using arrays to build some simple loop examples, we will only use them in special cases. However, they are a core part of Java, so it’s good to know how they work.

2.3.2. Java Objects

In Java, ==objects are structures that have a state and a set of behaviors. The state of an object includes properties/data that the coder can define and modify. Behaviors are actions that run when requested, and they can be used to evaluate, manipulate, or return data.==

==An array is one example of an object. It contains data, which are the values stored as the individual elements. The behaviors are methods like sort() that perform actions related to the elements in the array.==

==The String data type is also an example of an object.== For String language = "Java", the data would be the characters. The String manipulation section gives several of the behaviors available to the language object. For example, language.length() returns the value 4, which tells us how many characters are present in the string.

==Every variable in Java refers to either a PDT or to an object.==

2.3.3. Class Types

==A class is a template for creating objects.== In addition to the object types introduced so far, any class in Java also defines a type. We’ll have much more to say about classes and objects, but for now you need to recognize the basic syntax of class types and class creation.

If we have a class Cat, we can declare and create an instance of Cat using the new keyword:

Cat myCat = new Cat();
  1. Cat myCat declares the variable myCat and sets it to be of type Cat.
  2. = new Cat() initializes the variable with a new Cat object.
  3. Any arguments that are required to build the new Cat object must be included within the parentheses.

Just like a variable can be declared as a PDT like char or double, it can also be declared as a specific class type. Variables that hold objects--like String name = "Blake" or myCat--are said to be reference variables. Using this terminology, name is a reference variable of the String class, and myCat is a reference variable of type Cat.

Note: Java uses two general data types—primitive and object. A class type is NOT a new data type. Instead, it is just a specific name applied to the more general object data type.

int and char are both primitive data types, but the values they can store differ. Similarly, String and Cat are both object types, but they represent different classes.

2.3.3.1. Reference Variables

==Reference variables are different from primitive types in an essential way. A reference variable== (such as myCat above) ==does not actually store the object in question. Instead, it stores a reference to the object, which is literally a memory address.== We visualize a reference as an arrow pointing to the location of the object in memory.

Consider this code:

int firstCatAge = 11;
int secondCatAge = firstCatAge;
Cat myCat = new Cat();
Cat sameCat = myCat;

Visually, we can represent these four variables as shown below.

Reference Variables vs Primative Variables

Since int is a primitive type, the variables firstCatAge and secondCatAge function like separate boxes, each one holding the integer value 11. On the other hand, myCat is a reference variable, since it refers to an object of type Cat. The variable actually stores the memory address of the object, which we visualize as an arrow pointing from the variable box to where the data is stored. Instead of holding the actual Cat data, myCat stores directions for finding the data in memory.

When we to assign myCat to another variable, as in Cat sameCat = myCat, we do NOT create a second copy of the object or its data. Instead, we make a second arrow pointing to the same memory location.

The distinction between object types and primitives is important, if subtle. As you continue learning Java, you will see that object types are handled differently in essential and important ways.

2.3.4. Static Methods

If you are familiar with another programming language (JavaScript), then you most likely defined and called functions. As a pure object-oriented programming language (OOPL), Java also uses functions, but it structures them in a very specific way.

==In Java, functions may NOT be declared outside of a class. Even a simple function that checks if an integer is even needs to be defined within a class.==

Within the context of a class, functions are referred to as methods, and we will adopt this terminology from now on.

⚠️ WARNING!: Be prepared to receive a vocabulary lesson from veteran Java coders if you accidentally refer to methods as functions. 🤓 😫

We’ll dive deeper into classes and objects in Java soon enough. For now, we will explore how to write methods. In particular, we’ll use static methods. ==A static method is one that can be called without creating an instance of the class to which it belongs.==

Until we get further into object oriented programming (OOP), every method you write should use the static keyword. Leaving off static will prevent or complicate the process of calling the methods you defined.

Example: Define the class Cat and include the static keyword before the makeNoise method name:

public class Cat {
     public static void makeNoise(String[] args) {
      // some code
     }
}

Since makeNoise is static, we do NOT need to create a Cat object to access it. So instead of doing this:

Cat myCat = new Cat();     // Create a new Cat object.
myCat.makeNoise("purr");   // Call the makeNoise method.

We can call the method directly:

Cat.makeNoise("roar");

We will explore exactly what static does in more detail in later lessons.

2.3.4.1. Static Method Examples

Let’s examine two classes in Java to explore defining and using methods. The first class is defined in the HelloMethods.java file, and it has a main method. The second class is defined in a separate Message.java file, and it contains a getMessage method that we want to call from within main.

Examples:

/**
 * @file: HelloMethods.java
 */

public class HelloMethods {
   public static void main(String[] args) {
      String message = Message.getMessage("fr");
      System.out.println(message);
   }
}
/**
 * @file: Message.java
 */
public class Message {
   public static String getMessage(String lang) {
      if (lang.equals("sp")) {
         return "¡Hola, Mundo!";
      } else if (lang.equals("fr")) {
         return "Bonjour, le monde!";
      } else {
         return "Hello, World!";
      }
   }
}

We won’t explore every new aspect of this example, but instead focus on the two methods.

  1. The main method in the HelloMethods class has the same structure as that of our temperature conversion example.
  2. Take a look at the Message class. Note that it does NOT have a main method, so it can’t be run on its own. Code within the Message class must be called from elsewhere in order to execute.
  3. The Message class contains the getMessage method. Like main, it has the static keyword. Unlike main, getMessage has a return type of String instead of void.
  4. getMessage takes a single String parameter, lang.

Since Java is statically typed, we must declare the data type for each parameter AND the return value.

public static returnedDataType methodName(parameterDataType parameterName) {
   //code
}

One consequence of this is that a method in Java may NOT have return statements that send back different types of data. Note that lines 7, 9, and 11 in Message.java each return a string. If we try to replace line 11 with return 42;, we would generate a compiler error.

To call a static method, we follow a specific syntax. Line 7 in the HelloMethods.java shows this:

Message.getMessage("fr");

==To call a static method we must use the format ClassName.methodName(arguments).==

Note that getMessage is NOT defined within the HelloMethods class. We can do this because getMessage is declared as public. If we wanted to restrict the method from being called by another class, we could instead use the private modifier. We will explore access modifiers in more depth in coming lessons.

⚠️ WARNING! As you have been following along with these examples, you may have noticed that each class file, for example Message.java and HelloMethods.java, is named exactly the same as the class it holds (Message and HelloMethods, respectively).

It is a rule in Java that a file containing a class marked public MUST be named the same as that class.

2.3.4.2. Try It

Open the HelloMethods and Messages files in the java-web-dev-exercises project in IntelliJ and experiment with the following:

  1. Figure out how to alter the HelloMethods code to change the message returned.
  2. Add another “Hello, World” language option.
  3. Change one public keyword to private to see what happens. Repeat for each occurrence of public.

2.3.5. References

2.3.6. Check Your Understanding ✅

2.4. Exercises: Data Types 🏃

🎗️ TODO: Fill this out. There's some important stuff in this one.

2.4.1. Instructions

2.4.1.1. Creating a Package and Classes

2.4.2. Exercises 🏃

2.5. Studio: Area of a Circle 🎙️

2.5.1. Creating your class

2.5.2. Your first task

2.5.3. Your next task

2.5.4. Bonus Missions 🚀


#Java