Chapter:Classes - Declaring variables - Exercises

From Juneday education
Jump to: navigation, search

Exercises on variable declaration

We need to keep track of the members in the organisation, anything from a sport club to a car pool organisation. To do this we need the class Member which we're going to use as an abstraction of the actual (physical) members. Each physical member will have a corresponding Member instance (an object) in our system. We don't have knowledge yet on how to store many things of one kind in a good way, but that doesn't matter since the focus right now is to discuss and develop the Member class, so let's begin.

Q1

Create a class, Member in the package net.supermegacorp.orgmanager. Putting your class in a package also means you have to have a corresponding directory structure. So your file Member should be located in the directory structure like this net/supermegacorp/orgmanager

Expand using link to the right to see a suggested solution/answer.

Since the class name should be Member the following code must be stored in a file called Member.java. The content can be:

1 package net.supermegacorp.orgmanager;
2 
3 public class Member {
4 
5 }

Q2

Create a test class MemberTest, with a main method. You should use the package name in the package net.supermegacorp.orgmanager.test. In the main method you should create a Member instance.

Hint: you'll need to import net.supermegacorp.orgmanager.Member since Member is in a different package (and directory)

Expand using link to the right to see a suggested solution/answer.

Since the class name should be MemberTest the following code must be stored in a file called MemberTest.java. The content can be:

 1 package net.supermegacorp.orgmanager.test;
 2 
 3 import net.supermegacorp.orgmanager.Member;
 4 
 5 public class MemberTest {
 6 
 7   public static void main(String[] args) {
 8 
 9      Member m = new Member();
10   }
11 
12 }

Q3

Compile and run the MemberTest class. Don't expect anything to happen.

Expand using link to the right to see a suggested solution/answer.

To compile: javac net/supermegacorp/orgmanager/Member.java net/supermegacorp/orgmanager/test/MemberTest.java To execute: java net.supermegacorp.orgmanager.test.MemberTest

If you want to do the above on one line and execute only if compilation succeeds: javac net/supermegacorp/orgmanager/Member.java net/supermegacorp/orgmanager/test/MemberTest.java && java net.supermegacorp.orgmanager.test.MemberTest

Q4

Output, using println, the instance/object in the MemberTest class' main method (after you create the object of course).

Expand using link to the right to see a suggested solution/answer.

Add a normal println with the object as argument.

 1 package net.supermegacorp.orgmanager.test;
 2 
 3 import net.supermegacorp.orgmanager.Member;
 4 
 5 public class MemberTest {
 6 
 7   public static void main(String[] args) {
 8 
 9     Member m = new Member();
10     System.out.println(m);
11 
12   }
13 
14 }

Q5

Compile and run the code. You should see a printout that contains your class name Member followed by @ and some digits. We will look at how this printout will change through this lecture and in the coming lecture about inheritance we will reveal how the printout is done. What we can tell you right now is that there is no magic or philosophy behind this.

Expand using link to the right to see a suggested solution/answer.

The printout looks like this: net.supermegacorp.orgmanager.Member@717da562

Q6

Add, to the Member class, a instance variable, name with the type String. Make sure to use the public keyword. The keyword public makes it possible for everyone to read/write the variable.

Expand using link to the right to see a suggested solution/answer.

Add the String declaration in the class scope, like this:

1 package net.supermegacorp.orgmanager;
2 
3 public class Member {
4 
5   public String name;
6 
7 }

Q7

Compile and run the test class again. Nothing should have changed from above.

Expand using link to the right to see a suggested solution/answer.

To compile: javac net/supermegacorp/orgmanager/Member.java net/supermegacorp/orgmanager/test/MemberTest.java To execute: java net.supermegacorp.orgmanager.test.MemberTest .. and no changes in the printout.

Q8

In the test class' main method you should output the name variable of the Member instance. To access a public member (like the name variable) of an object, use the reference variable and a dot: myMember.name (if the reference variable is called myMember) You can put that between the parentheses of println (you give it as argument to println).

Expand using link to the right to see a suggested solution/answer.

To access the name variable in an object we use the . like this m.name. Printing it out will make the main code look like this:

 1   public static void main(String[] args) {
 2     // Here, we use the variable name "m" instead of myMember,
 3     // but the principle is the same!
 4 
 5     // Declare and initialize a referece variable with the name m
 6     // and initialize it to refer to a brand new Member
 7     Member m = new Member();
 8     // Now, we can print the reference m
 9     System.out.println(m);
10     // and we can use m to access the variable name
11     System.out.println(m.name);
12 
13   }

