Never confuse education with intelligence, you can have a PhD and still be an idiot.
- Richard Feynman -

Chapter: Classes III

From Juneday education
Revision as of 16:38, 22 September 2016 by Rikard (Talk | contribs) (Videos for immutable Strings)

Jump to: navigation, search

Meta information about this chapter

See introduction in previous chapter Chapter:Classes for meta information.

Chapter Videos

See below for individual links to the videos.

Classes III - classes conclusion

Static variables and methods


So far, we have focused on instance variables, i.e. variables which every instance hold their own copy of. Now it's time to introduce variables that rather belong to the class itself and that every instance of the class "share". Such variables are called "class variables" or "static variables". The latter name comes from the fact that we use the modifier static when we declare such variables.

If you think about it, there are values which are not unique to every instance of a class, but rather shared. One example would be the interest rate of a bank account of some type. It is common that every bank account of the same type (e.g. a savings account) have the same interest rate. If every savings account have the same interest rate, say 0,01%, and if this interest rate would change for every bank account, should the bank decide to change it, then it is practical to have a mechanism for expressing that the variable holding the current interest rate is shared between all instances of the class SavingsAccount.

The modifier static has precisely this meaning when applied to a variable declared in the block of a class. An example with the interest rate could look something like:

public class SavingsAccount{
  private static double interestRate = 0.01; // percent, shared by all instances
  // instance variable declarations like balance etc...
  // constructors...
  // methods...

An indication that a variable should be static is that the variable holds some value which is relevant to talk about without any relation to specific instances of the class. Another indication is that it is safe and natural that the variable has the same impact on every instance of a class, in the sense that if the variable's value changes, every instance will be effected by the change.

If you compare this to an instance variable such as the balance for an instance of SavingsAccount, you will see that the opposite holds for instance variables. It is not desirable that when one instance of a bank account changes the amount of the balance, every other instance of a bank account should also be affected. And it is not relevant to talk about the balance without the context of a particular instance of a bank account. The balance is the balance of one particular bank account! Therefore the balance is an instance variable which every bank account object will have its own copy of (so that they can have different balance). But the interest rate of some class of bank account, like a SavingsAccount, is relevant to talk about, even before any accounts have been created (the first customer enters the bank and decides she wants a savings account, because she agrees with the interest rate).

What about static methods, then (aka class methods)? Like with static variables, a static method is declared using the modifier static, and like static variables, static methods exist independent of any instances of the class it belongs to. Going back to the SavingsAccount class, there could be a static method for changing the static variable interestRate, something like this:

public class SavingsAccount{
  private static double interestRate = 0.01; // percent
  public static void changeInterestRate(double newRate){
    // Some logic to check that it is a feasible value...
    interestRate = newRate;
  // instance variables...
  // constructors...
  // instance methods...

Another potential case for static methods are convenience methods which only calculate something from its parameters, like the many static methods declared in java.lang.Math, for instance public double sqrt(double d) which calculate the square root of its parameter (given as argument in the calling code). Such a method only operates on its parameters and can therefore exist totally independent of any instances. In fact, you cannot create instances of the class Math!

So how do we call a public static method? We use the class name (where the method is declared) and a dot followed by the method and arguments:

 A | \ C
  Calculate the length of C when we know the lengths of
  A (4)
  B (3)
  double a = 4.0;
  double b = 3.0;
  double c = Math.sqrt(3*3+4*4); // Pythagoras...

A class method, or as it's also called, a static method, can only operate on static variables and its parameters. Why? Because we can call it regardless of any instances, even before any instances of the class is constructed. It is not possible to use instance variables inside a static method, because we don't know if there is any instances or which instance they would belong to. This is because we can call a static method via the class name so there is no reference to any specific instance known to the method.

While instance methods always have the keyword this as a reference to the instance for which the instance method was called, there is no such thing for a static method, since they are called using the class name.


Exercises on static variables and methods

Let's go back to our Member class. We added a variable separator that we used to store the separator between values in our printout. We also discussed if we needed to have one separator variable per object. We don't. Instead we can let the class have a variable common for every object. This means that this variable belongs to (is associated with) the class instead of a separate object.

  1. Change the separator variable into a class variable, using the keyword static.
  2. Let's assume someone wants to know what separator is used when calling toString on Member objects. To let people get this value we can either:
    * make the variable public. A drawback of this is that people can change it. This makes it not usable for us.
    * keep the variable private and add a public method, getSeparator.
    Your job is to write the method as described last. Should this method be public or private? Should it be static or non-static?.
  3. Now, say that we want to change the value of the separator variable. Add a method, setSeparator(String separator), to change it.
  4. Can you motivate keeping the separator variable private when everyone can change it using the set method?
  5. Write a new class, StaticConfusion. Don't use any packages in this class (which makes the class get the nameless package). Write a main method that invokes the method email(). The class can look something like this:
    import net.supermegacorp.orgmanager.Member;
    public class StaticConfusion {
        public static void main(String[] args) {
    Compile. Did it work? Why?

Solutions to static variables and methods

Expand using link to the right to see the full content.

  1. Suggested solution (parts of the class):
    package net.supermegacorp.orgmanager;
    public class Member {
      private String name;
      private String email;
      private static String separator = ";";
      public String toString() {
        return name + separator + email;
  2. Suggested solution (parts of the class):
    package net.supermegacorp.orgmanager;
    public class Member {
      private String name;
      private String email;
      private static String separator = ";";
      public static String getSeparator() {
        return separator;
      public String toString() {
        return name + separator + email;
    We need to make the method public since we want others to be able to use it. It does not have to be static since all objects can reach the class, but we suggest making it static to reflect that the variable is static.
  3. Suggested solution:
        public static String setSeparator(String separator) {
            this.separator = separator;
  4. The authors can not motivate Getters and Setters like this. But we will use the method in the next section so let's keep it for now.
  5. The class StaticConfusion will not compile. You'll get an error message similar to this: error: non-static method email() cannot be referenced from a static context
    1 error
    The method email() is an instance method which means it is associated with an object. Calling the method with an association to the class and no object does not make sense. This is similar to asking the blueprint of a mobile phone what phone number is has - it is instances of the mobile phone blueprint that has phone numbers.
    We have noticed that a common solution to this, even among teachers and supervisors, to make the method email() static. Try doing this and you'll find that you also need to make the instance variable email static. Et voila, it works. The "only" problem now is that all Member instances will share the same email address. So we urge you not to fall in to the common pattern we (the authors) are calling 'the static swamp anti-pattern'. Think about if asking the class for an email address is wise in the first place and you'll directly remove or replace the call to Another solution is to create an object of the type Member, which is probably you wanted in the first place.

Section: final variables


Final variables, when used as global constants, are mentioned in the video for static variables.

Note: a method and a class can also be final but this does not make sense before we introduce inheritance so we'll skip it for now


  • No videos for this small section!

Exercises on final variables and methods

Let's go back to our Member class. We added a variable separator that we turned into a static variable, in the previous section. Why should anyone, including ourselves, be able to change it? We (the authors) see no reason to be able to change it. So let's make the variable "unchangeable".

  1. Make it impossible to change the separator variable. Do this by using the keyword final. Also make sure that the method setSeparator(String separator) is present in the code. Compile. Does it work?
  2. Remove the setSeparator(String separator) and compile again. Compile and explain why this happens.
  3. There is a coding convention which says that final static variables (constants) should be named with all upper case letters with underscore as word separator if the name consists of several words. What should you rename separator to? (No underscore is needed, since it consists of only one word)

Solutions to final variables and methods

Expand using link to the right to see the full content.

  1. Change the separator declaration to look something like this:
      private static final String separator = ";";
    It does not compile since we have a method setSeparator(String separator) that alters (changes) the values of separator which we have made final.
  2. Now it compiles again. So we can't change, or even provide a method with which we can change, the value of a final variable.

About Java packages


Just as we like to organize our files on our computer in a hierarchical structure using directories, we want to maintain such order in our Java programs as well. Programmers tend to organize the classes in the system in directories with a hierarchical structure with descriptive names of the directories. This has many benefits. One is that the classes get a "name space" using the package names as part of the full class name. This, in turn, allows us to have two or more classes in our system with the same name, if they belong to different packages.

The package name corresponds to the relative path to the class file (and source code file). This allows us not only to have descriptive names of classes where the package names are part of the full (qualified) class name, but also to have the same name of the actual class, since the class files are kept in separate directories:;;;

All the classes declared above are declared with the name LoginCredentials, but the qualified names show us the context. Just by looking at the full, qualified, names of the classes we understand that they are representations of the login credentials for different social network services.

Another benefit from using packages is that we can group classes together according to some criteria. For instance, we could have all the classes dealing with networking in a directory (and package!) and all classes which deal with the graphical user interface in another directory (and package!). This way, it is easy for the programmers working on the source code to find the source code files. If a programmer has to fix a problem with the internet connectivity of the system, she would be able to look at the directory names and figure out where the relevant source code files for the classes probably are located: "They are probably somewhere under org/somecompany/net...". And when another programmer needs to work on the graphical interface of the system, she would similarly probably think: "The classes for this are probably somewhere under org/somecompany/gui/..." (gui often stands for "Graphical User Interface").

The perhaps most striking reason for using packages (and the corresponding directory structure) is that the alternative would mean that we keep all source code files (and after compilation, all class files) in one big directory. For a large project with thousands of files, this would of course be a great mess.

Finally, a less obvious benefit for using packages, is that we could actually use the "default" or "package private" access level for variables and methods. This access level is what we get when we don't use any of "public", "private" or "protected". The absence of an access modifier keyword gives us this level which is called "package private" (or simply "default"). Such variables and methods are accessible within the class itself and from classes in the same package.

It is not uncommon that we would give some methods visibility only in related classes, so that those classes can use the method but no other classes in the system. Related classes, as we said above, should be put in the same directory (and package), so the default access level works fine in such a case. Let's go back to the SavingsAccount example. Perhaps we have a class responsible for changing the interest rate of the different bank account classes. If we put this class in the same package as the classes for the accounts, we could give the static method changeInterestRate(double) default access level. The benefit of this approach could be that we effectively prevent "unauthorized" classes (unrelated classes) to mess with the interest rate values of the different bank account classes. We could then centralize the security measures for deciding if an interest rate could be changed to the class which has access to the various changeInterestRate(double) methods of the respective classes.

But from a foreign (unrelated) class, like org.somecompany.main.Main, the various changeInterestRate methods are not accessible, since this class belongs to a different package.


Exercises on grouping stuff in packages

This exercise aims to make you reflect on how one could divide classes into packages.

Given the following classes for some project, how could you divide the classes into directories (and packages) which better describe their role in the project? Be creative! There is not one single answer to this question, you have to use your imagination here.

$ ls -1

Solutions to grouping stuff in packages

Expand using link to the right to see the full content.

One possible division could be the following:

|-- literature
|   |--
|   `--
|-- main
|   `--
|-- math
|   `--
|-- test
|   `--
`-- text

Testing if your classes work

How do we know a class working the way we want it to? We need to test it. There are several test strategies and methods which could be the basis a separate course. In this course we'll provide some tips and tricks for you when writing code.

Let's look at a version of our Member class again:

package net.supermegacorp.orgmanager;

public class Member {

  private String name;
  private String email;
  private static final String separator = ";";

  public Member(String name, String email) {

  public Member(String name) { = name;

  public void setEmail(String email) {
    if (email.contains("@")) { = email;
  public String toString() {
    return name + separator + email;
  public String name() {
    return name;
  public String email() {
    return email;

  public static String getSeparator() {
    return separator;

What do we need to test (or verify) in this class? In the first constructor we have two parameters. The second argument is only valid if there's an "@" in it so let's write code to:

  • create a Member object with a valid email address
  • create a Member object with an invalid email address
  • create a Member object with null as an email address

let's do this first and then write code to make sure the values were set accordingly.

So let's start with the following test class:

 1 package net.supermegacorp.orgmanager.test;
 3 import net.supermegacorp.orgmanager.Member;
 5 public class MemberTest {
 7     public static void main(String[] args) {
 8       Member ada     = new Member("Ada", "");
 9       Member charles = new Member("Charles", "charles __AT__");
10       Member bert    = new Member("Bert", null);
11     }
13 }

Compile and execute these tests. Wooops, we can compile but get an error when executing it:

Exception in thread "main" java.lang.NullPointerException
	at net.supermegacorp.orgmanager.Member.setEmail(
	at net.supermegacorp.orgmanager.Member.<init>(

	at net.supermegacorp.orgmanager.test.MemberTest.main(

Already we have seen a positive effect of our tests and we have just begun. At line 20 in the Member.class something goes wrong. Since Java says it is a NullPointerException we can deduce that emails is null. So we need to change the method setEmail() in our member class slightly. Let's write it like this instead:

1   public void setEmail(String email) {
2     if (email != null && email.contains("@")) {
3 = email;
4     }
5   }

The change here is that we make sure that the email address is not null before we invoke the contains method. Let's compile and execute again.

Nice, it seems to work or at least not crash. So let's continue writing code to check that the values were set accordingly. We give an example on how to do this below:

1     public static void main(String[] args) {
2       Member ada     = new Member("Ada", "");
3       Member charles = new Member("Charles", "charles __AT__");
4       Member bert    = new Member("Bert", null);
6       System.out.println("ada:      " +;
7       System.out.println("charles:  " +;
8       System.out.println("bert:     " +;
9     }

This is ok, but it is a bit tedious that the developer has to manually check the email addresses. Since we're (or at least trying to become) developers we want to automate this, so let's write:

1       if ( !"")) {
2           System.err.println("Ada's email " + + ") is faulty: ");
3       }
4       if ( != null ) {
5           System.err.println("charles' email  is faulty: ");
6       }
7       if ( != null ) {
8           System.err.println("bert's email  is faulty: ");
9       }

Now we get an error message if something is not ok. If all is well, Nothing is printed. This is a better approach but still not good. Let's use assertions (Programming With Assertions). Assertion is a statement that let's you test your code in a structured way. If we for example want to verify that a variable email has the value we write

1    assert email.equals("");

Think of this as "saying" to Java: I am assuming that the variable email has the value "". Can you check that for me. If I am wrong, force an error to occur.

If we translate the above (rather short) introduction to our MemberTest class we could write:

 1     public static void main(String[] args) {
 2       Member ada     = new Member("Ada", "");
 3       Member charles = new Member("Charles", "charles __AT__");
 4       Member bert    = new Member("Bert", null);
 6       assert"");
 7       assert;
 8       assert;
10     }

To compile the classes: javac net/supermegacorp/orgmanager/ net/supermegacorp/orgmanager/test/

To execute the class java -ea net.supermegacorp.orgmanager.test.MemberTest

Note: to enable the assertions you have to use -ea (enable assertions)

It is important to discuss tests a bit. What is it we've verified? Have we made sure our code (the Member class) always works as it should? Are we sure that our test code is correct? These are all questions that require, as we said above, a separate course or book so we will settle with some short remarks. With the tests above you have made sure the code does not crash when the tests were executed

You cannot say that the code always will work. But the tests above are at least better than nothing since they made us find some bugs.

Exercises on testing your classes

This exercise aims to make you familiar with how to write test code to test your classes.

You should Write test code to test the Passport class below

package org.police.passportsystem;

public class Passport {

    private String  name;
    private String  birth;

    public Passport(String name, String birth) {  = name;
	this.birth = birth;

    public String toString() {
	return name + " " + birth;

    public String name() {
	return name;

    public String birth() {
	return birth;

1 Create a class PassportTest in the package org.police.passportsystem The class should have a main method.

2 Add, to the main method in the test class above, code to create a passport object with the following arguments "Ada Lovelace" "1815-12-10". It really seems a bit odd to create a passport for someone who died many years ago but we couldn't resist to give a bit of history lesson. Make sure that the name and birth is stored correctly in the object.

Hint: you could check if the name in the Passport object has the same content as the text you passed as argument. Do the same with email.

3 Verify (or test) that the toString method returns the correct string.

Hint: create a string yourself with the expected result and compare that string with the actual string returned from the method.

Solutions to Testing your classes

Expand using link to the right to see the full content.

1 Suggested solution

1 package org.police.passportsystem.test;
3 public class PassportTest {
5     public static void main(String[] args) {
8     }
9 }

To compile and execute the tests: javac org/police/passportsystem/test/ && java -ea org.police.passportsystem.test.PassportTest 2 Suggested solution

 1 package org.police.passportsystem.test;
 3 import org.police.passportsystem.Passport;
 5 public class PassportTest {
 7     public static void main(String[] args) {
 9         Passport p        = new Passport("Ada Lovelace", "1815-12-10");
11         assert"Ada Lovelace");
12         assert p.birth().equals("1815-12-10");
13     }
14 }

To compile and execute the tests: javac org/police/passportsystem/test/ && java -ea org.police.passportsystem.test.PassportTest

3 Suggested solution

 1 package org.police.passportsystem.test;
 3 import org.police.passportsystem.Passport;
 5 public class PassportTest {
 7     public static void main(String[] args) {
 9         Passport p        = new Passport("Ada Lovelace", "1815-12-10");
10         String expected   = "Ada Lovelace 1815-12-10";
12         assert"Ada Lovelace");
13         assert p.birth().equals("1815-12-10");
14         assert p.toString().equals(expected);
15     }
16 }

To compile and execute the tests: javac org/police/passportsystem/test/ && java -ea org.police.passportsystem.test.PassportTest

Using our classes

Now that we have seen the rules on how to write classes with variables, constructors and methods, we'll look a little at how we use these classes in programs which actually do something. How do we write programs using our own classes?

  • Typically there is only one main in a separate class (not counting tests).
  • typically the Main class (class with the main) is in a separate package
    • typically you need a package statement here too because of that
    • typically you need import statements in the Main class (also because of that)
  • Other normal classes (classes we write that don't have the main method) often also uses other classes
    • If we write a class, it probably needs more classes which we also write ourselves
    • Related classes are in the same package and can "use" eachother without import (otherwise we need that)
    • One use can be as a return type for a method
    • Another use can be as the type of an instance variable

Exercises on using your own classes

This exercise aims to make you familiar with how to write programs which make use of the classes you define yourself.

  1. Question 1 TODO: write questions

Solutions to using your own classes

Expand using link to the right to see the full content.

  1. Solution to exercise 1...

Looking at the source code for some API classes


To demystify source code for classes we show briefly the source code for some classes in the API. We also show how to find the source code in (or how to get it).

  • java.lang.String (quick glance)
  • java.lang.System (quick glance)
  • java.lang.Math (quick glance - focus on private constructor and all the static methods)


  • No video for this section

Exercises on the source code for API classes

Locate the file on your system. It should be located in the Java installation directory, for instance under the JDK1.8XXX directory (the exact location might vary a little from computer system to computer system).

Copy this zip file to your home directory and some directory under it (we suggest that you start by creating a directory somewhere under your home directory and copy the zip file to that place).

Enter the directory where you put your copy of Unzip the zip file (this will create a lot of new files and directories, which is why we strongly urge you to do this in a new directory dedicated for this exercise).

$ unzip

Let's study the directory structure from this zip file a little. It is the directory tree under the java directory we are most interested in. List the contents of the java directory.

  1. What are the folder names under the java directory?
  2. Do you recognize any of the folder names from package names?
    Change directory to the relative path java/lang/. List the file
    $ cd java/lang
    $ ls
  3. Does the file java/lang/ exist?
    Let's look inside the file. You may open in an editor, or if you think it is easier to stay in the terminal, you can use a pager, such as less (to move around a file in less, use the arrow keys, to quit you press "q").
  4. What is the package declaration in the source code for String?
  5. How many methods called toUpperCase can you find in the source code for String?
  6. Locate the definition of the method toUpperCase() (with no arguments). What is the return type of that method?
  7. Go to the online API documentation for String (use a search engine if you don't know the address by heart). How many methods called toUpperCase does the documentation list?
  8. Also in the online API documentation, lookup toUpperCase() (with no arguments). Can you see that the return type is the same as in the source code?
  9. Now, look at the source code for java.lang.System. Are there any constructors?
  10. What is the access modifier for the constructor(s)?
  11. Can you create an instance of System? (If you don't know the answer from looking at the constructors, try to write a small program and to the following in the main method: System sys = new System();
  12. Locate the class variable with the name out. What is the full declaration of out?
  13. Can we use out from another class?
  14. Have you used out before?
  15. How would we use out from another class?
  16. What is the full class name (the qualified name) of the class which out is a reference to?
  17. How can the System class use the name PrintStream which is defined in another class in another package?
  18. Next, look at the source code for java.lang.Math. Can you create an instance of Math? Why?
  19. Are there any instance methods in java.lang.Math?
  20. How many methods are called max?
  21. What are the differences between the various versions of max()?

Solutions to looking at the source code for API classes

Expand using link to the right to see the full content.

For Java 7, the online API is located at [1] and for Java 8, it is located at [2]

  1. The folder names under the java directory are applet beans lang net rmi sql time awt io math nio security text util
  2. You might recognize lang, and util which are part of the packages java.lang and java.util. Remember, package names are relative paths, so the package java.lang correspond to the path java/lang and the package java.util correspsyith the java installation in the file rt.jar).
  3. Yes, it exists!
  4. package java.lang;
  5. 2 methods exist with the name toUpperCase
  6. The return type of the toUpperCase() method is String
  7. The documentation also lists two methods called toUpperCase
  8. Yes, the return type is listed as String also in the documentation
  9. Yes, there is one constructor in java.lang.System, private System(){}
  10. The access modifier of the only constructor in System is private
  11. It is not possible to call a private member of a class, and since the only constructor is private, it is not possible to create an instance of java.lang.System!
  12. The full declaration of out in System is: public final static PrintStream out = null;
  13. Yes, out is declared public, so we can use it from another class!
  14. out is declared public static, so the syntax from another class would be System.out
  15. Yes, you have used it many times, for printing to the standard out stream like this: System.out.println("hello");, for instance. The variable out is of type "reference to PrintStream" and PrintStream has an instance method called println which you have used many times.
  16. The out is of type reference to
  17. The class System has an import statement saying import*; which allows System to use the shorter class name PrintStream for
  18. No, you cannot create an instance of Math, because the only constructor is private.
  19. No, there are only static (class) methods in java.lang.math
  20. There are four methods in java.lang.Math called max
  21. The parameters differ. Max returns the greater of two numbers, and is defined for comparing:
    1. Two int numbers
    2. Two long numbers
    3. Two float numbers
    4. Two double numbers

Other keywords related to elements declared in classes


The following keywords also exist in the Java programming language:

  • volatile (variable modifier)
  • native (method modifier)
  • transient (variable modifier)
  • synchronized (method modifier)
  • protected (access modifier - both variables and methods)
  • strictfp (method, class and interface modifier)
  • and more...

We will not use any of the ones listed above in this course/book. If you want to read about them, we refer to the Java Language Specification If you want the full list of java keywords, please see here.

Strings are immutable

Videos for immutable Strings

  • TODO: [#link-to-vimeo-on-immutable-strings (Eng)] [#link-to-vimeo-on-immutable-strings (Swe)] PDF


Some objects are impossible to change once they are created. Such objects are said to be "immutable". Strings are examples of such objects. Once you have created a String, you cannot change it.

There are instance methods in the class String which might lead you to think that you can change a String object, such as toLowerCase(), concat(), append() etc.

But every such instance method in the class String actually returns a reference to a brand new String object with a state as if the previous object would have been changed!

Some examples might be in place:

// Change all letters to lower case:
String city = "Liverpool";
String lowerCaseCity = city.toLowerCase();

In the above example code, we must save the result of calling toLowerCase() in a variable if we are to use it. Simply calling city.toLowerCase() doesn't change the textual contents of the String referred to by city. So, this code below would compile but not change anything:

// call toLowerCase()
String city = "Liverpool";
// city is still representing "Liverpool" with a capital "L"

The append() method works in a similar way:

String city = "Liverpool";
String cityAndCountry = city.concat(", Great Britain");

Simply calling concat() on a String reference doesn't change the String referred to by the reference. It actually creates a new String object with the contents produced from concatenating the original String with the argument, and returns a reference to this new String. All instance methods in String works this way.

By the way, how do we check if two reference variables refer to the same instance/object? We can use the == operator!

When applied to reference variables, the == operator compares the "address" (reference) of the two variables, which means "do they refer to the exact same object in memory?".

Consider the following snippets:

 Member first  = new Member("James");
 Member second = first;
 Member third  = new Member("James");
 System.out.println(first == second); // true  - same object!
 System.out.println(first == third);  // false - same name but different objects!
 System.out.println(second == second);// true  - same object!
 System.out.println(second == third); // false - same name but different objects!

And, using Strings:

 String name = "James";
 String fullName = name.concat(" Brown");
 System.out.println(name==fullName); // false - concat creates a new object!
 System.out.println( name==name.concat(" Stewart") ); // false - concat creates a brand new object!

If we want to check whether two different objects should be considered "equal" to each other, we must use a method called equals() instead. String has a functioning version of this method:

 String name = new String("James");
 String otherName = new String("James");
 System.out.println( name.equals(otherString) ); // true - different objects, but the same contents!

Bonus information (you may skip this part if you want, it is only for the keen students who want to know the whole truth):

There is actually something special with some immutable classes like String. Java maintains a pool of String objects created with the special syntax with double quotes: String s = "Some text";. Since Strings are immutable and will never change, they can be reused by the runtime system. So creating two Strings using the double quote style with the same text, actually only creates one String object! So this would print true:

 String one = "Hello";
 String two = "Hello";
 System.out.println(one==two); // true - actually only one object is created and reused...

But using the operator new when creating a String really creates a brand new object, regardless of the pool of reusable existing String objects. So the following will print "false":

 String one = "Hello";
 String two = new String("Hello");
 System.out.println(one==two); // false - the operator new forces the creation of a new object!

Exercises on immutable Strings

TODO: Some exercises (if needed)

Solutions to immutable Strings

Expand using link to the right to see the full content.

  1. TODO: write Solution to exercise 1...

Chapter Links

External links

Books this chapter is a part of

Programming with Java book

Book TOC | previous chapter | next chapter