Java Class

A class in java is a representation of an object. It is a blueprint. It describes the attributes and behavior of an object. Every class will have the basic structure shown below. All classes are capitalized and the files associated with them will also be named after the class by convention. The attributes are typically located towards the top of the class.

Since classes are just templates for objects you have to create them in Java. The creation of objects is facilitated by the use of a constructor. Constructors help set up the attributes of the object. Finally, the behaviors are listed with their implementation. Behaviors are the set of methods for the class.

Declaration

You should know how to declare variables by this point. The Declaration of objects is actually the same. This time instead of int, double, or boolean as the type, the type portion is the name of the Java class being used. In APCS-A and general programming, you must be comfortable using classes that you did not write yourself.

It is a good skill to be able to read through documentation quickly enough to use the class, and it is also a good idea not to reinvent the wheel by writing a set of untested code but rather use a set of code known to have been tested already. The libraries provided in the Java programming language are an example set of classes that you should be comfortable using knowing they have been tested and work as described. You need not know how they are written.

The class below has been provided and we will use it to discuss some of the processes involved in creating objects in Java. First, let's show you some example declarations so you can compare them to the declaration of primitive types.

int x;
int x2;
double y;
Pomekon p1;
Pomekon p2;

Because Pomekon is a type defined by a class, the variables p1 and p2 are called references. It is safe to assume that unless you are working with a known primitive type, you are working with a reference.

Instantiating an Object

The constructor was mentioned earlier and how it helps create objects in Java. The constructor helps define what the attributes of the class will contain. Recall that a class is just a bundle of attributes (variables) and behaviors (methods). How do we invoke the constructor to create objects? We will use the given Circle class below for this example.

Circle my_circle; 

The line above is NOT yet an object. It refers to a Circle object but right now it is referring to nothing. When this is the case, it can be said that my_circle is null. In order to create an object in java, you must call the keyword new as well as call upon the constructor as shown below.

Circle my_circle = new Circle();

The right side of the equal sign, new Circle(), calls upon the constructor of the class side-by-side with the keyword new. You cannot call upon the constructor in this way without the keyword new.

Example Class

public class Circle{            <----- declare and name the class (must be capitalized)

    public Circle(){             <---- This is the constructor, this line specifically is the method header/signature
        /* stuff that runs for constructor */
} //end of constructor

}//closing bracket for Circle class declaration

The part of the line of code, new Circle(), calls upon a part of the Circle class code, the constructor. The very first line of the constructor is called the signature. This signature is unique hence the name signature. The signature name of any constructor must match the name of the class. This is then followed by a set of parentheses. What is before the name is solely the keyword public which we will get to later and can be ignored for now.

If you are reading the rest of the code you can see that there are two constructors in this Circle class. The first one does not have anything in the parenthesis, while the second one does. This is allowed in java and the set of parameters is what sets the two constructors apart from one another. The set of parameters always lists the type and name for each parameter separated by a comma. Remember Java is a strongly-type language so every variable must have a declared type. The second constructor for Circle has one parameter called r_param and it is an int type.

Constructor?

What happens on the call to a constructor? When there is a call to new and the constructor, the code actually changes direction momentarily to execute a different set of code. That different set of codes is the constructor. Where you are instantiating objects may be in a different place from where the class file exists. They do not need to be in the same file. In fact, it is considered good practice to keep separate classes in their own files. The program sets aside enough memory space to hold the information for a Circle object. We know that the computer must, at the very least, reserve enough space to store the radius and the area of a Circle object. The rest of the program follows the constructor logic. Let's assume the first constructor without any parameters is being called. The only two lines that will run will be the assignment statements which set the initial values for the two attributes to 2 and 3.14 respectively.

Call by Value (Pass by Value)

Let's trace the code above. Take a look at the Driver class which contains our main method. Remember the main method is generally the starting point for a java program and you will continue to see examples like this one. There is a variable, radius, that has been declared and assigned the value 2. The second line of code uses the class Circle to the right. The variable c is known as a reference because the data type is a class (Circle in this case). Notice the call to the constructor, new Circle(radius). The constructor has a parameter and the type is int. This means that in order to use that constructor you need to give it a literal value that matches that type. In this case, the declared variable radius is being used as the value passed into the constructor.