Q9

Compile and run the test class again. What value of name was printed? the variable name seems to have gotten, or actually really gotten, a value (null) even if we didn't assign it that. See Default values in Java for more information

Expand using link to the right to see a suggested solution/answer.

null can be seen on the screen. Since we have not assigned a value to name the default value (null) is still in use. When printing a reference with the value null, java simply outputs null.

Q10

Set the value of the name variable in the object to "Ada". Do this in the main method of MemberTest. To access a public member (like the name variable) of an object, use the reference variable and a dot: myMember.name = "Ada"; (if the reference variable is called myMember)

Expand using link to the right to see a suggested solution/answer.

An example of how this can be done:

1   public static void main(String[] args) {
2 
3     // Here we call the reference "m" and not myMember
4     Member m = new Member();
5     m.name = "Ada";
6     System.out.println(m);
7     System.out.println(m.name);
8 
9   }

Q11

Compile and run the test class again. What value of name was printed?

Expand using link to the right to see a suggested solution/answer.

Not so surprisingly "Ada" was printed.

Q12

Remove the code that outputted the value of name.

Expand using link to the right to see a suggested solution/answer.

An example of how this can be done is to turn the code into a comment:

1   public static void main(String[] args) {
2 
3     Member m = new Member();
4     m.name = "Ada";
5     System.out.println(m);
6     //System.out.println(m.name);
7 
8   }

Q13

Now, we will ask you to just do as we tell you - without really fully understanding what happens. You will get a nice result and in the coming lecture on Inheritance you will get an explanation on what's going on. Add the following code to your Member class' definition:

  @Override
  public String toString() {
    return name;
  }

Expand using link to the right to see a suggested solution/answer.

The class now looks like this

 1 package net.supermegacorp.orgmanager;
 2 
 3 public class Member {
 4 
 5   public String name;
 6 
 7   @Override
 8   public String toString() {
 9     return name;
10   }
11 
12 }

Q14

Compile your code and run the test class again. What happened to the initial output of the Member object?

Expand using link to the right to see a suggested solution/answer.

The output now looks like this: Ada Note that the same output before was net.supermegacorp.orgmanager.Member@717da562

With the method toString an object defines its own String representation.

Note that toString does not print anything. It returns a string.

Q15

Now add another instance variable, email, also of the type String to the Member class.

Expand using link to the right to see a suggested solution/answer.

The class now looks like this

 1 package net.supermegacorp.orgmanager;
 2 
 3 public class Member {
 4 
 5   public String name;
 6   public String email;
 7 
 8   public String toString() {
 9     return name;
10   }
11 
12 }

Q16

Compile your code and run the test class again. What happened to the output of the Member object?

Expand using link to the right to see a suggested solution/answer.

The output now looks like this: Ada. The value of email is not part of the String returned by the toString method.

Q17

Change the toString method in the Member class to look something like:

1   public String toString() {
2     return name + " " + email;
3   }

Expand using link to the right to see a suggested solution/answer.

The Member class now looks like this:

 1 package net.supermegacorp.orgmanager;
 2 
 3 public class Member {
 4 
 5   public String name;
 6   public String email;
 7 
 8   public String toString() {
 9     return name + " " + email;
10   }
11 
12 }

Q18

Compile your code and run the test class again. What happened to the output of the Member object?

Expand using link to the right to see a suggested solution/answer.

The output now looks like this: Ada null. Since the variable email has not been assigned a value, the default value null is still assigned and thus printed.

Q19

In your main method, change the value of the email address to "ada@lovelace.net"

Expand using link to the right to see a suggested solution/answer.

The MemberTest code now looks like:

 1 package net.supermegacorp.orgmanager.test;
 2 
 3 import net.supermegacorp.orgmanager.Member;
 4 
 5 public class MemberTest {
 6 
 7   public static void main(String[] args) {
 8 
 9     Member m = new Member();
10     m.name = "Ada";
11     m.email = "ada@lovelace.net";
12     System.out.println(m);
13     //System.out.println(m.name);                                           
14 
15   }
16 
17 }

Q20

Compile your code and run the test class again. What happened to the output of the Member object?

We now have a class Member that can be used in our Member management system. Objects creating from that class will have two instance variables, name and email. This means we (potentially) could continue writing our system. But to write such a system we need more knowledge, so in this course we will do a thing similar to the Member class, to continue practicing on the newly learnt concepts.

