object.method(arguments)
class classname { methods variables }
public class Name { public String getFirst() {return first;} // Behavior public String getLast() {return last;} public void setFirst(String f) {first = f;} public void setLast(String l) {last = l;} private String first, last; // State }
public class Counter { public up() {val++;} // Behavior public int getVal() {return val;} private int val = 0; // State }
Name name1, name2; Counter c1;
SomeClass sc = new SomeClass();
new
operator
new Name() new Counter()
new
is done, it returns a reference to the newly created
object.
Name name = new Name(); Counter c = new Counter();
Name name1 = new Name(), name2 = new Name(); Counter c1 = new Counter(), c2 = new Counter();
name1
and name2
are two instance with their own copies of the first
and last
instance variables of the class.
c1
and c2
are two instance with their own copies of the val
instance variable of the class.
name1.getFirst(); // name1 is the receiver here, getFirst will access name1's instance variables name2.getLast(); // name2 is the receiver here, getLast will access name2's instance variables System.out.println(c1.getVal()); // c1 is the receiver System.out.println(c2.getVal()); // c2 is the receiver
public static void main(String [] args) { Name name1 = new Name(); name1.setLast("Arnow"); name1.setFirst("David"); System.out.println(name1.getFirst()); System.out.println(name1.getLast()); Name name2 = new Name(); name2.setLast("Weiss"); name2.setFirst("Gerald"); System.out.println(name2.getFirst()); System.out.println(name2.getLast()); Name name3 = name1; System.out.println(name3.getFirst()); System.out.println(name3.getLast()); }
public static void main(String [] args) { Counter c = new Counter(); for (int i = 1; i <= 10; i++) c.up(); System.out.println(c); }
class NameApp { public static void main(String [] args) { Name name1 = new Name(); … } }
class CounterApp { public static void main(String [] args) { Counter c = new Counter(); … } }
class Name { … public static void main(String [] args) { Name name1 = new Name(); … } }
class Counter { … public static void main(String [] args) { Counter c = new Counter(); … } }
main
Methodmain
method which must be declared as
public static void main(String [] args) { body }
main
method. Execution begins at that method.
reference
types/values/variables and primitive
types/values/variables.
operators
: +
, *
,
!
, &&
, etc..
Name name1 = new Name("Weiss", "Gerald"); Name name2 = name1;
name1
and name2
both contain references to it
new
is the only way of creating objects
Name name1 = new Name("Weiss", "Gerald"); Name name2 = new Name("Weiss", "Gerald");
Name
example, equality means having the same last and first names
equals
is usually defined (by the class designer) to test for (semantic) equality):
name1.equals(name2)
Name name1 = new Name("Weiss", "Gerald"); Name name2 = new Name("Arnow", "David");
Constructors
- Initializing Objectsnew
creates the object it invokes a method, known as a constructor
to initialize the object
new
-- the programmer does not call it directly.
Counter() {val = 0;}
default constructors
Name(String l, String f) { last = l; first = f; )
Counter
class, one might want to be able to create a counter with an initial value, or simply
create a counter whose value defaults to 0.
class Counter { … private int val; // value of the counter }
Counter c1 = new Counter();while the former case would be:
Counter c2 = new Counter(10); // create a Counter instance with an initial value of 10
Counter(int v) {val = v;} Counter() {val = 0;}
this
Counter(int v) {val = v;} Counter() {this(0);}
this
to specify that we are calling
another constructor from the current constructor.
this(0)
, it is clear to the compiler that we are
invoking a different constructor (the one that accepts an int parm).
this
later on.
toString
MethodtoString
defined by their designers.
public String toString()
==
and the equals
Methodnull
in the absence of such a reference)
==
operator compares the primitive values, which is the correct semantics; i.e.,
i == 4, d == 12.4
==
operator also compares the values, however, in this case, it's a reference
so we are effectively comparing if the two value (references) refer to the same object.
equals
instance method for the class:
Counter
class this might mean whether the val
fields are equal
public boolean equals(Counter otherCounter) {return val == otherCounter.val;}
Name
class this might mean whether the first and last name fields are equal:
public boolean equals(Name otherName) {return this.first.equals(otherName.first) && this.last.equals(otherName.last);}
public boolean equals(Name otherName) {return first.equals(otherName.first) && last.equals(otherName.last);}
equals
is more than a 'good' suggestion; later we will understand why it
should (must?) be named main
Method
A main
method is often added to a class whose execution will either 'show-off'
the behavior of the class, or test the class (basically the same thing).
public class Counter { public Counter() {val = 0;} public void up() {val++;} public void down() {val--;} public int get() {return val;} public String toString() {return val+"";} // The String concat, '+', converts integers to String automatically private int val; public static void main(String [] args) { Counter c = new Counter(); System.out.println("After initialization: " + c.get()); System.out.println("After initialization, using toString()" + c.toString()); // The String concat, '+', calls an object's toString automatically System.out.println("After initialization, using toString() implicitly" + c); System.out.println("going up!"); for (int i = 0; i < 10; i++) { c.up(); System.out.println("The counter after " + i + " up(s) is now: " + c); } System.out.println("down we go!"); for (int i = 0; i < 10; i++) { c.down(); System.out.println("The counter after " + i + " down(s) is now: " + c); } } }
More often than not, this illustrative main is placed in its own class:
class CounterApp { public static void main(String [] args) { Counter c = new Counter(); System.out.println("After initialization: " + c.get()); System.out.println("After initialization, using toString()" + c.toString()); // The String concat, '+', calls an object's toString automatically System.out.println("After initialization, using toString() implicitly" + c); System.out.println("going up!"); for (int i = 0; i < 10; i++) { c.up(); System.out.println("The counter after " + i + " up(s) is now: " + c); } System.out.println("down we go!"); for (int i = 0; i < 10; i++) { c.down(); System.out.println("The counter after " + i + " down(s) is now: " + c); } } }
Name
class, a Student
class would contain an instance
variable of type Name
. (Similarly if the was an Address
class)
class Name { … } … class Student { … private Name name; private Address address; }
String
class, a Name
class would contain an
instance variable of type String
for the last name (similarly for first name).
class Name { … private String last, first; }
Employee
class, a Department
class might contain an array
of Employee
objects.
Employee
class probably contains a Name
field
class Employee { … Name name; } … class Department { … private Employee [] employees; }
class Patient { … public String toString() { return name + " (" + dateOfBirth + ")"; } public boolean equals(Patient other) { return name.equals(other.name) && dateOfBirth.equals(other.dateOfBirth); } … private Name name; private Date dateOfBirth; }
toString
and equals
null
class Name { Name(String last, String first) {…} … private String last, first;
class Person { Person(int age, Name name) { this.age = age; this.name = name; } Person(int age, String last, String first) {this(age, new Name(last, first));} … private Name name; private int age; }
static
— Class Membersthis
or instance variable (or methods) allowed
static
keyword — the method/variable is static, i.e., it's
not dependent on any particular instance/object of the class.
final
)
Color
class' predefined color constants
static final Color BLACK = new Color(0, 0, 0);
Calendar
class' month names
static final String JANUARY = 1, FEBRUARY = 2. … DECEMBER = 12;
class Employee { Employee(String name) { this.name = name; this.id = nextId; nextId++; } ... ... String name; // instance variable int id; // instance variable - individual Employee's id static int nextId=1001; // class variable - next id to be assigned; }
Math
class' abs
method
Integer
class' parseInt
method
main
method (called from 'nowhere'-- no receiving object)
main
read
method for a class-- reads data, and uses it to call new
,
invoking constructor with the data.
class C { void f1() { int i; … System.out.println(i); … } void f2(int i) { … System.out.println(i); … } void f3() { … System.out.println(i); … } int i; }
{}
's.
{}
's (i.e., within the block) are said to be
local to the block.
Name name = new Name("Weiss", "Gerald"); name.getFirst();when the method
getFirst
is entered as a result of the call, the instance variable first
is the one belonging to the receiver, i.e., the object referred to by the variable name
(with the
value "Gerald"
).
class Name { Name(String last, String first) { … } … String last, first; }
this
Name
constructor:
class Name { Name(String last, String first) { … } String last, first; }
Name(String last, String first) {...}
?
Name(String last, String first) { this.last = last; this.first = first; }
this
specifies the receiver and
this this.first
is an explicit (i.e., qualified)
referral to the instance variable of the class (rather than the local parameter of the same name).
private
class C { C(int val) {this.val = val;} … C add f(C otherC) { return new(val + otherC.val C); // Legal and common } … public String toString() {return val;} … private int val; public static void main(String [] args) { … C c1 = new C(10); c1.val = 12; // Legal, but definitely not recommended. } }
class CApp { public static void main(String [] args) { … C c1 = new C(10), c2 = new C(12); //c1.val = 12; // Here (outside the class) it's simply illegal C c3 = c1.add(c2); System.out.println(c3); // prints 23 } }
Counter
classval
containing the value of the counter
up
, that increments the counter's value by 1
down
, that decrements the counter's value by 1
class Counter { void up() {...} void down() {...} int val; }
Window
classwidth
, that will contain the width (in pixels) of the window
height
, that will contain the height (in pixels) of the window
x
, that will contain the horizontal position (in pixels) of the window
y
, that will contain the vertical position (in pixels) of the window
fgcolor
, that will contain the text color of the window (where Color is itself a
class)
bgcolor
, that will contain the background color of the window (where Color is itself a
class)
text
, that will contain the text currently in the window
move
that changes the position of the window
resize
that changes the size of the window
setFgColor
that changes the text color of the window
getFgColor
that returns the text color of the window
setBgColor
that changes the background color of the window
getBgColor
that returns the background color of the window
insert
that will insert text into the window
class Window { void move(int newX, int newY) {...} void resize(int new width, int newHeight) {...} void setFgColor(Color newFgColor) {...} Color getFgColor() {...} void setBgColor(Color newBgColor) {...} Color getBgColor() {...} void insert(String newText, int where) {...} int width, height; int x, y; Color fgColor, bgColor; String text; }
int [] intArr; String [] stringArr; Name [] nameArr;
System.out.println(intArr[0]);
results in a NullPointerException
String
)
new
operator:
String [] stringArr = new String[20]; // Creates an array of 20 String references and assign the // reference to the array object tostringArr
Name [] nameArr = new Name[100]; // Creates an array of 100 Name references and assigns the // reference to the array object tonameArr
final int CAPACITY = 100; Name [] names = new Name[CAPACITY]; names[0] = new Name("Gerald", "Weiss"); names[1] = new Name("David", "Arnow"); names[2] = new Name("Yedidyah", "Langsam"); …
or more typically, the contents of the array would be read in from a file using a read
method, which reads the
data from the file, creates the object (which is initialized via the constructor being passed the data), and returns its reference:
final int CAPACITY = 100; Name [] names = new Name[CAPACITY]; int size = 0; Scanner scanner = new Scanner(new File("names.text")); Name name = Name.read(scanner); while (name != null) { if (size >= CAPACITY) { System.out.println("Too many names in file -- increase the size of your array"); System.exit(1); } names[size++] = name; name = Name.read(scanner); }
read
method is typically defined as a static
method (because no object has been created yet), that
reads the values to be passed to the constructor into local variables, then creates the object (passing those values to the constructor via the new
statement) and returns the reference to the new object as the return value of the method.
void print(Name [] names, int size) { for (int i = 0; i < size, i++) System.out.println(names[i] + (i < size-1 ? ", " : "")); } boolean contains(Name [] names, int size, Name name) { for (int i = 0; i < size, i++) if (names[i].equals(name)) return true; return false; }
class FootballTeam { … private Player [] offensiveSquad = new Player[11]; private Player [] defensiveSquad = new Player[11]; private Player [] specialSquad = new Player[3]; }
class Arr { … private int [] arr = new int[100]; private int size = 0; }
Array
ClassWe lose some things by moving from an array to a class:
Array
instance.
class Phonebook { static class PhonebookEntry { … } … }
a + b
, the result of the operation is
a new value
a += b
, the result of the operation is
stored in the left operand
class ImmutableColor { public ImmutableColor(int r, int g, int b) { this.r = r; this.g = g; this.b = b; } … public ImmutableColor lighter() { if (r < 255 && g < 255 && b < 255) return new ImmutableColor(r+1, g+1, b+1) else return null; } private final int r, g, b; }
final
in the declaration of the instance variables. This is because they will not be modified once initialized in the
constructor.
final
variables do not need to be initialized at point of declaration; they can be given their initial (and only) value within
the constructor.
Color
object (rather than modifying the receiver).
null
if the color cannot be made lighter
class MutableColor { public MutableColor(int r, int g, int b) { this.r = r; this.g = g; this.b = b; } … public MutableColor makeLighter() { if (r < 255 && g < 255 && b < 255) { r++; g++; b++ return this; } else return null; } private int r, g, b; }
makeLighter
) to better reflect the semantics of the method
MutableColor color = new MutableColor(100, 34, 67); System.out.print(color.makelighter().makeLighter().makeMoreTransparent();