[toc]
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.
Strings in JavaScript are immutable, which means that the characters withing a string cannot be changed.
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';The table below summaried some of the most common string methods available in Java. For example, we use the string variable String str = "Rutabaga".
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.
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:
| 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, thefloatdata type sacrifices some accuracy for speed of calculation. Thus, evaluating1.11111 + 3results in an answer of4.1111097instead of4.11111.Anytime you need to perform calculations with decimal values, consider using the double type instead of
float.
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.
"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:
int someInteger = 5; Integer someIntegerObject = Integer.valueOf(someInteger); ClassName.methodName(someIntegerObject);
- Line 1 declares an initializes the variable
someInteger.- Line 2 converts the primitive
intto theIntegerobject type.- Line 3 calls
methodNameand passessomeIntegerObjectas the argument. IfmethodNameexpects an object type and we tried sending anintinstead, we would generate an error message.Let's assume that a method returns a random number of
Integertype, and we want to combine it with a value ofinttype.int ourNumber = 5; Integer randomNumber = ClassName.randomNumberGenerator(); int randomInt = (int) randomNumber; int sum = ourNumber + randomInt;
- Line 2 declares and initializes
randomNubmeras anIntegertype.- Line 3 converts
randomNumberto anintand stores the value in therandomIntvariable.
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:
int→Integerfloat→Floatdouble→Doublechar→Characterboolean→Boolean
[^pdt ]: Primitive Data Types [^ box ]: Autoboxing and Unboxing [^ var ]: Variables
🎗️ TODO: Take more notes on this section later.
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");
}
}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.
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:
- All the classes you define in the
.java(source) and.class(compiled) files in your current working directory. - All the classes that get shipped with the software.
Try It: In the sample code, remove the
importstatement in line 3, and changeScanneron lines 9 & 11 tojava.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:
java.utilis called the package,Scanneris the class name.
We’ll talk more about the class naming system a bit later.
In the example above, lines 7 - 9 contain variable declarations:
double fahrenheit; // line 7
double celsius; // line 8
Scanner input; // line 9Since 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:
- Edit your
TempConverterclass by removing line 8, which declares the variablecelsius.- Click any of the “Run” options in IntelliJ. Alternatively, use the terminal to navigate to the parent directory of your
TempConverter.javaclass and runjava 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;
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!"); } }
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 9We 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 11Notice 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
Scannerobject to read data fromSystem.inwhen we can write data directly toSystem.outusingprintln, 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.
Note: For a full list of
Scannermethods, 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. |
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 14The general sytanx is scannerObjectName.close().
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.
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.
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.==
==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();Cat myCatdeclares the variablemyCatand sets it to be of typeCat.= new Cat()initializes the variable with a newCatobject.- Any arguments that are required to build the new
Catobject 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.
intandcharare both primitive data types, but the values they can store differ. Similarly,StringandCatare both object types, but they represent different classes.
==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.
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.
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
Catand include thestatickeyword before themakeNoisemethod name:public class Cat { public static void makeNoise(String[] args) { // some code } }Since
makeNoiseisstatic, we do NOT need to create aCatobject 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.
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.
- The
mainmethod in theHelloMethodsclass has the same structure as that of our temperature conversion example. - Take a look at the
Messageclass. Note that it does NOT have amainmethod, so it can’t be run on its own. Code within theMessageclass must be called from elsewhere in order to execute. - The
Messageclass contains thegetMessagemethod. Likemain, it has thestatickeyword. Unlikemain,getMessagehas a return type ofStringinstead ofvoid. getMessagetakes a singleStringparameter,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 exampleMessage.javaandHelloMethods.java, is named exactly the same as the class it holds (MessageandHelloMethods, respectively).It is a rule in Java that a file containing a class marked
publicMUST be named the same as that class.
Open the HelloMethods and Messages files in the java-web-dev-exercises project in IntelliJ and experiment with the following:
- Figure out how to alter the
HelloMethodscode to change the message returned. - Add another “Hello, World” language option.
- Change one
publickeyword toprivateto see what happens. Repeat for each occurrence ofpublic.
🎗️ TODO: Fill this out. There's some important stuff in this one.
#Java
