Java
Welcome!
This page is the main page for Java
This page is the main page for Java
In Java, each piece of code is broken down into functions, which are individual routines that we can call in our code. Let’s review how to create functions in Java.
The table below lists the flowchart blocks used to represent functions, as well as the corresponding pseudocode:
Operation | Flowchart | Pseudocode |
---|---|---|
Declare Function |
|
|
Call Function |
|
In general, a function declaration in Java needs a few elements. Let’s start at the simplest case:
static void foo(){
System.out.println("Foo");
return;
}
Let’s break this example function declaration down to see how it works:
static
at the beginning of this function declaration. That keyword allows us to use this function without creating an object first. We’ll cover how to create and work with objects in a later module. For now, each function we create will need the static
keyword in front of it, just like the main()
function.void
, determines the type of data returned by the function. We use a special keyword void
when the function does not return a value. We’ve already seen this keyword used in our declaration of the main
function.foo
. We can name a function using any valid identifier in Java. In general, function names in Java always start with a lowercase letter.()
that list the parameters for this function. Since there is nothing included in this example, the function foo
does not require any parameters.{}
that surround the code of the function itself. In this case, the function will simply print Foo
to the terminal.return
keyword. Since we aren’t returning a value, we aren’t required to include a return
keyword in the function. However, it is helpful to know that we may use that keyword to exit the function at any time.Once that function is created, we can call it using the following code:
foo();
In a more complex case, we can declare a function that accepts parameters and returns a value, as in this example:
static int countLetters(String input, char letter){
int output = 0;
for(int i = 0; i < input.length(); i++){
if(input.charAt(i) == letter){
output++;
}
}
return output;
}
In this example, the function accepts two parameters: input
, which is a string, and letter
, which is a character. It also declares that it will return an int
value.
We can use the parameters just like any other variable in our code. To return a value, we use the return
keyword, followed by the value or variable containing the value we’d like to return.
To call a function that requires parameters, we can include values as arguments in the parentheses of the function call:
sum += countLetters("The quick brown fox jumped over the lazy dog", 'e');
Java allows us to create multiple functions using the same name, or identifier, as long as they have different parameters. This could include a different number of parameters, different data types for each parameter, or a different ordering of types. The names of the parameters, however, does not matter here. This is called function overloading.
For example, we could create a function named max()
that could take either two or three parameters:
public class Overloading{
public static void main(String[] args){
max(2, 3);
max(3, 4, 5);
}
static void max(int x, int y){
if(x >= y){
System.out.println(x);
}else{
System.out.println(y);
}
}
static void max(int x, int y, int z){
if(x >= y){
if(x >= z){
System.out.println(x);
}else{
System.out.println(z);
}
}else{
if(y >= z){
System.out.println(y);
}else{
System.out.println(z);
}
}
}
}
In this example, we have two functions named max()
, one that requires two parameters, and another that requires three. When Java sees a function call to max()
elsewhere in the code, it will look at the number and types of arguments provided, and use that information to determine which version of max()
it should use.
Of course, we could just use the three argument version of max()
in both cases:
public class Overloading{
public static void main(String[] args){
max(2, 3);
max(3, 4, 5);
}
static void max(int x, int y){
max(x, y, y);
}
static void max(int x, int y, int z){
if(x >= y){
if(x >= z){
System.out.println(x);
}else{
System.out.println(z);
}
}else{
if(y >= z){
System.out.println(y);
}else{
System.out.println(z);
}
}
}
}
In this case, we are calling the three parameter version of max()
from within the two parameter version. In effect, this allows us to define default parameters for functions such as this. If we only provide two arguments, the code will automatically call the three parameter version, filling in the third argument for us.
Unfortunately, Java does not support any other way of defining default parameters, but we can use function overloading to achieve something similar, as demonstrated above.
Finally, Java allows us to define a single parameter that is a variable length parameter. In essence, it will allow us to accept anywhere from 0 to many arguments for that single parameter, which will then be stored in an array. Let’s look at an example:
public class Overloading{
public static void main(String[] args){
max(2, 3);
max(3, 4, 5);
max(5, 6, 7, 8);
max(10, 11, 12, 13, 14, 15, 16);
}
static void max(int ... values){
if(values.length > 0){
int max = values[0];
for(int i : values){
if(i > max){
max = i;
}
}
System.out.println(max);
}
}
}
Here, we have defined a function named max()
that accepts a single variable length parameter. To show a parameter is variable length we use three periods ...
between the type and the variable name. We must respect three rules when creating a variable length parameter:
So, when we run this program, we see that we can call the max()
function with any number of integer arguments, and it will be able to determine the maximum of those values. Inside of the function itself, values
can be treated just like an array of integers.
Before we learn about classes and objects, let’s do a quick exercise to review how to create and use functions in our code.
Write a program that accepts input from a file provided as a command-line argument. If an incorrect number of arguments are provided, or if the program is unable to open the file, it should print “Invalid Arguments” and terminate.
The program’s input will consist of a list of 100 integers, one per line. If any line of the input cannot be converted to an integer, the program should print “Invalid Input” and terminate.
The program should determine whether the list of integers is considered a mathematical set. That is, each item in the list should be unique, with no duplicate numbers. If the input is not a set, it should print “Not a set” and terminate.
If the input is a set, then the program should print the sum of the values in the set and then terminate.
This program should consist of three functions:
main(args)
- The main function that controls the program. It should accept an array of strings representing the command-line arguments to the program.isSet(int[] numbers)
- A function to determine if the given array is a set. The input should be a single array of integers, and the return value should be a Boolean value.sumSet(int[] numbers)
- A function to find the sum of all the elements in the given array. The input should be a single array of integers, and the return value should be an integer.
There may be easier ways of determining if an array contains duplicate items, but could we simply check that, for each item, there is only one of that item in the list?
This exercise uses a custom grading program to grade submissions, which will be used extensively throughout this course. The first step of the grading process will examine the structure of your code, making sure that it contains the correct classes and functions. The second step will directly examine each function in the program, making sure that they operate as expected. You are welcome to include any additional code to complete the project that is not specified above.
Each step of the grading process will create two files in your work directory showing more detailed output. To open the HTML file as a webpage, right-click on it and select Preview Static. The log file may contain helpful debugging messages if your program experiences an unhandled exception.
{Check It!|assessment}(test-500463119)
{Check It!|assessment}(test-2806204399)
import java.util.Scanner;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.InvalidPathException;
import java.nio.file.NoSuchFileException;
import java.io.BufferedWriter;
import java.io.IOException;
import java.lang.NumberFormatException;
public class Functions{
public static void main(String[] args){
if(args.length != 1){
System.out.println("Invalid Arguments");
return;
}
try(
Scanner scanner1 = new Scanner(Paths.get(args[0]));
){
int[] nums = new int[100];
int i = 0;
while(scanner1.hasNext()){
String line = scanner1.nextLine().trim();
int input = Integer.parseInt(line);
nums[i++] = input;
}
if(isSet(nums)){
System.out.println(sumSet(nums));
}else{
System.out.println("Not a set");
}
}catch(InvalidPathException e){
System.out.println("Invalid Arguments");
return;
}catch(NoSuchFileException e){
System.out.println("Invalid Arguments");
return;
}catch(IOException e){
System.out.println("Invalid Arguments");
return;
}catch(NumberFormatException e){
System.out.println("Invalid Input");
return;
}
}
static boolean isSet(int[] nums){
for(int i : nums){
int count = 0;
for(int j : nums){
if(i == j){
count++;
}
}
if(count > 1){
return false;
}
}
return true;
}
static int sumSet(int[] nums){
int sum = 0;
for(int i : nums){
sum += i;
}
return sum;
}
}
In programming, a class describes an individual entity or part of the program. In many cases, the class can be used to describe an actual thing, such as a person, a vehicle, or a game board, or a more abstract thing such as a set of rules for a game, or even an artificial intelligence engine for making business decisions.
In object-oriented programming, a class is the basic building block of a larger program. Typically each part of the program is contained within a class, representing either the main logic of the program or the individual entities or things that the program will use.
We can represent the contents of a class in a UML Class Diagram. Below is an example of a class called Person
:
Throughout the next few pages, we will realize the design of this class in code.
To create a class in Java, we can simply use the class
keyword at the beginning of our file:
public class Person{
}
As we’ve already learned, each class declaration in Java includes these parts:
public
- this keyword is used to identify that the item after it should be publicly accessible to all other parts of the program. Later in this chapter, we’ll discuss other keywords that could be used here.class
- this keyword says that we are declaring a new class.Person
- this is an identifier that gives us the name of the class we are declaring.Following the declaration, we see a set of curly braces {}
, inside of which will be all of the fields and methods stored in this class.
According to the Java standards, this class must be stored in a file called Person.java
.
Of course, our classes are not very useful at this point because they don’t include any attributes or methods. Including attributes in a class is one of the simplest uses of classes, so let’s start there.
To add an attribute to a class, we can simply declare a variable inside of our class declaration:
public class Person{
String lastName;
String firstName;
int age;
}
That’s really all there is to it! We can also add default values to these attributes by assigning a value to the variable in the same line as the declaration:
public class Person{
String lastName = "Person";
String firstName = "Test";
int age = 25;
}
However, it is very important to note that we cannot declare an attribute and then set the default value on a separate line. So, code such as this is not allowed:
Finally, we can add either the public
keyword to the beginning of each of these attributes to make them available to code outside of this class, or the private
keyword to prevent other code from accessing those attributes directly. We denote this by adding a +
in front of the attribute in our UML diagram for public attributes, and a -
for private attributes. In the diagram above, each attribute is private, so we’ll do that in our code:
public class Person{
private String lastName;
private String firstName ;
private int age;
}
We can also add methods to our classes. These methods are used either to modify the attributes of the class or to perform actions based on the attributes stored in the class. Finally, we can even use those methods to perform actions on data provided as arguments. In essence, the sky is the limit with methods in classes, so we’ll be able to do just about anything we need to do in these methods. Let’s see how we can add methods to our classes.
To add a method to our class, we can simply add a function declaration inside of our class. In fact, all of the functions we’ve been creating up to this point have been inside of a class. The only difference is that we’ll now be able to remove the static
keyword from our function declarations. We’ll discuss more about exactly what that keyword does later in this chapter.
public class Person{
private String lastName;
private String firstName ;
private int age;
public String getLastName(){ return this.lastName; }
public String getFirstName(){ return this.firstName; }
public int getAge(){ return this.age; }
private void setAge(int age){ this.age = age; }
public void happyBirthday(){
this.setAge(this.getAge() + 1);
}
}
In this example, the first four methods are getter and setter methods. We have three public getter methods that allow us to access the values stored in our private attributes in a read-only way. In addition, we have created a private setter method for the age attribute. This isn’t technically required, since we can always just change it directly from within our code, but it is a good practice to include one.
Lastly, we have created a happyBirthday()
method that uses getters and setters to update the person’s age by 1 year.
We’ve already discussed variable scope earlier in this course. Recall that variables declared inside of a block are not accessible outside of the block. Similarly, two different functions may reuse variable names, because they are in different scopes.
The same applies to classes. A class may have an attribute named age
, but a method inside of the class may also declare a local variable named age
. Therefore, we must be careful to make sure that we access the correct variable, usually by using the this
keyword to access the attribute variable. Here’s a short example:
public class Test{
int age = 15;
void foo(){
int age = 12;
System.out.println(age); // 12
System.out.println(this.age); // 15
}
void bar(){
System.out.println(age); // 15
}
}
As we can see, in the method foo()
we must be careful to use this.age
to refer to the attribute, since there is another variable named age
declared in that method. However, in the method bar()
we see that age
automatically references the attribute, since there is no other variable named age
defined in that scope.
This can lead to some confusion in our code. So, we should always get in the habit of using this
to refer to any attributes, just to avoid any unintended problems later on.
A constructor is a special method that is called whenever a new instance of a class is created. It is used to set the initial values of attributes in the class. We can even accept parameters as part of a constructor, and then use those parameters to populate attributes in the class.
Let’s go back to the Person
class example we’ve been working on and add a simple constructor to that class
public class Person{
private String lastName;
private String firstName ;
private int age;
public String getLastName(){ return this.lastName; }
public String getFirstName(){ return this.firstName; }
public int getAge(){ return this.age; }
private void setAge(int age){ this.age = age; }
public Person(String lastName, String firstName, int age){
this.lastName = lastName;
this.firstName = firstName;
this.age = age;
}
public void happyBirthday(){
this.setAge(this.getAge() + 1);
}
}
Inside that constructor, notice that we use each parameter to set the corresponding attribute, using the this
keyword once again to refer to the current object.
Now that we have fully constructed our class, we can use it elsewhere in our code through the process of instantiation. In Java, we use the new
keyword to create a new instance of class, which calls the constructor, and then we can use dot-notation to access any attributes or methods inside of that object.
Person john = new Person("Smith", "John", 25);
System.out.println(john.getLastName());
john.happyBirthday();
We can also build classes that inherit attributes and methods from another class. This allows us to build more complex structures in our code, better representing the relationships between real world objects.
As we learned earlier in this chapter, we can represent an inheritance relationship with an open arrow in our UML diagrams, as shown below:
In this diagram, the Student
class inherits from, or is a subclass of, the Person
class.
To show inheritance in Java, we can use the extends
keyword after the class name in our class declaration, listing the parent class that we are inheriting from:
public class Student extends Person{
}
From there, we can quickly implement the code for each attribute and getter method in the new class:
public class Student extends Person{
private int studentID;
private int gradeLevel;
public int getStudentID(){ return this.studentID; }
public int getGradeLevel(){ return this.gradeLevel; }
}
Since the subclass Student
also includes a definition for the method happyBirthday()
, we say that that method has been overridden in the subclass. We can do this by simply creating the new method in the Student
class, and prefixing it with the @Override
annotation:
public class Student extends Person{
private int studentID;
private int gradeLevel;
public int getStudentID(){ return this.studentID; }
public int getGradeLevel(){ return this.gradeLevel; }
@Override
public void happyBirthday(){
super.happyBirthday();
this.gradeLevel += 1;
}
}
Here, we are using the keyword super
to refer to our parent class. In that way, we can still call the happyBirthday()
method as defined in Person
, but extend it by adding our own code as well.
In addition, we can use the super()
method to call our parent class’s constructor. This must be done as the first line of our subclass’s constructor:
public class Student extends Person{
private int studentID;
private int gradeLevel;
public int getStudentID(){ return this.studentID; }
public int getGradeLevel(){ return this.gradeLevel; }
public Student(String lastName, String firstName, int age, int studentID, int gradeLevel){
super(lastName, firstName, age);
this.studentID = studentID;
this.gradeLevel = gradeLevel;
}
@Override
public void happyBirthday(){
super.happyBirthday();
this.gradeLevel += 1;
}
}
In addition to private
and public
, Java also includes a keyword protected
. This modifier prevents external code from accessing attributes and methods, but will allow any subclasses to access them. In a UML diagram, the protected keyword is denoted by a hash symbol #
in front of the attribute or method.
Inheritance allows us to make use of polymorphism in our code. Loosely polymorphism allows us to store an instance of a class within the data type of any of its parent classes. By doing so, we can only access the methods and attributes defined by the data type, but any overriden methods will use the implementation from the child class.
Here’s a quick example:
Student steveStudent = new Student("Jones", "Steve", "19", "123456", "13");
Person stevePerson = (Person)steveStudent;
// Can access methods in Person
System.out.println(stevePerson.getFirstName());
// Cannot access methods in Student
System.out.println(stevePerson.getStudentID()); // will not compile
// Can call methods from Person
// This will use the code defined in Student,
// even though it is stored as a Person.
stevePerson.happyBirthday();
System.out.println(steveStudent.getGradeLevel()); // 14
Polymorphism is a very powerful tool in programming, and we’ll use it throughout this course as we develop complex data structures.
The other important modifier we can use in Java is the static
modifier. Again, we’ve seen this modifier each time we declare the main
method in our programs, but we haven’t really been able to discuss exactly what it means. Thankfully, we now have the knowledge we need to talk about the static
modifier.
In essence, the static
modifier makes an attribute or method part of the class in which it is declared instead of part of objects instantiated from that class. If we think about it, the word static means “lacking in change”, and that’s sort of a good way to think about it.
First, we can use the static
modifier with an attribute, attaching that attribute to the class instead of the instance. Here’s an example:
public class Stat{
public static int x = 5;
public int y;
public Stat(int an_y){
this.y = an_y;
}
}
In this class, we’ve created a static
attribute named x
, and a normal attribute named y
. Here’s a main()
method that will help us explore how the static keyword operates:
public class Main{
public static void main(String[] args){
Stat someStat = new Stat(7);
Stat anotherStat = new Stat(8);
System.out.println(someStat.x); // 5
System.out.println(someStat.y); // 7
System.out.println(anotherStat.x); // 5
System.out.println(anotherStat.y); // 8
someStat.x = 10;
System.out.println(someStat.x); // 10
System.out.println(someStat.y); // 7
System.out.println(anotherStat.x); // 10
System.out.println(anotherStat.y); // 8
Stat.x = 25;
System.out.println(someStat.x); // 25
System.out.println(someStat.y); // 7
System.out.println(anotherStat.x); // 25
System.out.println(anotherStat.y); // 8
}
}
First, we can see that the attribute x
is set to 5 as its default value, so both objects someStat
and anotherStat
contain that same value. Then we can update the value of x
attached to someStat
to 10, and we’ll see that both objects will now contain that value. That’s because the value is static
, and there is only one copy of that value for all instances of the Stat
class.
Finally, and most interestingly, since the attribute x
is static, we can also access it directly from the class Stat
, without even having to instantiate an object. So, we can update the value in that way, and it will take effect in any objects instantiated from Stat
.
We can also do the same for static methods.
public class Stat{
public static int x = 5;
public int y;
public Stat(int an_y){
this.y = an_y;
}
public static int sum(int a){
return x + a;
}
}
We have now added a static method sum()
to our Stat
class. The important thing to remember is that a static method cannot access any non-static attributes or methods, since it doesn’t have access to an instantiated object. Likewise, we cannot use the this
keyword inside of a static method.
As a tradeoff, we can call a static method without instantiating the class either, as in this example:
public class Main{
public static void main(String[] args){
//other code omitted
Stat.x = 25;
Stat moreStat = new Stat(7);
System.out.println(moreStat.sum(5)); // 30
System.out.println(Stat.sum(5)); // 30
}
}
This becomes extremely useful in our main()
method. Since the main()
method is always static, it can only access static attributes and methods in the class it is declared in. So, we can either create all of our additional methods in that class as static
methods, or we can instantiate the class it is contained in.
Another major feature of class inheritance is the ability to define a method in a parent class, but not provide any code that implements that function. In effect, we are saying that all objects of that type must include that method, but it is up to the child classes to provide the code. These methods are called abstract methods, and the classes that contain them are abstract classes. Let’s look at how they work!
In the UML diagram above, we see that the describe()
method in the Vehicle
class is printed in italics. That means that the method should be abstract, without any code provided. To do this in Java, we simply must use the abstract
keyword on both the method and the class itself:
public abstract class Vehicle{
private String name;
protected double speed;
public String getName(){ return this.name; }
protected Vehicle(String name){
this.name = name;
this.speed = 1.0;
}
public double move(double distance){
System.out.println("Moving");
return distance / this.speed;
}
public abstract String describe();
}
Notice that the keyword abstract
goes after the security modifier, but before the class
keyword on a class declaration and the return type on a method declaration.
In addition, since we have declared the method describe()
to be abstract, we must place a semicolon after the method declaration, without any curly braces. This is because an abstract method cannot include any code.
Now, any class that inherits from the Vehicle
class must provide an implementation for the describe()
method. If it does not, that class must also be declared to be abstract. So, for example, in the UML diagram above, we see that the MotorVehicle
class does not include an implementation for describe()
, so we’ll also have to make it abstract.
We can also declare a class to be abstract without including any abstract methods. By doing so, it prevents the class from being instantiated directly. Instead, the class can only be inherited from, and those child classes can choose to be instantiated by omitting the abstract
keyword.
Let’s build a quick program following the MVC architecture style to review working with classes, object, inheritance, and polymorphism.
Write a program to store a list of students and teachers at a school. The program should have methods to add a student or a teacher, as well as a method to print the entire list.
The program should conform to the following UML diagram:
Right-click and select “Open image in new tab” to view larger
The purpose of each method will be further described below.
Person
ClassPerson()
- constructor that initializes all attributes based on parametersgetLastName()
- getter for lastName
attributegetFirstName()
- getter for firstName
attributegetAge()
- getter for age
attributehappyBirthday()
- method to increase person’s age
attribute by $1$toString()
- method that overrides the built-in Object
class toString()
method. It should return a string in the form "firstName lastName: age"
Student
ClassStudent()
- constructor that initializes all attributes (including in super class) based on parametersgetStudentID()
- getter for studentID
attributegetGradeLevel()
- getter for gradeLevel
attributehappyBirthday()
- method to increase student’s age
and gradeLevel
attribute by $1$toString()
- method that overrides the built-in Object
class toString()
method. It should return a string in the form "firstName lastName: age (studentID - gradeLevel)"
Teacher
ClassTeacher()
- constructor that initializes all attributes (including in super class) based on parametersgetClassroom()
- getter for classroom
attributegetSalary()
- getter for salary
attributehappyBirthday()
- method to increase teacher’s age
by $1$ and salary
attribute by $1000$toString()
- method that overrides the built-in Object
class toString()
method. It should return a string in the form "firstName lastName: age (classroom - $salary)"
View
ClassshowMenu()
- a method to show a menu of options to the user. The user should be prompted to input exactly one of the options listed below, which is returned as a String. The wording of the menu is up to you. The method should return whatever was input by the user, without any error checking (that is done in the Controller)
addStudent()
- a method to add a new student to the system. The user should input a list of parameters for each attribute as they are listed in the constructor for Student
, separated by spaces. The wording of the prompt is up to you. The method should return whatever was input by the user, without any error checking (that is done in the Controller)
addTeacher()
- a method to add a new teacher to the system. The user should input a list of parameters for each attribute as they are listed in the constructor for Teacher
, separated by spaces. The wording of the prompt is up to you. The method should return whatever was input by the user, without any error checking (that is done in the Controller)listPeople()
- a method to list all Person
objects in the persons
array given as a parameter. Each one should be prefixed by an index starting at $0$, incrementing by one for each Person
in the array. Remember that unused array slots will contain the value null
so that should be considered in your code.
showError()
- a method to display an error to the user. The parameter error
should be printed to the screen, prefixed by “Error: "Controller
Classmain()
- the main method for this program. It should simply instantiate a new instance of the Controller class, and then call the run()
method of that object.Controller()
- the constructor for the Controller object. It initialize the persons
attribute to an array with a maximum size of 20 items, as well as a View
object stored in the view
attribute.run()
- this method consists of a loop that will execute the program until it is terminated. It will call the showMenu()
method of the view to show a menu to the user (see above). Finally, it will parse the string returned by the call to showMenu()
and call additional appropriate methods in the Controller
or View
class to complete the operation. If the user inputs “exit” then it should terminate. Otherwise, the program will repeatedly display the menu to the user until “exit” is chosen. If at any time the user provides input that cannot be properly parsed, the controller should call the showError()
method in the View
class and restart the process (loop back to the beginning) by showing the menu again.addStudent()
- this method will receive the string input by the user from the addStudent()
method in View
, parse the input, and call the appropriate methods to create a new Student
object and add it to the first empty slot in the persons
array.addTeacher()
- this method will receive the string input by the user from the addTeacher()
method in View
, parse the input, and call the appropriate methods to create a new Teacher
object and add it to the first empty slot in the persons
array.getPersons()
- this method will simply return the current persons
attribute as an array. This is for testing purposes onlysetPersons()
- this method will replace the persons
attribute with the array provided as a parameter. This is for testing purposes only.A sample execution of the program is shown below.
{Check It!|assessment}(test-3269626908)
{Check It!|assessment}(test-2757569305)
{Check It!|assessment}(test-2923816668)
{Check It!|assessment}(test-3356253417)
{Check It!|assessment}(test-2664871931)
{Check It!|assessment}(test-3442438399)
{Check It!|assessment}(test-163667115)
{Check It!|assessment}(test-496994260)
{Check It!|assessment}(test-2263639856)
{Check It!|assessment}(test-2809305019)
public class Person{
private String lastName;
private String firstName;
private int age;
public Person(String lastName, String firstName, int age){
this.lastName = lastName;
this.firstName = firstName;
this.age = age;
}
public String getLastName(){ return this.lastName; }
public String getFirstName(){ return this.firstName; }
public int getAge(){ return this.age; }
public void happyBirthday(){
this.age = this.age + 1;
}
@Override
public String toString(){
return this.firstName + " " + this.lastName + ": " + this.age;
}
}
public class Student extends Person{
private int studentID;
private int gradeLevel;
public Student(String lastName, String firstName, int age, int studentID, int gradeLevel){
super(lastName, firstName, age);
this.studentID = studentID;
this.gradeLevel = gradeLevel;
}
public int getStudentID(){ return this.studentID; }
public int getGradeLevel(){ return this.gradeLevel; }
@Override
public void happyBirthday(){
super.happyBirthday();
this.gradeLevel = this.gradeLevel + 1;
}
@Override
public String toString(){
return super.toString() + " (" + this.studentID + " - " + this.gradeLevel + ")";
}
}
public class Teacher extends Person{
private String classroom;
private int salary;
public Teacher(String lastName, String firstName, int age, String classroom, int salary){
super(lastName, firstName, age);
this.classroom = classroom;
this.salary = salary;
}
public String getClassroom(){ return this.classroom; }
public int getSalary(){ return this.salary; }
@Override
public String toString(){
return super.toString() + " (" + this.classroom + " - $" + this.salary + ")";
}
}
import java.util.Scanner;
public class View{
public String showMenu(){
System.out.println("Please enter one of the following options:");
System.out.println(" add student");
System.out.println(" add teacher");
System.out.println(" list people");
System.out.println(" exit");
try{
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
return input;
}catch(Exception e){
return "";
}
}
public String addStudent(){
System.out.println("Please enter the following items for the new student, all on the same line");
System.out.println("LastName FirstName Age StudentID GradeLevel");
try{
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
return input;
}catch(Exception e){
return "";
}
}
public String addTeacher(){
System.out.println("Please enter the following items for the new teacher, all on the same line");
System.out.println("LastName FirstName Age Classroom Salary");
try{
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
return input;
}catch(Exception e){
return "";
}
}
public void listPeople(Person[] persons){
System.out.println("The school contains the following people:");
int i = 0;
for(Person p : persons){
if(p == null){
continue;
}
System.out.println(i + ") " + p.toString());
i++;
}
}
public void showError(String error){
System.out.println("Error: " + error);
}
}
public class Controller{
private Person[] persons;
private View view;
private int size;
public static void main(String[] args){
new Controller().run();
}
public Controller(){
this.persons = new Person[20];
this.view = new View();
this.size = 0;
}
public void run(){
while(true){
String input = view.showMenu();
if(input.equals("add student")){
addStudent(view.addStudent());
}else if(input.equals("add teacher")){
addTeacher(view.addTeacher());
}else if(input.equals("list people")){
view.listPeople(persons);
}else if(input.equals("exit")){
break;
}else{
view.showError("Invalid Input!");
}
}
}
public void addStudent(String input){
String[] splits = input.split(" ");
try{
Person p = new Student(splits[0], splits[1], Integer.parseInt(splits[2]), Integer.parseInt(splits[3]), Integer.parseInt(splits[4]));
if(size < 20){
persons[size++] = p;
}else{
view.showError("Array full!");
}
}catch(Exception e){
view.showError("Unable to parse input!");
}
}
public void addTeacher(String input){
String[] splits = input.split(" ");
try{
Person p = new Teacher(splits[0], splits[1], Integer.parseInt(splits[2]), splits[3], Integer.parseInt(splits[4]));
if(size < 20){
persons[size++] = p;
}else{
view.showError("Array full!");
}
}catch(Exception e){
view.showError("Unable to parse input!");
}
}
public Person[] getPersons() { return persons; }
public void setPersons(Person[] input) { persons = input; }
}