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



Difference between revisions of "Chapter:Classes - Static members"

From Juneday education
Jump to: navigation, search
(Fixed navigation)
(Added topic progression, removed exercises)
Line 1: Line 1:
=Meta information about this chapter=
+
= Classes: Static variables and methods=
 
+
See introduction in previous chapter [[Chapter:Classes]] for meta information.
+
 
+
==Chapter Videos==
+
 
+
* Classes III [https://vimeo.com/channels/1133606 (English)] [https://vimeo.com/channels/1133608 (Swedish)]
+
See below for individual links to the videos.
+
 
+
= Classes III - classes conclusion =
+
 
+
==Static variables and methods==
+
===Description===
+
 
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 <code>static</code> when we declare such variables.
 
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 <code>static</code> when we declare such variables.
  
Line 67: Line 55:
  
 
While instance methods always have the keyword <code>this</code> 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.
 
While instance methods always have the keyword <code>this</code> 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.
===Videos===
+
==Chapters about classes==
 +
Here are the chapters about classes in this book, so that you can keep a check on your progress:
 +
* [[Chapter:Classes_-_Introduction]]
 +
** [[Chapter:Classes_-_Introduction_-_Exercises]]
 +
* [[Chapter:Classes_-_Declaration]]
 +
** [[Chapter:Classes_-_Declaration_-_Exercises]]
 +
* [[Chapter:Classes_-_Packages]]
 +
** [[Chapter:Classes_-_Packages_-_Exercises]]
 +
* [[Chapter:Classes_-_main]]
 +
** [[Chapter:Classes_-_main_-_Exercises]]
 +
* [[Chapter:Classes_-_Commenting_code]]
 +
** [[Chapter:Classes_-_Commenting_code_-_Exercises]]
 +
* [[Chapter:Classes_-_Declaring_variables]]
 +
** [[Chapter:Classes_-_Declaring_variables_-_Exercises]]
 +
* [[Chapter:Classes_-_Defining_constructors]]
 +
** [[Chapter:Classes_-_Defining_constructors_-_Exercises]]
 +
* [[Chapter:Classes_-_Defining_methods]]
 +
** [[Chapter:Classes_-_Defining_methods_-_Exercises]]
 +
* '''[[Chapter:Classes_-_Static_members]]''' « you are here!
 +
** [[Chapter:Classes_-_Static_members_-_Exercises]]
 +
* [[Chapter:Classes_-_final_members]]
 +
** [[Chapter:Classes_-_final_members_-_Exercises]]
 +
* [[Chapter:Classes_-_Using_packages]]
 +
** [[Chapter:Classes_-_Using_packages_-_Exercises]]
 +
* [[Chapter:Classes_-_Testing_your_classes]]
 +
** [[Chapter:Classes_-_Testing_your_classes_-_Exercises]]
 +
* [[Chapter:Classes_-_Using_your_classes]]
 +
** [[Chapter:Classes_-_Using_your_classes_-_Exercises]]
 +
* [[Chapter:Classes_-_API_source_code]]
 +
** [[Chapter:Classes_-_API_source_code_-_Exercises]]
 +
* [[Chapter:Classes_-_Other_keywords]]
 +
** [[Chapter:Classes_-_Other_keywords_-_Exercises]]
 +
* [[Chapter:Classes_-_Strings_are_immutable]]
 +
** [[Chapter:Classes_-_Strings_are_immutable_-_Exercises]]
 +
 
 +
=Videos=
 
* Static variables [https://vimeo.com/183329185 (Eng)] [https://vimeo.com/183329247 (Swe)] [[:Media:Classes_III_Static_variables.pdf|Static variables (pdf)]]
 
* Static variables [https://vimeo.com/183329185 (Eng)] [https://vimeo.com/183329247 (Swe)] [[:Media:Classes_III_Static_variables.pdf|Static variables (pdf)]]
 
* Static methods  [https://vimeo.com/183332858 (Eng)] [https://vimeo.com/183332870 (Swe)] [[:Media:Classes_III_Static_Methods.pdf|Static methods (pdf)]]
 
* Static methods  [https://vimeo.com/183332858 (Eng)] [https://vimeo.com/183332870 (Swe)] [[:Media:Classes_III_Static_Methods.pdf|Static methods (pdf)]]
  
===Exercises on static variables and methods===
+
=Links=
 
+
==Further reading==
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.
+
 
+
# Change the <code>separator</code> variable into a class variable, using the keyword <code>static</code>.
+
# Let's assume someone wants to know what separator is used when calling <code>toString</code> 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, <code>getSeparator</code>.
+
#: Your job is to write the method as described last. Should this method be public or private? Should it be static or non-static?.
+
# Now, say that we want to change the value of the <code>separator</code> variable. Add a method, <code>setSeparator(String separator)</code>, to change it.
+
# Can you motivate keeping the separator variable private when everyone can change it using the set method?
+
# Write a new class, <code>StaticConfusion</code>. Don't use any packages in this class (which makes the class get the nameless package). Write a main method that invokes the method <code>email()</code>. The class can look something like this:
+
#:<source lang="Java">
+
import net.supermegacorp.orgmanager.Member;
+
 
+
public class StaticConfusion {
+
 
+
    public static void main(String[] args) {
+
 
+
        Member.email();
+
 
+
    }
+
 
+
}
+
</source> 
+
#: Compile. Did it work? Why?
+
 
+
===Solutions to static variables and methods===
+
 
+
<div class="mw-collapsible mw-collapsed">
+
Expand using link to the right to see the full content.
+
<div class="mw-collapsible-content">
+
 
+
# Suggested solution (parts of the class):
+
#:<source lang="Java">
+
package net.supermegacorp.orgmanager;
+
 
+
public class Member {
+
 
+
  private String name;
+
  private String email;
+
  private static String separator = ";";
+
 
+
  public String toString() {
+
    return name + separator + email;
+
  }
+
}
+
</source>
+
# Suggested solution (parts of the class):
+
#:<source lang="Java">
+
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;
+
  }
+
}
+
</source>
+
#: 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.
+
# Suggested solution:
+
#:<source lang="Java">
+
    public static void setSeparator(String separator) {
+
        Member.separator = separator;
+
    }
+
</source>
+
# 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.
+
# The class StaticConfusion will not compile. You'll get an error message similar to this:
+
#:<source lang="bash">
+
StaticConfusion.java:7: error: non-static method email() cannot be referenced from a static context
+
        Member.email();
+
              ^
+
1 error
+
</source>
+
#:The method <code>email()</code> 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 <code>email()</code> static. Try doing this and you'll find that you also need to make the instance variable <code>email</code> 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 <code>Member.email(). Another solution </code> is to create an object of the type Member, which is probably you wanted in the first place.
+
</div>
+
</div>
+
 
+
 
+
=Chapter Links=
+
==External links==
+
 
* [https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html Oracle tutorial - Class variables (static)]
 
* [https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html Oracle tutorial - Class variables (static)]
 
* [https://docs.oracle.com/javase/tutorial/java/javaOO/classes.html Oracle's tutorial section on Classes]
 
* [https://docs.oracle.com/javase/tutorial/java/javaOO/classes.html Oracle's tutorial section on Classes]

Revision as of 09:58, 22 June 2017

Classes: 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
   |__\
     B
  
  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.

Chapters about classes

Here are the chapters about classes in this book, so that you can keep a check on your progress:

Videos

Links

Further reading

Where to go next

« PreviousBook TOCNext »