We will continue practicing by developing a class for a system for the police to keep track of the passport of a country's citizens.

An interesting difference between a Member and a passport is that in the former case, the Member, it feels natural to be able to update variables in an object. If, for example, a Member change email address it is still the same member so it feels natural that the system shall allow that as well. If we, on the other hand, want to update a passport, let's say we need to change the social security number of a person (to which the passport belongs) we'll need to create a new physical passport (not an updated). Should this be reflected in the code of the class? This is a question we (the authors) would love to spend more time on but right now we don't have the tools so we (the authors) will skip it.

Expand using link to the right to see a suggested solution/answer.

The output now looks like this: Ada ada@lovelace.net. Since the variable email has been assigned the value "ada@lovelace.net" which is printed alongside the value of name.

Q21

Create a class, Passport in a package called org.police.passportsystem The class should have a public String variable, name, to represent the person's (to which the passport belongs) name and a String variable, birth, which represents the birth date of the person.

Note: it is a good practice to use specialised classes to store dates, such as the Calendar class. We don't do this at the moment since we want you to be able to feel familiar. We also want you to see later on that the choice of String is not the best approach. Some authors and developers use Strings even when storing dates in a database. This is wrong for may reasons, the most obvious being that we can't trust the data in our database doing so. We aim at making you aware of the danger of doing so and give you an alternative solution.

Expand using link to the right to see a suggested solution/answer.

The passport class will look something like this:

1 package org.police.passportsystem;
2 
3 public class Passport {
4 
5   public String name;
6   public String birth;
7 
8 }

Q22

Write a test class, PassportTest in the package org.police.passportsystem.test, that creates a Passport instance and sets the name of the Passport to "Adam" and the birth date to "1994-01-01".

Now, compile both classes.

Expand using link to the right to see a suggested solution/answer.

The PassportTest class will look something like

 1 package org.police.passportsystem.test;
 2 
 3 import org.police.passportsystem.Passport;
 4 
 5 public class PassportTest {
 6 
 7   public static void main(String [] args) {
 8 
 9     Passport p = new Passport();
10 
11     p.name  = "Adam";
12     p.birth = "1994-01-01";
13 
14   }
15 
16 }

Compile and execute like this: javac org/police/passportsystem/Passport.java org/police/passportsystem/test/PassportTest.java && java org.police.passportsystem.test.PassportTest

23

It is "rather" unlikely, actually it would not make sense at all, that we need to change the birth date of a person, so we suggest that you change this variable to be private instead. And while we're at it, change the name variable to be private as well. Compile the class Passport (only that class).

Expand using link to the right to see a suggested solution/answer.

The Passport class will now look something like

1 package org.police.passportsystem;
2 
3 public class Passport {
4 
5     private String  name;
6     private String  birth;
7 
8 }

Compilation of the Passport class (javac org/police/passportsystem/Passport.java) succeeds.

24

Now, compile the PassportTest class as well. Will it work?

Expand using link to the right to see a suggested solution/answer.

Compilation of the PassportTest class (javac org/police/passportsystem/test/PassportTest.java) fails with the following message:

1 org/police/passportsystem/test/PassportTest.java:12: error: name has private access in Passport
2         p.name  = "Adam";
3          ^
4 org/police/passportsystem/test/PassportTest.java:13: error: birth has private access in Passport
5         p.birth = "1994-01-01";
6          ^
7 2 errors

We are not allowed to change the values of private variables.

Note that the error message may differ between different compilers and versions

Concluding remarks

Not being able to assign or read values from an object makes the keyword private useless, doesn't it? On the contrary. We recommend setting as many variables as possible as private. How to set them then? One way would be a method many authors and teachers like called Getters and Setters. We do not recommend this at all - at least not in the way it is most commonly taught. Instead we recommend setting the values in a constructor, which is, by pure coincident, the subject of the next chapter.

Another thing we'd like to point out, is that String is not a very good choice for the birth variable. It would be much better to use java.time.LocalDate.

You could experiment with this, just to get a feel for it. Here's an example of the passport class where we use a LocalDate:

package org.police.passportsystem;
import java.time.LocalDate;

public class Passport {

  private String  name;
  private LocalDate birth;

  // here we'd have a constructor, but that's something we'll learn in the next chapter

}

Links

Solutions (source code)

You can find complete source code to the suggested solutions below in the declaring-variables directory in this zip file or in the git repository.

Where to go next

Next page is: Classes_-_Defining_constructors

« PreviousBook TOCNext »