Static Members

No. 92

Class vs. instance

 Q: Is it possible to implement getDetails() from Figure 262, “Implementing membership numbers. ” as a class method by adding static? Is it possible to remove the static modifier from getMemberCount() in Figure 264, “Access to the club's overall member count? ”? A: Adding the static modifier yields: public class ClubMember { ... final private int memberNumber; final private String name; ... static public String getDetails() { return "Member " + name + ", member number " + memberNumber; } }The above code does not compile: The two variables name and memberNumber are instance variables. Trying to access these from a static context results in two compile time error messages: model/ClubMember.java:20: error: non-static variable name cannot be referenced from a static context return "Member " + name + ", member number " + memberNumber; ^ model/ClubMember.java:20: error: non-static variable memberNumber cannot be referenced from a static context return "Member " + name + ", member number " + memberNumber; ^ 2 errors Defining getMemberCount() as an instance rather than a class method is possible albeit discouraged: public class ClubMember { static private int memberCount = 0; ... public int getMemberCount() { return memberCount; } ... }Instance methods may access class variables. However calling the method now requires an instance: final ClubMember john = new ClubMember("John"), karen = new ClubMember("Karen"), petra = new ClubMember("Petra"); System.out.println(karen.getDetails()); System.out.println("Club's headcount:" + john.getMemberCount());This is actually a regression with respect to the static class method variant since the number of club members does not depend on individual member instances.

No. 93

Distinguishing leap- and non-leap years

 Q: In Leap years you already started a leap year related exercise. This exercise is about wrapping your implementation into a method: /** * Characterizing a given year either as leap year or * non- leap year * * @param year The year in question. * @return true if the year parameter is a leap year, false otherwise. */ public static boolean isLeapYear(int year) { ... }Write unit tests prior to actually implementing boolean isLeapYear(int year)! After finishing you should also be able to test your implementation manually: public static void main(String[] args) { System.out.println("Is 1800 a leap year? " + isLeapYear(1800)); System.out.println("Is 2000 a leap year? " + isLeapYear(2000)); System.out.println("Is 2016 a leap year? " + isLeapYear(2016)); }This should produce the following output:Is 1800 a leap year? false Is 2000 a leap year? true Is 2016 a leap year? true A: Maven module source code available at sub directory P/Sd1/leapYear below lecture notes' source code root, see hints regarding import. Online browsing of API and implementation. We start by a dummy implementation:public static boolean isLeapYear(int year) { return true; // Wrong in most cases, we yet don't care. }This enables us writing unit tests beforehand:/** * Testing leap year behaviour. */ public class LeapYearTest { /** * Test for leap years */ @Test public void testLeapYearPositive() { assertTrue(LeapYear.isLeapYear(2000)); assertTrue(LeapYear.isLeapYear(1984)); } /** * Test for non-leap years */ @Test public void testLeapYearNegative() { assertFalse(LeapYear.isLeapYear(2001)); assertFalse(LeapYear.isLeapYear(1800)); } }Obviously all negative tests will fail. We now implement the desired method: public static boolean isLeapYear(int year) { if (year % 400 == 0) { // Every 400 years we do have a leap year. return true; } else if (year % 4 == 0 && 0 != year % 100) { // Every 4 years we do have a leap return true; // year unless the year in // question is a multiple of 100. } else { return false; } }This one is easy to read. Experienced programmers however prefer compact code: public static boolean isLeapYear(int year) { return year % 400 == 0 || // Every 400 years we do have a leap year. year % 4 == 0 && 0 != year % 100; // Every 4 years we do have a leap year // unless the year in question ... }

No. 94

A method for printing square numbers using for, while and do ... while

 Q: You already did exercises on printing mathematical tables. This exercise is about decomposing tasks into methods thereby improving code readability. We also explore using different loop types. Consider the following example:public class LoopExample { public static void main(String [] args) { squareNumbers(14); } /** * Compute all square numbers starting from 4 in steps of 3 being smaller * than a given limit. The results are being written to standard output. * Implemented by a for -loop. * * @param limit An upper exclusive bound for the highest number to be squared.. */ public static void squareNumbers(final int limit) { System.out.println("Computing square numbers"); for (int i = 4; i < limit; i += 3) { System.out.println("i = " + i + ", i * i = " + i * i); } System.out.println("Finished computing square numbers"); } }Re-implement the above code in two different ways: while (...) {...} loop:  ... public static void while_squareNumbers(final int limit) { System.out.println("Computing square numbers"); ... while (...) { ... } System.out.println("Finished computing square numbers"); } ... do {...} while(...) loop:  ... public static void while_squareNumbers(final int limit) { System.out.println("Computing square numbers"); ... do { ... } while(...); System.out.println("Finished computing square numbers"); } ... Caveat: The do {...} while(...) part is a little bit tricky. Read the method's documentation precisely to avoid a common pitfall. Do you have a comment choosing the right type of loop? A: The while loop is actually quite straightforward to implement: public class LoopExample { ... public static void while_squareNumbers(final int limit) { System.out.println("Computing square numbers"); int i = 4; while (i < limit) { System.out.println("i = " + i + ", i * i = " + i * i); i += 3; } System.out.println("Finished computing square numbers"); } ...Its tempting to implement a do ... while in a similar fashion: public class LoopExample { ... public static void doWhile_squareNumbers(final int limit) { System.out.println("Computing square numbers"); int i = 4; do { System.out.println("i = " + i + ", i * i = " + i * i); i += 3; } while (i < limit); System.out.println("Finished computing square numbers"); } ...This implementation however is flawed: If we call doWhile_squareNumbers(3) we still receive one line of output. But according to the documentation no output is to be expected. Whatever the argument is, at least one output line gets printed. To avoid this error the loop has to be enclosed by an if- statement: public static void doWhile_squareNumbers(final int limit) { System.out.println("Computing square numbers"); int i = 4; if (i < limit) { // Needed !!! do { System.out.println("i = " + i + ", i * i = " + i * i); i += 3; } while (i < limit); } System.out.println("Finished computing square numbers"); }This required if-clause reminds us that a do {...} while (...) is an ill-suited choice here in comparison to a while(...){...} or a for(...){...} loop. Actually a for(...){...} loop is the best choice here since the number of iterations is known in advance, the increment is constant and it allows for initialization.