///////////////////////////////////////////////////////////////////// // CS 308-202 // // Java-by-example #1 (declarations, statements, expressions // // and functions) // ///////////////////////////////////////////////////////////////////// // Execution of a Java program starts from "main" function. // Statements of any function are executed sequentially. public class cl { public static void main(String[] args) { System.out.print("Hello"); System.out.println(" world"); // executed sequentially } } // Variables allow accessing some memory locations by name. Thus // variables can store values. To print contents of variables into // the standard output (screen) System.out.print (or println) can be // used. The variables to be printed are concatenated to a string! public class cl { public static void main(String[] args) { double p=0.14 + 3; // p stores a double precision float // + expresses addition System.out.println("res =" + p); // + expresses string concatenation } // p is first converted to a string } // Buffered reader class can be used for input. Numbers are first // read as strings and further converted into numeric types. There // are different ways of converting integers and floats from Strings. public class cl { public static void main(String[] args) { InputStreamReader isr=new InputStreamReader(System.in); BufferedReader stdin=new BufferedReader(isr); String str; // stores a string int i; // stores an integer float f; // stores a single precision float str=stdin.readLine(); // read digits as characters i=Integer.parseInt(str); // convert characters into an int str=stdin.readLine(); // read digits as characters f=Float.valueOf(str).floatValue(); // convert characters into a float } } // Declared variables can be preinitialized with an expression. // The expression is computed and the result is assigned to a variable // (Not unlike an assignment statement where the same occurs). // // An expression is a chain of operands connected by operators i.e.: // + for addition, * for multiplication etc. Operands can be variables // e.g.: a,b etc., literal constants e.g.: 11, 3.14 etc., or other // expressions in parentheses e.g.: (a+11) etc. // // Variables which are prohibited from changing their value are known // as constants. Declarations of constants are preceded by "final" // keyword. public class cl { public static void main(String[] args) { float fi=3,fj=fi+34; // declarations with initialization. final float pi=3.14; // a constant fi=(fi+fj)/4*pi; // assignment statement. // pi=3.15; // Incorrect! pi cannot appear on } // the left of assignment, constants } // cannot be changed // Expressions are computed using the rules of precedence // and association. The operators with higher precedence are // applied first. (e.g. multiplications ahead of additions) // Operators with the same precedence (e.g. multiplication // and division) are associated and computed, in this case, // from left to right. To alter evaluation order, parentheses // should be introduced into an expression. public class cl { public static void main(String[] args) { int i,j; // * higher than + i=2+3*4; // means 2+(3*4) i=(2+3)*4; // changed order // *, / - same precedence i=2*2/3; // means (2*2)/3 hence =1 j=2/3*2; // means (2/3)*2 hence =0 } } // Variables can be of different data type. Some data types are // iherently part of the language itself. These are known as // primitive data types. Among these are several integer // data types: byte, short, int, long and several "real" data types: // float and double. All other data types are handled as classes i.e. // user-defined data types. String is a class! Operators have different // meaning when applied to different data types. // // Boolean primitive data type is used to express truth values: // {true, false} boolean operators of && (and), || (or), ! (not) // can be used as well as relational operators == (equal), != (not equal), // < (less than) etc. The latter take numerical arguments and return // boolean result. // // Note that literal constants without a decimal point have // type int. Literal constants with a point have type double. // We can have a literal constant of type long by appending // an L after an int literal constant (i.e. 100L verses 100). // We can also have a literal constant of type float by appending // an F after a double literal constant (i.e. 3.14F verses 3.14). // Literal constants included into single quotes have type char // (i.e. 'a') and literal constants included into double quotes // have type String (i.e. "abc"). public class cl { public static void main(String[] args) { int i; double d; boolean b; i=2/3; // integer div (remainder ignored) f=2.0/3; // floating point div b=(30)) // boolean expression of if statement { // block statement starts System.out.println("zero"); i=1; } // block statement ends // if((i==0)&(j>0)); // Incorrect! ";" means empty statement! // { // thus this block is considered // ... // as a statement following if // } // not belonging to if } } // To repeat the same statement multiple times "while" statement // should be used. It repeats a statement as long as its boolean // condition is true. public class cl { public static void main(String[] args) { int i=0; while(i<10) // boolean expression of while { System.out.println("Line:" + i); i=i+1; // so that while will eventually stop. } // while(i<10) // Incorrect! there is no way for // { // condition to change, hence // System.out.println("Line:" + i); // no way for the while to terminate // } // - an eternal loop. } } // A while loop allows to execute a statement zero or multiple times. // There are situations where some statement has to be executed at // least once, possibly multiple times. A "do-while" loop can be used // in such a situation. public class cl { public static void main(String[] args) { int i; BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in)); do { // i has to be read at least once System.out.print("Enter a positive number:"); i=Integer.parseInt(stdin.readLine()); } while(i<0); // until positive number entered // if negative entered, reread. } } // Many loops are set in a similar way: Some counter is initialized before // the loop; the loop's condition is checked and the counter is updated // every iteration. A "for" loop has a syntax simplifying that construct. public class cl { public static void main(String[] args) { int i; for(i=0;i<10;i=i+1) // starting with i=0, while i<10 System.out.println("i="+i); // do the statement and increment i // i=0; // any for loop has a semantically // while(i<10) // equivalent while loop. // { // System.out.println("i="+i); // i=i+1; // } } } // Within all loops: "while", "do-while" and "for", two special statements // can be used: "break" to exit from the loop and "continue" to start // new iteration of the loop import java.math.*; // indicates that usage of Math.sqrt // will follow public class cl { public static void main(String[] args) { for(double i=-10;;i=i+1) // declaration is allowed in for! { // no condition - an eternal loop System.out.println("i="+i) // will use break statement to exit if(i<0) continue; // start next iteration System.out.println("Line:" + Math.sqrt()); if(i>10) break; // break from the loop } } } // We often have to do a chain of nested if-else statement. In some // situations a switch statement is a good alternative. Switch statement // evaluates an expression and matches the obtained value against // a list of cases. It starts execute statements following that case // until either the end of switch or enountering a break statement. public class cl { public static void main(String[] args) { int i=1; switch(i) // switch's expression should evaluate { // to either int or char case -1: // each case has a literal constant // case i+1: // Incorrect! cannot handle expression case -2: System.out.print("-1 or -2"); break; // if there is no break case 0: System.out.print("0"); // following statement, even following // other cases are executed case 'b': System.out.print("b"); break; default: System.out.print("?"); // special case, when nothing matches } // go to default case } } // Each declared variable has a visibility scope within which it // is alive and accessible. The scope in Java coincides with the // block statement within which the variable is declared. Thus a variable // is alive from the declaration point until the end of its block statement. public class cl { public static void main(String[] args) { int i; // i is constructed if(true) { int j; // j is constructed j=i; // Correct, i is alive } // j is destroyed here // i=j; // Incorrect! j's dead } // i is destroyed here } // A program can be composed as a set of functions. Each // function takes some arguments and produces a result. // Since the function has a block statement we can define // variables inside a functions. These are known as local // variables. Function's arguments are used just as if they // were local variables. Parameters in the declaration of // a function are called "formal", parameters during the // invocation are called "actual". When function is called, // the formal parameters have been assigned values of actual // parameters which were specified in the function's invocation. // If an expression was specified as an actual parameter. The // expression would be first computed and then its result passed // to an appropriate formal parameter. There is a special // statement "return" used to specify what should be the result // of the function. public class cl { public static int sqr(int arg) // Declaration of a function sqr // int - return type, int arg { // one formal parameter arg, type int int tmp; tmp=arg*arg; return(tmp); // special statement indicating } // what to return as function's result public static void main(String[] args) { int c; c=sqr(2); // Invocation of a function. } // number, position and type of } // actual parameters must match // that of formal parameters // Primitive data types (int, float etc) are passed into // functions by value. That is, formal parameters of the // function just as its local variables have separate memory // location distinct from that of actual arguments. public class cl { public static void inc1(int x) // Declaration of a function inc1 { // void - doesn't return anything x=x+1; // x is local! modifying it doesn't } // have any effect on the // calling function public static int inc2(int x) { x=x+1; // x is still local return(x); // but it is also returned } public static void main(String[] args) { int x=1; inc1(x); // x is still 1 after the call x=inc2(x); // x is modified as a result of } // an assignment statement } ///////////////////////////////////////////////////////////////////// // CS 308-202 // // Java-by-example #2 (classes and objects) // ///////////////////////////////////////////////////////////////////// // Java allows us to define user data types to augment existing // primitive data types. A declaration of such a data type is called // a class, an instance of a class is called an object. Class // declarations consist of member declarations describing storage // requirement for objects of the class, constructor declarations // describing how the objects are initialized and method declarations // specifying what are the operators applicable to the objects of the // class. Methods are essentially functions. Note that they can access // the class data members beside their parameters and local variables. // Note that constructors must have the same name as the class name. // A constructor doesn't have any return value! public class Point { int x; // declarations for the members int y; // each Point object will have x and y public Point(int xx,int yy) // To construct a point we must { // specify initial values for x and y x=xx; y=yy; } public void translate(int ox,int oy) // An operation on points. { // Translation: moving a point by ox,oy x=x+ox; y=y+oy; } } // An object of a class can be used in similar ways // primitive data types are used. By giving class name // as a data type in a variable declaration we can declare // a reference to an object. These point to the position // in memory where the object will be located. To create // an instance of an object operator "new" should be used // which will invoke necessary constructor. class UsePoint // Uses class Point declared above { public static void main(String[] args) { Point a; // Declare a reference to an object // a.translate(1,1); // Incorrect! Cannot use the object yet! // It has not been constructed. a=new Point(5,5); // Construct an object by invoking the // constructor a.translate(10,10); // Apply a method translate to the } // object } // A data member or a method can be declared to be static. // This means that it will be shared by ALL objects of the class. // To invoke a static function we specify Class name, dot, static // method name e.g.: Math.pow(2,2); Note also that main is static! // A static function cannot access data members which are not // static since this is ambiguous, these exist only in particular // objects and static methods are not invoked for any objects in // particular. public class Point { static int no_points=0; // shared by all Points, number of Points // static members are initialized or // constructed here, in the declaration! int x; int y; // non static members. public Point(int xx,int yy) { x=xx; y=yy; no_points=no_points+1; // new point constructed hence update } public void translate(int ox,int oy) { x=x+ox; y=y+oy; } public static int noPoints() // Shared by all points! { return(no_points); // report how many points there is } } public class UsePoint // uses class Point declared above { public static void main(String[] args) { Point a=new Point(0,0); Point b=new Point(100,100); a.translate(10,10); // calls non static method hence // must specify object int np; np=Point.noPoints(); // Call static method, don't have } // to specify any particular object } // use class name instead // If one non static method needs to call another non static // method for the same object no object selectors ( "a." in // a.translate(1,1); ) needed to be specified. The same object // is assumed. // Static methods can also be called in the same way, without // specifying the Class selector ( "Math." in Math.pow(2,2); ). public class Point { int x,y; // coordinates of the point public Point(int xx,int yy) { x=xx; y=yy; } public void translateX(int ox) { x=x+ox; } public void translateY(int oy) { y=y+oy; } public void translate(int ox,int oy) // to translate by ox,oy { // can translate by ox and then by oy translateX(ox); // calls method on the same translateY(oy); // object translate was invoked on! } } // Thus a program can be built as a set of classes instantiating // and using other classes. Note that there should exist a single // public static void main function. The execution of the program // will start there. main can build the necessary objects and // call their methods. // // Note that keyword "this" can be used inside non static methods // to refer to the object with which this method was invoked. public class Point { int x,y; // coordinates of the point Rectangle f; // Rectangle this point belongs to public Point(int xx,int yy) { x=xx; y=yy; } public void assignRect(Rectangle ff) // associate the point with Rectangle { f=ff; } public void translateSelf(int ox,int oy) { x=x+ox; y=y+oy; // translate this point only } public void translate(int ox,int oy) { f.translate(ox,oy); // translate entire Rectangle } } public class Rectangle { Point u,d; // Described in terms of two Points public Rectangle(Point uu,Point dd) // constructing Rectangle { u=uu; d=dd; u.assignRect(this); // keyword "this" refers to current d.assignRect(this); // Rectangle! -- this Rectangle } public void translate(int ox,int oy) // translate the Rectangle { u.translateSelf(ox,oy); // by translating the two points d.translateSelf(ox,oy); // describing it } } public class UseRectangle { public static void main(String[] args) { Point a=new Point(0,0); Point b=new Point(100,100); // build the Points Rectangle r=new Rectangle(a,b); // build the Rectangle a.translate(10,10); // although we are just moving one } // corner, Point will make sure } // that all proper Points are moved! // References only point to objects thus when we assign a value of // one reference to another, both will physically point to the same // object! public class UsePoint // Uses class Point declared above { public static void main(String[] args) { Point a=new Point(10,10); // "a" refers to created Point(10,10) Point b=a; // a and b refer to the same point b.translate(1,1); // object changed through b but } // a points to the very same, now } // changed object. // A local variable of a primitive data type declared in a method exists // till the end of the block statement where it is declared. // // A static class variable of a primitive data type exists as long as // the entire program exists. // // A variable of a primitive data type declared as a non static member of // a class is instantiated when an object of this class is created // and destroyed when that object is destroyed. Each object has its own // member variables. // // An object exists as long as there are any references to that object // which exist. When the last reference is destroyed, the object is // destroyed. // // References behave as variables of primitive data types as far // as scoping is concerned. public class UsePoint // Uses class Point declared above { public static void main(String[] args) { Point a; // declare a reference to a Point if(true) { Point b=new Point(1,1); // declare another reference and build // an object a=b; // reference assignment, both a and b // now point to the same object } // reference b is gone a.translate(10,10); // but the object Point(1,1) exists // while there are any references to it! } // last reference "a" is destroyed and } // the object is destroyed too! // Objects are passed to methods by reference. Thus causing // a modification inside a method call DOES have effect outside. // This is unlike primitive data types which are passed by value! // Modifying variables of primitive data types when passed by value // won't have any effect outside! public class UsePoint { public static void change(Point p) // passing by reference! { p.translate(10,10); // calls a method changing the object } // p refers to public static void main(String[] args) { Point a=new Point(10,10); change(a); // after the call the object is changed! } } // Several classes can have methods with the same name. Even // within the same class we can have multiple methods with // the same name including multiple constructors. When the // method is called, Java determines what to invoke based on // the "methods" signature -- method's name plus the types of // method's object selector and types of its arguments // Hence, it is indeed possible to have two methods with // the same name, but not with the same signature (otherwise there // will be ambiguity what to call). Note that the return type // of a method is not part of the signature! public class Point { int x,y; // coordinates of the point public Point(int xx,int yy) // Construct a point from coordinates { x=xx; y=yy; } // signature: [Point int int] public Point(Point p) // Construct a point from another Point { x=p.x; y=p.y; } // signature: [Point Point] public void translate(int ox,int oy) // Translate to (ox,oy) { x=x+ox; y=y+oy; } // [Point translate int int] public void translate(int ox) // Translate x by ox { x=x+ox; } // [Point translate int] // public void translate(int oy) // Incorrect! this method will have // { y=y+oy; } // the same signature! } // [Point translate int] public class Rectangle { Point u,d; // Described in terms of two Points public Rectangle(Point uu,Point dd) // constructing Rectangle { u=uu; d=dd; } public void translate(int ox,int oy) // translate the Rectangle { u.translate(ox,oy); // [Rectangle translate int int] d.translate(ox,oy); } } public class UseRectangle { public static void main(String[] args) { Point a=new Point(0,0); // build a Point Point b=new Point(a); // build a Point from a Point Rectangle r=new Rectangle(a,b); // build a Rectangle // Calling methods with appropriate // signature: a.translate(10,10); // [Point translate int int] r.translate(100,100); // [Rectangle translate int int] a.translate(10); // [Point translate int] // r.translate(10); // Incorrect! no method with signature } // [Rectangle translate int] } // Data members of the class and the methods of the class can // be accessed in expressions where objects of this class are used. // It is a good programming practice to always isolate internal // workings of the class from its public interface. Access modifiers // allow us to hide those data members and those methods which are // internal and only used in the methods of the given class. // Data members and methods declared public are visible outside // and thus form public interface of the class. Data members and // methods declared private are visible only inside the class and // cannot be accessed outside. If no modifier is specified private // is assumed by default! Note that it is generally preferable // to make all data members private! public class Point { private int x,y; // coordinates of the point public static int no_points=0; public Point(int xx,int yy) { x=xx; y=yy; no_points=no_points+1; } private void translateX(int ox) { x=x+ox; } private void translateY(int oy) { y=y+oy; } public void translate(int ox,int oy) // to translate by ox,oy { // can translate by ox and then by oy translateX(ox); // calls method on the same translateY(oy); // object translate was invoked on! } } public class UsePoint { public static void main(String[] args) { Point a=new Point(10,10); // int a=a.x; // Incorrect x is private a.translate(20,20); // OK, translate is public // a.translateX(30); // Incorrect translateX is private int pts=Point.no_points; // OK, no_points is public } } ///////////////////////////////////////////////////////////////////// // CS 308-202 // // Java-by-example #3 (applets, file i/o, arrays) // ///////////////////////////////////////////////////////////////////// // Java applets are modified instances (objects) of Applet // class. They are instantiated and executed by web browsers // or special applet viewers. To build an applet we have to // inherit all functionality from Applet class and then // write methods describing behaviour of this particular // applet. As opposed to applications which have main method // where the execution will start, applets follow event driven // paradigm. Applets should implement a number of different // methods which are automatically called by the applet viewers // when a particular event needs to be handled. For instance // applets should implement init() method. It is called when // the applet starts and needs to be initialized. Similarly, // applets should implement paint() method. This is called when // an applet's window needs to be redrawn. import java.applet.*; // import Applet class import java.awt.*; // import other classes (Graphics) public class App extends Applet // our applet inherits all methods { // and data members of an Applet private String s; public void init() // When applet starts executing { // this method will be automatically s="text"; // called to perform initialization } public void paint(Graphics page) // When the applet's window needs to { // be redrawn this method will be page.drawString(s,10,10); // automatically called } } // It should be noted that applets are to be embedded into web // pages. Thus to execute an applet even by an appletviewer there // should be an HTML document calling the applet. App // As opposed to applications which by default use text only // input/output, applets have a graphics window where graphics // output can be presented and input from various devices (e.g. mouse) // taken. The paint method takes as an argument an object of type Graphics. // this object is capable of displaying numerous graphics primitives. // It is possible to change painting colour by calling // setColor method. The latter can take as an argument one of // many constants defined in the Color class, e.g.: Color.red, // Color.black etc. import java.applet.*; // import Applet class import java.awt.*; // import other classes (Graphics) public class App extends Applet // our applet inherits all methods { // and data members of an Applet public void paint(Graphics page) { page.drawString("text",10,20); // draw string at coordinates (10,20) page.drawLine(0,0,300,300); // draw a line from (0,0) to (300,300) page.setColor(Color.red); // Change the painting colour page.drawOval(30,30,10,40); // draw an oval at (30,30) with axes // 10 and 40 page.setColor(Color.black); Polygon poly = new Polygon(); // Create a Polygon object poly.addPoint(10,20); // add vertices poly.addPoint(100,30); poly.addPoint(50,40); page.drawPolygon(poly); // Draw a polygon } } // To be notified when a particular input event has occurred // an applet should implement particular methods. For instance, // mouseDown method will be automatically called when a mouse button // will be pressed. A keyDown method will be called when a key was // pressed etc. When responding to an event an applet can, for // instance, modify the state of some variable and call repaint() // to indicate that applet's window needs updating. Eventually, // paint() method will be called at which point an applet may use // the modified variable to produced updated output. import java.applet.*; // import Applet class import java.awt.*; // import other classes (Graphics) public class App extends Applet // our applet inherits all methods { // and data members of an Applet private String s; public void paint(Graphics page) // When the applet's window needs to { // be redrawn this method will be page.drawString(s,10,10); // automatically called } public boolean mouseDown(Event evt, int x, int y) { s="Mouse pressed at (" +x+","+y+")"; // modify state of a variable repaint(); // make sure that paint will be called return(true); // indicate that the event was processed } // and default handlers need not to } // be called. // Note that we can achieve an animation effect by calling repaint() // from paint(). When paint is called first, it can modify a state of // some class variable and call repaint() which will insure that paint // will be called shortly after etc. import java.applet.*; // import Applet class import java.awt.*; // import other classes (Graphics) public class App extends Applet // our applet inherits all methods { // and data members of an Applet private int y; public void init() { y=0; } public void paint(Graphics page) { page.drawString("text",10,y); // paints the window y=y+10; // updates state for next painting repaint(); // makes sure paint is called again } } // An applet can also use a variety of AWT (Abstract Windowing Toolkit) // objects to create and manage user interface components in its window. // For instance we can add buttons pressing these by the user will generate // an event for which action() method will be called. By implementing // action() we can handle these events in particular ways. import java.applet.*; // import Applet class import java.awt.*; // import other classes (Graphics) public class App extends Applet // our applet inherits all methods { // and data members of an Applet private int y; public void init() { y=0; add(new Button("restart")); // adding a button to the window } public void paint(Graphics page) { page.drawString("text",10,y); // paints the window y=y+10; // updates state for next painting repaint(); // makes sure paint is called again } public boolean action(Event evt, Object arg) { if("restart".equals(arg)) // check if our button was pressed { y=0; // reinitialize the state repaint(); // make sure painting will occur return(true); // indicate that the event was handled } else return(false); // indicate event not handled } } // It is often necessary to store some information permanently. // Since random access memory only works when a computer is operational, // all information in it is lost when the computer is switched off. // Disk storage however is persistent and allows information to be // stored permanently. A unit of information on disk is called a // "file". Each file has a name and stores some contents. // Similar to the way we output information to standard output // device, we can also write it into a file. import java.io.*; // import File and other classes public class a { public static void main(String[] args) throws Exception { // note throws Exception! File f=new File("info"); // Open a disk file named "info" FileOutputStream fos=new FileOutputStream(f); PrintStream ps=new PrintStream(fos); // ps has print and println methods // just like System.out! ps.println("Hello!"); // printing a string into a file "info" } } // Reading from a file is very similar to reading from standard input. // Just as was the case with he latter, we also have to create an // instance of BufferedReader which will provide us with the // method readLine allowing us to read from the file. import java.io.*; // import File and other classes. public class cl { public static void main(String[] args) throws Exception { // note throws Exception! File f=new File("info"); // open a disk file named "info" FileInputStream fis=new FileInputStream(f); InputStreamReader isr=new InputStreamReader(fis); BufferedReader br=new BufferedReader(isr); String str=br.readLine(); // read a string from a file "info" System.out.println(str); // show what was read on the screen } } // In many situations we have to manipulate with arrays of data, // that is, with many instances of the same data type. It is // prohibitive to allocate a separate variable for every such // element since there may be too many variables, also we may not // know in advance how many there will be and also we may want // to process all elements in a similar way and thus need some // uniform access to them. // // Arrays allow to do just that. An array keeps multiple elements // of the same data type and allows to access individual elements // by an integer index. // // Arrays in Java are handled as objects. Thus we first describe // a reference to an array and then create the array itself. Square // brackets are used to describe array data type and also to // describe accessing array's element. When creating an array, // the dimension is an integer expression. Similarly when // accessing an element, the index is also some expression evaluating // to an integer. Note that first element of an array has index of 0 // and the last one length-1 where length is the dimension of the array. public UseArray { public static void main(String[] args) { int[] ar; // Declares a reference to an array // of integers. // ar[0]=6; // Incorrect, array itself not built yet ar=new int[5]; // Create an array of 5 integers. ar[1]=4; // Ok, space was allocated. i=1; // Array index can be specified as ar[(i+1)*2]=12; // an expression, not just a constant int lng=ar.length; // Report how many elements is there // by accessing length data member // ar[ar.length]=0; // Incorrect! there is only elements } // from 0 to ar.length-1. Exception } // will occur in this case. // An array may be constructed with initial values assigned. A list // of initial values following the declaration of an array reference cause // implicit creation of an array (calling new etc.) with these initial // values assigned. public class UseArray { public static void main(String[] args) { float[] ar={2.3, 1.2, 3}; // Both declares a reference and creates // an array with initial values set. ar[0]=6.1; // Ok, array was indeed constructed int lng=ar.length; // Whatever creation method was, length } // data member is available } // Since arrays are handled as objects, the scoping rules and parameter // passing rules which apply to objects apply to arrays. For instance, // arrays are passed to methods by reference. An array exists until // there are some references pointing to it. An assignment of one // array to another is a reference assignment (same as for objects). public class UseArray { public static void change(int[] ar) // passing by reference! { ar[0]=1; // change the array which is passed } public static void main(String[] args) { int[] aa=new int[10]; aa[0]=5; // after the call the array is changed! change(aa); // a[0] is equal to 1! } } // Similarly to arrays of primitive data types, we can have arrays // of objects. When we declare an object we actually declare a reference // to an object. Similarly when we declare an array of objects we // actually have an array of references to objects. In both cases // the objects themselves have to be created and assigned to their // references. public class Point { int x,y; public Point(int xx,int yy) { x=xx; y=yy; } public void translate(int ox,int oy) { x+=ox; y+=oy; } } public class UsePoint { public static vois main(String[] args) { Point[] pa; // Reference to an array of references // to Points pa=new Point[10]; // 10 references to Points created for(int i=0;i<10;i++) // create 10 Points, one at a time. pa[i]=new Point(0,0); // make array elements refer to these // Points. a[3].translate(10,10); // array elements refer to Points } // we can call their methods } // We can create arrays of variables of some data type, such as // float (primitive data type) or Point (class). Since an array of // something is also a data type, we can create an array of arrays of // something, i.e. we can have multidimensional arrays. public class UseArray { public static void main(String[] args) { int[][] a=new int[10][10]; // Creates a square array int[][][] a3d=new int[5][5][5]; // Create a 3 dimensional array a[1][2]=5; // Selecting an element from 2d array float[][] fa={ // Similarly to linear array, can use {1.2, 3.4}, // initialization list. Note that a {2.1, 0.0} // square array is a linear array }; // where each element is a linear array! Point[][] pt=new Point[20][20]; // A square array of Point references for(int i=0;i<20;i++) // Each Point has to be created for(int j=0;j<20;j++) // and array elements should refer pt[i][j]=new Point(0,0); // to proper Point objects first_dim=pt.length; // A square array is a linear array // where each element is a reference // to some linear array! thus asking // for length gives first dimension second_dim=pt[0].length; // pt[0] is a linear array! asking // its length gives us second dimension } // Note that in this example } // pt[0].length==pt[1].length etc. // Arrays are basically static. Once created with dimension 5, we // cannot add to it an extra element. However, we can always create // our own class which will have a functionality of an array and will // allow adding as many elements as necessary. One approach to this // class's implementation is to keep a regular static array as a data // member. If its size permits, we will just store a new element in it. // If its size doesn't permit adding, we will reallocate the array with // bigger dimension and copy all elements from the old storage and // then will be able to store the new element // // Note that standard Vector class uses this approach. public class DynamicIntArray // A dynamic array of integers { private int[] storage; // data stored in a static array public DynamicIntArray(int size) // constructs with some initial size { // for storage storage=new int[size]; } public void put(int index,int value) // adding new element at some index { if(index>=storage.length) // if storage doesn't permit { // create bigger array int tmp=new int[index+1]; for(int i=0;i