Where I want everybody to be after demonstration 4, or at least very soon. This demo paper contains additional information that I had no time to provide last week.
You know all the primitive types available in Java.
You know how to define a subroutine that takes any number of parameters, and returns a value of any primitive type available in Java.
You are able to divide a long program into subroutines.
You understand that the public static void main(String[] args){...} declaration is nothing more than a subroutine that takes one argument of type String[] (later we'll see what this type actually means, it is not a primitive type but an array object reference) and returns nothing (void written as the return type). The Java virtual machine works in such a way that main is called, and the command line arguments are passed in the array parameter.
Each subroutine works in the same way internally: Parameters and all variables declared within the body block are local to the subroutine; only way that a subroutine communicates with the outside world are:
- when called, the numerical values of the parameters get copied from the callers local variables (the variables themselves are not transferred, only the numerical values as they are coded into bits!)
- when the subroutine returns (it's "activation" ends), its return value is copied as a numerical value to the calling subroutine's expression that is being evaluated.
Now the overall structure of our programs is as complicated as it ever gets during Programming 1. There is the obligatory main-method (to make the program executable), and there is any number of additional methods. A generic example:
public class TheNameOfYourProgram { public static double fahrenheitFromCelsius(double cels){ double result = (9.0/5)*cels + 32.0; return result; } public static void printHello(String username){ System.out.printf("Hello %s! Hope you're well.%n", username); } /* ... any number of method declarations ... */ public static void main(String[] args){ /* We can call other methods from here. Example: */ printHello("user, whose name I do not know"); double t = temperatureRightNow(); printf("It is now %f celsius which is %.4f fahrenheit.", t, fahrenheitFromCelsius(t)); /* ... any number of method calls ... * preferrably not very many; we'll see that methods can * call each others, and also re-call themselves recursively. * It means that each method can be made nice and small by * itself. */ } }
Agenda for the next step:
- We must deepen the knowledge of subroutines (=method / function / subprogram / whateverNameOfTheSameConcept) and the ingredients: parameters, local variables, and returning the result value.
- Let us take on additional structures this time: while and do-while. [Previously, we have seen the if and for structures. And we also should've been using return (it wasn't in my materials, but then again, it can't have all the information; you need to read textbooks and WWW materials in addition to my short notes!. Later we add at least switch, break, continue, try-catch-finally, throw, and labelled statements. ]
In this demonstration, we try to make proper programs where subroutines are using each other. Always follow strictly the code conventions!
Contents
Last time I showed this on the whiteboard, but here it is also in printed format. These are the types available in Java, and their purpose. Each variable type is essentially a numerical value, represented in bits. Some considerations:
The integer types are coded as "two's complement" values where the most significant bit denotes the sign, zero is represented as "all bits zero", and -1 is represented as "all bits one".
The character type is a 16-bit Unicode character encoding.
float and double are the standardized single and double precision floating-point encodings (specifically, in Java, they are the 32 and 64 bit variations of floating point numbers; there might be some platform-specific issues, which you'll have to find out from other sources; seek information about the keywords "Java floating point strictfp", if you need to know more).
Boolean (truth value) type is encoded in bits, but the number of bits is unspecified (might depend on the JVM implementation)
Reference types ("addresses of objects") are numerical values; the number of bits, and how these are used internally, depends on the implementation of JVM. What you need to understand are two things:
- Where there is a reference, there is a numerical value of a certain length in bytes. (I suppose it's 4 bytes in Sun's JVM working on 32-bit Windows, but I'm not sure.)
- You don't care how the value is used by the JVM to address objects, i.e., you can't see, and you don't need to see, how this translates to the actual location of an object, or how an object or class is represented in the machine. You just need to understand.
OK. Here's the table:
Meaning Type size in bits Example of a literal truth value boolean ? true, false character char 16 'A', '\u0041' integer byte 8 14, 123, -128, 0x7A integer short 16 -14, 0123, 32767 integer int 32 14, -1234, 32767 integer long 64 14L, 9223372036854775807 real numbers float 32 14.0, 1.234, 3.4e38 real numbers double 64 14.0, 1.234, 4.9e-324 reference AnyIntf ? String, Scanner, short[]
There are no more types in Java, but you must note that an object reference can be to any type of object (or, actually, an object with the specified interface). So there are as many types of references as you can think of different kinds of objects (Car, BillingSystem, GameBoard, CrissCrossPotato, SalsaSauce, LittleGreenPerson, UniversityStudent, ... in theory, an infinite number of classes of objects). But there are only eight kinds of primitive types. All data structures in Java boil down to objects that contain these types of numerically coded values.
Exercise 1:
Learn about the Gregorian Calendar and leap years here: http://en.wikipedia.org/wiki/Leap_year
Using the information, make a subroutine that takes as an integer parameter a year, and provides as return value a truth value that tells you whether the year is a leap year or not. A common way to name this kind of subroutine (method) in Java would be "isLeapYear". Usage:
if (isLeapYear(someYear)) /*... Handle differently somehow...*/
Exercise 2:
Make a subroutine that uses double-valued parameters and return values. It's purpose is to make a conversion between monetary units. It has to take as parameters: an amount of money in a currency, and a conversion rate between two currencies. It has to return: the same amount of money in the different currency. For example, you'd be converting like this:
/*Today's rate of 1 euro in AED (currency of United Arabic Emirates)*/ double dirhamRate = 5.2793; double moneyInEuros = 70.0; double moneyInDirham = convertMoney(moneyInEuros, dirhamRate);
Exercise 3:
Let's make a lot of subroutines for handling temperatures. Last time you made a method callable like the following:
double tempFahr = calcFahrFromCels(2.0);
Now, make a completely new program that has the following:
- Subroutine rankineFromKelvin that returns a temperature in the Rankine scale (Kelvin degrees times 1.8)
- Subroutine kelvinFromRankine that returns a temperature in the Kelvin scale (Rankine divided by 1.8)
- Subroutine celsiusFromKelvin that returns a temperature in the Celsius scale (Kelvin - 273.15)
- Subroutine kelvinFromCelsius that returns a temperature in the Kelvin scale (Celsius + 273.15)
- Subroutine fahrenheitFromKelvin that returns a temperature in the Fahrenheit scale (Kelvin times 1.8 minus 459.67)
- Subroutine kelvinFromFahrenheit that returns a temperature in the Kelvin scale ((Fahrenheit plus 459.67) times 1.8)
- Subroutine fahrenheitFromCelsius that works in the following way: It first computes kelvin using the subroutine kelvinFromCelsius and then returns fahrenheit using fahrenheitFromKelvin. Verify that this works in the same way as the previous direct conversion. This is to show you that subroutines can call each other, and that you can convert things into a convenient internal representation. This is a trivial example, but a small and understandable one.
You can have interactive console programs where the user inputs some values from the keyboard. In a Java program, you get to this by using the standard input. We'll look more into this when we enter object orientation properly, but first let us just use the following code:
import java.util.Scanner; /*This goes to the beginning of your program, where the syntax allows the import statements*/ ... Scanner sc = new Scanner(System.in); /* This makes an object that is able to read numerical values from the character input stream that comes from the user's keyboard.*/ /* Read like this:*/ int someInteger = sc.nextInt(); double someDouble = sc.nextDouble(); String aWholeLineOfText = sc.nextLine();
In the near future, you'll need to be able to read the so-called API documentation of the Java classes. Begin by skimming through the Scanner documentation:
http://java.sun.com/javase/6/docs/api/java/util/Scanner.html
There's a lot of text over there. Try to manage the documentation on different levels: Introduction, Summaries, Details. You should be able to locate the methods invoked on a Scanner object that were used in the above example, and also a lot of others with very similar names and interface definitions. Look at what you can do with a scanner.
Exercise 4:
Make an addition to your currency program: The program should ask the user (Print out a question and expect an answer that is stored to a variable) both the currency exchange rate and the amount of money to be converted. It should then output the result, as the original program that used a "hard-coded" test case.
We have seen how the for structure iterates over some values. Let us look at some simpler loop structures. Examples:
do { interactiveCurrencyExchange(); } while (userWantsToContinue());
The above would call the subroutine interactiveCurrencyExchange at least once. And this would be repeated as long as the truth value returned by the subroutine userWantsToContinue is true. Another:
while (userWantsToConvertMoney) { interactiveCurrencyExchange(); }
This would repeat interactiveCurrencyExchange as long as userWantsToConvertMoney is true; perhaps the loop never happens, if userWantsToConvertMoney returns false in the first place.
Exercise 5:
Make two programs where you do the following:
- interactiveCurrencyExchange performs like the program in Exercise 4.
- userWantsToConvertMoney and/or userWantsToContinue asks the user if he/she wants to continue using the program, and returns the answer as boolean value.
- your main method will contain exactly the loops given in the examples above.