Java - syntax etc.
*** ← → Language basics From variables to statements to objects 'p s v m' Reminder - psvm is 'public static void main' - here again is the prototypical HelloWorld program:
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, Java World!");
}
}// HelloWorld
Create a folder called JavaLangBasics, save each example from today's class into it, then load into drjava, compile, run. EVERY piece of code needs to be INSIDE a class! There are no global variables (that are declared outside functions), and, for that matter, no free-standing functions either. We'll use small examples to get a handle on how to code in Java. Data types There are 8 primitive datatypes: byte: 8 bits short: 16 bits int: 32 bits long: 64 bits float: 32 bits double: 64 bits char: 16 bits (to represent 'Unicode' chars) boolean: can only be 'true' or 'false' The numerical types have corresponding 'wrapper' classes. There is also a String type, to handle strings. Try this:
class IntegerEx {
public static void main(String args[]) {
Integer x = new Integer(4);
System.out.println(Integer.rotateLeft(x,2)); // static method
}
}
The truth is, we NEVER use wrapper classes directly! They exist so that other things are possible, eg. to be able to say things like 'ArrayList aL = ...'. Data types [cont'd] Here are the built-in types again, in tabular form (from http://www.isr.umd.edu/~austin/ence688r.d/java-basics.html): Data Type Contains Default Size Range boolean true or false false 1 bit N.A. char Unicode character \u0000 16 bits \u0000 to \uFFFF byte Signed integer 0 8 bits -128 to 127 short Signed integer 0 16 bits -32768 to 32757 int Signed integer 0 32 bits -2147483648 to 2147483647 long Signed integer 0 64 bits -9223372036854775808 to 9223372036854775807 float IEEE 754 floating point 0.0 32 bits -1.4e-45 to 3.402e+38 double IEEE 754 floating point 0.0 64 bits -4.9e-324 to 1.79e+308 Another look: http://softpixel.com/~cwright/programming/datatypes.java.php Data types [cont'd] Here is a small program, useful for playing with datatypes:
class DataTypes {
public static void main(String[] args) {
//int x=5, y=3.1415; // error: can't assign float to int!
int x = 5;
System.out.println(x);
char uc = 241;
System.out.println(uc);
}
}// DataTypes
Exercise: print the Unicode 233 character. Also, print ALL Unicode chars, ie. from 0 to 65535 [hint: (char)i will cast int i, to a char]:
import java.io.PrintWriter;
public class UC {
public static void main(String[] args) {
PrintWriter pW = new PrintWriter(System.out,true);
for(int i=0;i<65536;i++) {
char uc = (char)i;
pW.println(uc);
}
}// main()
}// UC
Note again that ALL CODE needs to be **inside** class definitions! There can't be free-floating vars or functions... Arrays Arrays of primitive datatypes are created using [] and new, eg.
class Arrays {
public static void main(String args[]){
int[] anIntArray = new int[5]; // [0], [1], [2], [3], [4]
anIntArray[0] = 111;
System.out.println(anIntArray[0]); // 111
System.out.println(anIntArray[4]); // 0 [uninitialized]
System.out.println(anIntArray[40]); // will result in an error!
}
}// Arrays
More: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html REFERENCES to arrays of objects are created likewise, eg. Image[] clubs = new Image[13]; After such an assignment, we'd still need to POPULATE each clubs[i] with an actual object (via new Image(), for ex). In other words, the array object, eg. clubs, initially points to null - it needs to be pointed to actual objects, subsequently. Arrays, including multi-dimensional ones 2D, 3D.. arrays are SIMPLE to create. 2D array creation:
class Array2D {
public static void main(String args[]){
int chessBoard[][] = new int[8][8]; // a SINGLE step!
// this is a 5x4 array, ie 5 rows, 4 cols
int anAr[][] = new int[5][4];
// or can do a 3-step creation, like in C++
int anotherAr[][]; // just the "pointer" decl
anotherAr = new int[5][]; // row of 'pointers'
for (int i=0; i < 5 ; i++) {
anotherAr[i] = new int[4]; // 'pointer' to each row
}
}
}// Array2D
Operators All the standard operators (assignment, numerical, comparison, Boolean) are available: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html 'instanceof' is an operator (not a function) that can be used to determine the actual (subclass) type of an object:
// place *all* the code below in A.java, compile, run
// [alternatively, you can use three files: A.java, C.java, D.java]
class A {
public static void main(String[] args){
A c = new C();
A d = new D();
System.out.println(c instanceof A && d instanceof A);
System.out.println(c instanceof C && d instanceof D);
System.out.println(c instanceof D);
System.out.println(d instanceof C);
}
}
// subclassing!
class C extends A { }
class D extends A { }
Expressions, statements These work, just like in C++ : https://docs.oracle.com/javase/tutorial/java/nutsandbolts/expressions.html Flow control: branching The usual if(){}, if(){}else{} and if(){}else{}if(){}..else{} constructs are available - here is a demo program. Also, try out the examples here. The 'switch' multi-way branch statement is also available - here is a small example. Flow control: looping Just like in C++, there are the while(){}, do{}while() and for() statements, for looping (repeating) code. 'while' loop:
class WhileDemo {
public static void main(String[] args){
int count = 1;
while (count < 11) {
// + below does string concetanation
System.out.println("Count is: " + count);
count++;
}
}
}
This sets up an infinite loop. Flow control: looping [cont'd] A do{}while() loop is an 'upside down' while(){} loop, it runs at least once (because do{} runs first, then while()).
class DoWhileDemo {
public static void main(String[] args){
int count = 1;
do {
System.out.println("Count is: " + count);
count++;
} while (count < 11);
}
}// DoWhileDemo
Flow control: looping [cont'd] Here is the classic 'for' loop (with initialization, termination, alteration):
class ClassicFor {
public static void main(String[] args){
for(int i=1; i<11; i++){
System.out.println("Count is: " + i);
}
}
}// ClassicFor
And this is the 'enumerated' for:
class EnumFor {
public static void main(String[] args){
int[] numbers = {1,3,5,7,9,2,4,6,8,10};
// similar to Python's "for i in [0,2,4,6,8]:"
for (int item : numbers) {
System.out.println("Num: " + item);
}
}
}// EnumFor
Flow control: break, continue In a loop, 'break' lets us EXIT the loop early, and 'continue' lets us SKIP the rest of an iteration. Here is how they work:
import java.util.Random;
class BreakContin {
public static void main(String[] args){
Random RNG = new Random();
boolean done=false;
while(!done) {
int r = RNG.nextInt(100);
if(r>90) continue; // SKIP the rest of the loop
System.out.println(r); // we'll never see a value > 90
// break if "too small"
if(r<5) break; // LEAVE the loop
if(r==50) done=true; // stop looping
}// next
}
}// BreakContin
Static fns We have been using 'psvm' to walk through Java's basic syntax and code structuring. main() is a "class method" (because it is 'static'), meaning it is attached to a CLASS rather than an OBJECT. Such a static function can call other static functions (and so on). In general, a static function f, in a class X, can be called from a: static function in the same X class static function in some other class non-static function (ie. method) in the same X class non-static function (ie. method) in some other class So we **could** (but shouldn't!) write large, functions-based programs this way, where all the functions are housed in just a single wrapper class :) Or, we could create a lot of classes, populate them with only static methods, and have them all call each from a psvm - this would be like programming using functions in 'C' - NO OBJECTS! But we don't do this either. All this said, static functions are useful for providing functionality that doesn't require object creation before its usage, eg. Integer.rotateLeft(). Static function example:
public class StaticFns {
// remove 'static' below, see what compilation error you get
public static int squared(int x) {
// just for exercise, we do this three different ways :)
int sq1 = x*x;
int sq2 = (int)Math.pow(x,2);
int sq3 = power(x,2); // our own eqvt of Math.pow()
return (sq1+sq2+sq3)/3; // because sq1,sq2,sq3 should all be identical
}// squared()
// our own version of Math.pow()
public static int power(int a, int b) { // a raised to b
int result=1;
for(int i=1;i<=b;i++) {
result *= a;
}
return result;
}// power
public static void main(String args[]){
int x = 25;
int y = squared(x); // static main() calls static squared()
// note that we could have said, above: StaticFns.squared(x);
System.out.println(y);
}// main
}// StaticFns
Here is the source for the example above. Note that inside a static function, we can create objects (ie. call constructors), use them (call their methods), and can even return one of them; in fact, that's commonly what we do in psvm, in real-world programs :) In psvm we can make an object of our own enclosing class (and call one of its methods) - this is how we'd bootstrap a Java program. Note too that we can do the exact same thing in a non-static function (ie method), too (create objects, use, and possibly return one). And - static functions are loosely analogous to 'free floating functions' in C++, Python etc. Also, all math library calls, eg. Math.pow(), are static functions [because we shouldn't need to create a math object, just to calculate sin(45), for ex). Setting on-screen pixel colors This is a 'fun' distraction (actually, it is a seriously cool thing - it provides you a 'canvas' (an onscreen buffer) on which you can set an RGB color at any pixel location!). You can use this to redo everything you did in C++ via .pgm or .ppm! Take a look at this program. Over an orange background, it draws white circles at random locations, and blue lines between random pairs of points. Exercise: how would you make the circles be (randomly) distributed/located near the center, and the lines also start near the center? Eg. to create random points centered at (cenX,cenY), within a rectangle of size (w,h), you'd do:
int ptX = cenX + random.nextInt(2*w) - w;
int ptY = cenY + random.nextInt(2*h) - h;
// now we can use (ptX,ptY) to draw our circle etc.
// ...
Here is the solution.