Passing information to a constructor or a method like this is done through a call by value. What does that mean? All it means is that a copy of that value is created separately to be passed to that part of the code. That part of the code could be a constructor or a method. Regardless, what is received on the intended block of code is a copy of the original data. This is known as call by value. The relevance of this will show up a lot later when you get to more data processing.

For now, know that because a copy of the data is made, the original data is untouched no matter what you do in the block of code you sent the data to. Specifically in this case, even if the constructor altered the data it is sent, the original data is unaffected. Call by value always happens for primitive types.

System Class

Often times you will actually call upon existing code that has already been tested and proven to work. The very first set of codes you will call upon comes from the System class. The line of code System.out.println("Hello World") is actually a call to a print method. Calling upon a method in Java involves calling the name of the method including the parenthesis. You may be familiar with using the square root function like sqrt(16). Parenthesis is a major part of a method call. The information you pass to a method goes inside the parenthesis.

In the sqrt method, 16 is the input to this method. The expected result would be the square root of that. In java, inputs to programs are called parameters. More on this in Units 2.4 and 2.5. For now, just know that in order to call upon the print methods you must always include System.out. This part of that line of code just says that the method you are accessing happens to live in a library called System.

The methods we are going to invoke are going to be instance methods. They are behaviors that are attached to an object. For example, if you are an object and you could sing, then you need to exist first before I could ask you to sing. Same thing here. In order to use the methods above, which are part of the HelloWorld class, you need to first create an object of that type. 

public class HelloWorld{
    public void sing(){  System.out.println("lalala");
}


HelloWorld myObject = new HelloWorld(); //This declares and creates the object similar to how you declare a variable. 
                                        //the keyword new is what creates an object which is necessary for Object types                          

Assume this line of code above is in the main method as seen in previous examples. Now we have an object, myObj, which we can use to invoke the methods shown in the class above! So how about it? Let's start invoking some methods. To start with you need to call upon the object by its variable name then use the dot operator to access a public instance method of that object. See the examples below.

void method?

void myMethodName(){  <----- the method is called myMethodName and it does not return a value
    return;           <----- although you can have an empty return line, the method cannot return data.                
}

What exactly is a void method anyway? A void method is a method that does not return a value. The set of curly brackets define the body of the method. Whenever you have a void method, you will see there is no return keyword followed by some literal value, expression, or method call. If you are using an IDE (Integrated Development Environment), a software application that facilitates software development like VS Code, Eclipse, NetBeans, or IntelliJ, the dot operator use for any object will auto-suggest all accessible public parts of the object defined by the class file.

In our simple example, the two possible choices would be methodA and methodB. The dot operator is available for all objects albeit you will be limited to what has been defined to be publicly accessible. Do not worry about the public keyword yet. You may be poking around on an IDE or your teacher may be walking you through the use of an IDE so it's worth a mention.

Method Header

Below is the general form of any Java method. Make sure you're familiar with what information the method header gives you as a programmer using the method. Why? Well, you need to be aware of what type of data the method gives you back, you need to know how to call upon the method so you need to know the name and finally you need to know what data the method is expecting. Remember, it has been mentioned earlier that the existence of variables allows programmers to generalize algorithms regardless of changing data. The use of methods is a strong case for this.

public returnType methodName(/*parameter list*/){

    /* method body */
}


Above is a label method with the parts.

This time around we will play around with the static keyword. If a class method has the keyword static in front of the return type, in this case, void, then you can call upon the name of the class and use the dot operator that way. See examples below.

public class Math{
    public static int getRand(){ /* logic for method */ }
public static void print() { /* logic for method */ }

//Below is an example of method overloading
    public void method(double x){ }
public void method(String s){ }
public void method(boolean b){
}


public class Runner{
    public static void main(String[] arg){
        
        int result = Math.getRand(); <---- since getRand is static, this syntax is valid.

    }
}

Again notice that instead of calling upon an object to access the method, you can simply use the name of the Java class containing the static method(s). More on this in 2.9 but it is being introduced here. But wait a minute... You have three methods named the same thing. How is Java not getting confused? Recall that method overloading in Java is a mechanism where you can have multiple methods with the same name as long as the signatures are unique. If you look at the methods above, they all differ in their parameter list making their signatures different. Java will match the list of parameters you are passing to the method when you're invoking them and call the correct method accordingly. It's not magic! It's a "method overloading".

The parameters of a method are in the set of parentheses after the name of the method. These are also known as formal parameters.
Method Header vs Usage:

Header/signature:

void method(double x)   <--- This defines some basic information about the method (like a recipe)

Use:

method(3.14)                 <---- This calls upon the method (uses it)

When you use the method, you're not declaring any variable x necessarily. You are strictly passing data to the method that matches the type that is defined by the method header. The method header parameter list describes the type of data a method requires. When you use the method, whatever data is passed in as a parameter will be named x. x is a generalized name for any data being passed to the method

The first line above creates a Circle. If you follow which constructor it calls based on the parameters or lack of, then you will see that the radius is set to 2. The next line of code then invokes the getRadius method for the circle. While this works it actually does nothing for you as the value returned by the method is unused. Imagine you order and pay for your order at a restaurant and then drove away without the food. Although nothing bad happens, it's not ideal that you walked away from the food that was eventually prepared. Let's alter the second line to look like the code segment below.

int result = myCircle.getRadius();
System.out.println(result);

This time around, we are declaring an int variable to capture the result of the method invocation. This is completely legal and happens all the time in programming. A valid Java expression is just a set of Java constructs made up of variables, operators, and/or method invocations. Once you have stored the value returned by a method you can perform any operation that is valid on it.

What happens if you want to retrieve the result of the call to a method? For example, when you use your calculator to calculate the square root of 9 you are expecting to get a result. This is similar to what happens with non-void methods. Non-void methods may perform the same type of calculator as void methods, but what they must do is return a result in the form of a literal, expression, or method invocation. Let's revisit the Circle class for this section. Given a Circle object, it is reasonable to query that object for its radius or its area. There are two methods that meet those desired behaviors. 
Circle myCircle = new Circle();
myCircle.getRadius(); 

System is the first java class where we used code from when we use the print methods. String is one of the major classes you will use in APCS-A. You should have read the section on String literals in Chapter 1 so we will not repeat it here. It is 1.4 if you want to revisit that discussion. What kind of objects for a String class represent? You probably guessed correctly. String characters! Recall string literals in chapter 1. These string literals are actually instances of String objects!

Mechanically, Java handles automatically converting them to String objects as means to make the process convenient! This means there are two ways to create String objects. You can create them like in chapter 1 through the use of double quotes or you can instantiate them like you would any object. The two ways of creating Strings are shown below.

There is an operation that is predefined for you in Java called concatenation. Concatenate multiple strings in the order in which you want them to appear reading left-to-right. The operator used is the + operator.

Example concatenations:
String s = "hello"+"world"; 
String s2  = "hi":
Strng s3  = s + s2;

As demonstrated above, the order does matter when you are joining two string. Remember to add any white space if you want them as concatenation does no insert new characters that are not there before.

String substring(int start, int end)

Given a string, you can obtain a substring of it through the substring methods. One of the substring methods requires two parameters which are the start and end of the substring you are obtaining from the string.
System.out.println(str.substring(0,5)); //output: Hello
In the example above, 0 is the starting index. In Java, the first element will be at location 0! The output above does not include white space! This is because the substring method stops at the ending index - 1. Let's see another.
System.out.println(str.substring(3,8)); //output: lo Wo 

String substring(int start)

The second version of substring allows you to specify the starting point and it will automatically grab all the characters to the length of the string.
System.out.println(str.substring(3)); //output: lo World
System.out.println(str.substring(5)); //output: World  

String indexOf(String other)

You can search for the existence of a substring in a String. This method will return the starting location where it finds the substring.
System.out.println(str.indexOf("World")); //output: 6
System.out.println(str.indexOf("l")); //output: 2
The method returns the starting location of the first occurrence of the string. In the second example above, the method returns 2 even though there are multiple copies of the letter l in the string. But what about the case where the substring is not found? It returns -1.
System.out.println(str.indexOf("avocado")); //output: -1 

String equals(String other)

This method compares the String object you have to another String object that is being passed into the method.
System.out.println(str.equals("Hello world")); //output: false
The segment of code above returns false because the W is not capitalized. Again, the parameter String object is being compared to the String object you're in which you are calling the methods. More examples are shown below.
String str2 = "Hey World";
System.out.println(str.equals(str2)); //output is false
In the example above, it becomes more obvious that you are working with two String objects, str, and str2. The content of each of these objects is the string of characters. The method, equals, will compare each character of the objects. You can skip the creation of a second object because Java has a built-in mechanism to transform any String literal (denoted by the set of double quotes) to a String object.

String compareTo(String other)

If you want finer detail in comparing two String objects, you can use the compareTo method. This method will have three possible results and compares two Strings lexicographically or how it would appear in the dictionary. For this assume we have the String objects as declared and instantiated below.
String a = "cat";
String b = "dog";
String c = "bird";

Since Strings are objects in Java, you can use the dot operator. Remember the dot operator allows you to access publicly available methods and attributes of that class. In this section, we will go over ones that are quite useful in text processing in addition to being tested on the AP Exam. The list of the methods is below. We will go over them one by one.

For all of the example uses of the methods below assume the String object has been defined as shown below. These methods are all instance methods. An instance method means there must be an object in which it resides.
String str = "Hello World" 

String length()

You can check the length of the string by using its length method. Remember white spaces count.
System.out.println(str.length()); //output: 11 

The two numerical primitive types we will use heavily are int and double. Java provides a class version of these primitive types. Taking a primitive type and create a class version of it is calling creating a wrapper class. All this means is that the class stores the information of that primitive type. Because it is now a class, it also provides useful methods. Later, you will find that there are certain structures in Java that require objects instead of simple primitive types. This is the main reason an object version of these two primitives exists! Java is also kind enough to perform a lot of the transformations behind the scenes similar to how creating String literals actually creates String objects behind the scenes! The three lines of code below are equivalent in that they all store the literal value 7.
int val = 7;
Integer val2 = new Integer(7)
Integer val3 = 7;
The third line of code demonstrates the built-in mechanism in Java that converts the literal value 7 to an object. What does this mean for you? This means that technically speaking, you almost never have to create Integer or Double objects due to the Java language handling the auto conversions for you. What you do need to know is that seeing object versions of these two data types should not change a lot of your problem-solving. You can just treat them as if you are dealing with primitives. Now there may be available methods for you through the dot operator. For example, given a Double-object, you can use the method intValue() to cast it to an int and vice-versa. This is shown below.
//using a method to cast
Double x = new Double(3.14);
System.out.println(x.intValue());

//what we have seen for casting double x2 = 3.14; System.out.println((int) x2);
Recall that explicit casting is the process of transforming some bigger data to fit into a smaller type. Going from a double to an int takes away the decimal portion. This is known as truncation and the java compiler may warn you or throw an error that you do not want to do this. Explicitly casting tells the compiler that you as the programmer are intentionally doing it and stops it from throwing a fit.

The Math class in java is a static library class providing you with many useful mathematical functions. The following are the list of methods commonly used in a first-year programming course.

These methods from the Math class are known as static methods. You do not need an instance of the object to invoke them. Recall the Circle class where there needed to be an instance of the class before the methods in it could be invoked. For the Math class, all you have to do is call the name of the class then immediately use the dot operator to gain access to any of the static methods. If you take the Circle class and changed the methods to be static by added the static keyword to the method header, you could get the same behavior. Sample calls to the Math methods:
double result = Math.sqrt(23);        //sqrt function
double val = Math.random();           //random function returns a number in the range [0 1)
double res2 = Math.pow(2, 3);         //power function. note that ^ is NOT the power operator