Title: Java Programming
1Java Programming
- CHAPTER 9, 10, 11
- Operators and Expressions
- Control Flow
- Generic Types
2Contents
- Operators and Expressions
- Arithmetic operations
- General operators
- Expressions
- Type conversions
- Operator precedence
- Member access
- Control Flow
- Generic Types
3Operators and Expressions
- The fundamental computational building blocks of
the programming language are operators and
expressions - Each operator is described in terms of its basic
operation, upon operands of the base expected
type such as a numeric primitive type or a
reference type
4Arithmetic Operations
- The binary arithmetic operators are
- addition (e.g. a b)
- - subtraction (e.g. a - b)
- multiplication (e.g. a b)
- / division (e.g. a / b)
- remainder (e.g. a b)
- The unary operators
- - for negation (e.g. val -val)
- positive value (e.g. 2.0)
5Increment and Decrement Operators
- is the increment operator
- -- is the decrement operator
- The or -- expression is more efficient
- prefix i ? the operation is applied before the
value of the expression is returned - postfix i-- ? the operation is applied after the
original value is used
- i ? i i 1
- // assuming that where() returns the same index
- arrwhere() ?
- arrwhere() arrwhere() 1
6Relational and Equality Operators
- All of these produce boolean values
- gt greater than
- gt greater than or equal to
- lt less than
- lt less than or equal to
- equal to
- ! not equal to
- Only the equality operators and ! are allowed
to operate on boolean values
- if (x lt 0)
- // statement
- boolean x true, y false
- if (x y)
- // statement
- else // x ! y part
- // statement
7Logical Operators
- Combine boolean expressions to yield boolean
values in boolean algebra - logical AND
- logical OR
- logical exclusive or (XOR)
- ! logical negation
- conditional AND
- conditional OR
- and are similar to and , but more
efficient, e.g. - if (a b c) will fail immediately if a or b
are false - if (a)
- if (b) // only if a is true
- if (c) // only if a and b a true
- if (a b) // if a is true then b does not matter
- boolean x true, y true
- x y ? true
- x y ? true
- x y ? false
- x y ? true
- x y ? true
- true !false
- boolean x true, y false
- x y ? false
- x y ? true
- x y ? true
- x y ? false
- x y ? true
8Bit Manipulation Operators
- The binary bitwise operators are
- bitwise AND
- bitwise inclusive OR
- bitwise exclusive or (XOR)
- Bitwise operators apply only to integers and char
- The complement operator toggles each bit in its
operand - The shift bit operators
- ltlt shifts left
- gtgt shifts right
- gtgtgt shifts right, setting to 0 bits on the
left-hand side
- 0xf00f 0x0ff0 ? 0x0000
- 0xf00f 0x0ff0 ? 0xffff
- 0xaaaa 0xffff ? 0x5555
- 0x00003333 ? 0xffffcccc
- int var 2
- var ltlt 1 ? 4 // multiply by 2
- var gtgt 1 ? 1 // divide by 2
- int var -2000
- var gtgt 2 ? -500
- var gtgtgt 2 ? 1073741324
9The Conditional ? Operator
- Provides a single expression that yields one of
two values based on a boolean expression - This operator is also called the question / colon
operator, and the ternary operator as it takes 3
operands
- value booleanExpr ? val1 val2
- if (booleanExpr)
- value val1
- else
- value val2
- double scale halveIt ? 0.5 1
- int scale (int)(halveIt ? 1. 2.)
casting
10Assignment Operators
- The assignment operator assigns the value to
its right to its left operand, which is a
variable - The type of the expression must be assignment
compatible with the type of the variable - Compound assignment operators (var op expr),
e.g. -
- -
-
- /
-
- int z 3
- x y z 3
- // perform an operation and assign the value
- x 3 y ? x x (3 y)
- x 1 ? x ? x
- var op expression ? var (T) ((var) op
(expression)) - where the variable var is of type T
11String Concatenation Operator
- To concatenate strings can be used
- String str part1 part2 123 ?
part1part2 123 - At least 1 of the operands must be a String and
the others will be implicitly converted - This is a built in operator
- The compound assignment operator
- String str this string
- str is a bit longer now
- It is better to use a java.util.StringBuffer when
more than 2 Strings are being concatenated - StringBuffer sb new StringBuffer(128)
- String cc sb.append(a).append(b).append(123)
.toString()
str
this string is a bit longer now
12Implicit Type Conversion
- Implicit conversions happen automatically
- A widening primitive conversion (e.g. assigning a
short to an int, a float to a double, an int to a
double) - However some may lose precision (e.g. a long (64
bits) to a float (32 bits)) - A narrowing primitive conversion assigns a larger
type to a smaller type (e.g. byte b 27)
13Explicit Type Cast
- An explicit cast is required when one type cannot
be implicitly converted into another - Most often this is when performing a narrowing
conversion, e.g. - int i 1234
- byte b (byte)i ? 46 // loosing the higher
bits - These can lead to a loss of precision
14Operator Precedence and Associativity
- Operator precedence determines the order in which
the operations gets executed - Assignment is right associative
- All other binary operators are left associative
- ? is right associative
- Precedence can be overridden with parentheses,
e.g. - 3 3 5 is different from
- (3 3) 5
- Parentheses can make code look illegible try
not to use them if not necessary
- Order of precedence
- postfix . (params) expr expr--
- unary expr --expr expr expr !
- creation or cast new (type)expr
- multiplicative /
- additive -
- shift ltlt gtgt gtgtgt
- relational lt gt gt lt instanceof
- equality !
- AND
- XOR
- inclusive OR
- conditional AND
- conditional OR
- conditional ?
- assignment - / gtgt ltlt gtgtgt
15Member Access
- . is used to access members of a type
- Static members can be accessed by using the type
name or an object reference of that type - Nonstatic members are accessed via an object
reference of that type
- class XX
- static int i
- void nsmethod()
- static void smethod()
-
- class YY extends XX
- static void smethod()
-
- XX.i
- XX.smethod()
- YY.smethod()
- new XX().nsmethod()
- new YY().nsmethod()
16Finding the Right Method
Dessert
- Invoking a method requires arguments of the
correct type and number - Only 1 method can be the correct one, e.g.
- void moorge(Dessert a, Scone b)
- void moorge(Cake a, Desert b)
- void moorge(ChocolateCake a, Scone b)
- void moorge(Dessert a)
Cake
Scone
ChocolateCake
ButteredScone
- moorge(dessert,scone)
- moorge(chococake,dessert)
- moorge(chococake,buttscone)
- moorge(cake,scone)
- moorge(scone,cake)
17Control Flow
- A program consists of a list of consecutive
statements that are executed in the order they
are written - The ability to control the order in which
statements are executed is important - The 2 basic statement are expressions (e.g. i)
and declarations (i.e. local variable declaration
statements) - Expression statements
- Assignment expressions, both or op variants
- Prefix and postfix forms of and --
- Method calls
- Object creation expressions
- Local variables must be initialized before use
- Curly braces group statements into a block
18if - else
- Is the most basic form of conditional control
flow - if (expression)
- statement1
- else // optional part
- statement2
- The expression part is of type boolean or Boolean
- The general form
- if (expression1)
- statement1
- else if (expression2)
- statement2
- else if (expression3)
- statement3
- else // optional
- statement4
- void setProperty(String keyword,double value)
throws UnknownProperty - if (keyword.equals(charm))
- charm(value)
- else if (keyword.equals(strange))
- strange(value)
- else
- throw new UnknownProperty(keyword)
-
- double sumPositive(final double values)
- double sum 0 // initialize before use
- if (values.length gt 1) // this if
- for (int i 0i lt values.lengthi)
-
- if (valuesi gt 0) // no else here
- sum valuesi
-
- else // this else
any number allowed
19switch
- A switch statement provides labeled constant
entry points in a block of statements - The general form
- switch (expression)
- case n statements
- case m statements
-
- default // optional
- statements
-
- The expression must evaluate to an integer (char,
byte, short, int, or a corresponding wrapper
class) or an enum type - A single statement can have more than 1 case
label - A break, return, throw, or continue can be used
to terminate a case (i.e. prevent a fall through)
- int hexValue(char ch) throws anException
-
- switch (ch)
- case 0
- case 1
- case 2
- return ch 0
- case a
- case b
- case c
- return ch a 10
- case A
- case B
- case C
- return ch A 10
- default
- throw anException
-
20while and do-while
- The while loop
- while (expression)
- statement
- The expression is either of boolean or Boolean
type - A do-while loop executes its body at least once
- do
- statement
- while (expression)
- int i 0
- while (i lt 2)
-
- int i 0
- do
- if (i lt 2)
- i
- else
- break
- while (true)
21The Basic for
- The general form is
- for (initialization expression
- loop expression
- update expression)
- statement
- A for loop runs until the loop expression
evaluates to true - A while loop equivalent
- initialization expression
- while (loop expression)
- statement
- update expression
-
- In a for loop the update expression is always
executed
- for (int i 0i lt 2i)
-
- for (int i 0)
- if (i lt 2)
- i
- else
- break
- for (int i 0,double j 0)
- return i
- for () // forever loop for (true)
- statement
22The Enhanced for
- Also known as the for-each loop
- The general form is
- for (Type loop-variable set-expression)
- statement
- The loop-variable is a local variable that
matches the sets content type - The set-expression is an object that defines the
set of values to iterate through - The set-expression is an array or an object that
implements the java.lang.Iterable interface
- void method ()
- int values new int 1,2,3
- double sum 0
- for (int val values)
- sum val
-
- import static java.lang.System.
- public static void main(String args)
- for (Sring arg args)
- if (arg.equals(-a))
-
- else if (arg.equals(-b))
-
- else if (arg.equals(-c))
-
- else
23Labels
- Statements can be labeled by a name, e.g.
- label statement
- A break statement can be used to exit a block
- break - unlabeled
- break label - labeled
- A continue statement is used within a loop
- continue
- continue label
- A continue cause the for loop to execute its
update expression, or go to the next element in
the set
- search1
- for (int i 0i lt 5i)
- search2
- for (int j 0j lt 2j)
- switch (i)
-
- default
- break search2
-
- while (stream.eof())
- final String token stream.next()
- if (token.equals(skip)
- continue
24return
- A return statement terminates execution of a
method and returns to the invoker - For void methods the return statement is
- return
- The method with a return type, the returned value
must match that type - A void return can be used to exit a constructor
- void method (final int arg)
- if (arg gt 5)
- return // optional
- else
- System.out.println(arg)
-
- double method (final double val)
- if (val lt 0)
- return 0.
- else
- return val
-
- public class X
- public X(final int arg)
- if (arg gt 5)
- return
-
25Generic Types
- In Java the class Object forms the root of the
class hierarchy - This is good because all objects can be cast up
to Object - This is bad because
- we can potentially insert objects of the wrong
type into a set or similar - we must cast explicitly back down to the actual
class - Generic types allow to store only a particular
type of objects and they make code type safe - Any type mismatch is detected at compile time
26An Example Generic Store
- class Store // before java 1.5
- private int count
- private Object arr new Object10
- public Object get(final int i)
- if (i lt arr.length)
- return arri
- return null
-
- public boolean set(final Object obj)
- if (count lt arr.length)
- arrcount obj
- return true
-
- return false
-
-
- // this Store takes any type, not only Strings
- final Store store new Store()
- class StoreltTgt // java 1.5
- private int count
- private T arr (T)new Object10
- public T get(final int i)
- if (i lt arr.length)
- return arri
- return null
-
- public boolean set(final T obj)
- if (count lt arr.length)
- arrcount obj
- return true
-
- return false
-
-
- // this Store takes only Strings
- final StoreltStringgt store new StoreltStringgt()
27Generic Type Declarations
- The declaration StoreltTgt is a generic type
declaration - Store is a generic class, and T is the type
parameter - StoreltStringgt is a specific i.e. parameterized
type and String is a specific type argument - The use of a parameterized type is known as a
generic type invocation - A generic type declaration can contain multiple
type parameters separated by commas (e.g.
StoreltA,Bgt, StoreltA,B,Cgt)
28Raw Type
- The class Store is known as the raw type
corresponding to the generic class declaration
StoreltTgt - StoreltStringgt and StoreltNumbergt are not 2
different classes, but 2 generic type invocations
of the one class Store, e.g. - StoreltStringgt ss new StoreltStringgt()
- StoreltIntegergt si new StoreltIntegergt()
- boolean same ss.getClass() si.getClass()
- The use of ltIntegergt and ltStringgt in the
constructor invocations are not class definitions - They help the compiler to check that the object
is used correctly
29Limitations
- Primitive types are not polymorphic objects, so
Storeltintgt is not allowed - Generic types cannot define static fields of a
parameter type. No access to static members via a
parameterized type name (e.g. StoreltStringgt.aStati
cMethod) - Generic types cannot create arrays or objects of
a parameterized type, e.g. - class StoreltTgt
- private T obj new T() // what constructor to
use? - private T arr new T10 // requires a field
for each T -
- Therefore, the compiler uses
- the most general type available to represent the
type parameter (often Object) - type casting to ensure correctness
30Bounded Type Parameters
- In the generic declaration of StoreltTgt, T stands
for any reference type - Thus, a Store can store any type but sometimes we
want to be more specific
- // restrict comparison only to Items
- class Item implements ComparableltItemgt
- public int compareTo(final Item it)
- int result 0
- // compare
- return result
-
-
- // Comparable as the upper bound on T
- // T is a bounded type parameter
- interface SortedCollectionltT extends
ComparableltTgtgt - // sorted collection methods
-
- interface SortedCharSeqCollectionltT extends
ComparableltTgt CharSequencegt - // sorted char sequence collection methods
31Static Nested Generic Types
- A nested type can be declared as a generic type
- Any type variable in a static nested type is
distinct from any type variable in the outer type
- class StoreltTgt
- InternltTgt intern
- static class InternltTgt
- T element
- Intern(T t)
- element t
-
- T getElement()
- return element
-
-
32Inner Generic Types
- If the nested type is an inner class then the
type variables of the outer class declaration are
accessible to it - A type variable in the inner class hides any type
variable with the same name in the outer class - Hiding variables should be avoided
- Deeply nested classes should be avoided
- class StoreltTgt
- InternltTgt intern
- class InternltTgt
- T element
- Intern(T t)
- element t
-
- T getElement()
- return element
-
-
- public static void main(String args)
- StoreltIntegergt sb new StoreltBytegt()
33Subtyping and Wildcards
- ListltNumbergt means an object compatible with List
that has elements declared to be Number - ListltIntegergt is not a subtype of ListltNumbergt
- An unbounded wildcard stands for any type (e.g.
Listlt?gt) - A bounded wildcard forms the upper bound on the
type that is excepted - Wildcard type as a supertype or the same of
another (e.g. Listlt? super Integergt) forms the
lower bound on the wildcard
- static double sum(ListltNumbergt list)
- double sum 0
- for (Number n list)
- sum n.doubleValue()
- return sum
-
- ListltIntegergt list new ArrayListltIntegergt()
- list.add(1)
- double sum sum(list) // a compile error
- // upper bounded wildcard
- static double sum(Listlt? extends Numbergt list)
-
-
- Listlt? extends A Bgt // a compile error
34Bounded Wildcard Relationship
generic
Listlt?gt
- A bounded wildcard can have either an upper or a
lower bound - The non-wildcard and wildcard versions of
parameterized types relate differently - Typically, method parameters use lower bounded
wildcards, and return values us upper bounded
wildcards - Wildcards cannot be used to name a class or
interface in an extends or implements clause
Listlt? extends Numbergt
ListltObjectgt
Listlt? extends Integergt
ListltNumbergt
ListltIntegergt
specific
- Queuelt?gt q new QueueltStringgt()
- q.add(Hello) // a compile error
- Object o q.remove()
- Queuelt? extends Numbergt q new QueueltNumbergt()
- q.add(new Integer(1)) // error
- static void add(Queuelt? super Stringgt sq)
- sq.add(Hello)
35Generic Methods
- A parameterized type array is to be passed in
- method1 is restrictive because Number is Object
but an Object is not necessarily a Number - Therefore, method1 may not know what to do with
the Object - However, casting up a return value is fine
meaning that no specialization is needed - method2 constraints only the parameter and return
type to be the same and ignores the class type
- import static java.lang.System.
- class XXltEgt
- // restrictive
- E method1(E arr)
- for (E e arr)
- out.println(m1 e.toString())
- return arr
-
- // generic
- ltTgt T method2(T arr)
- for (T e arr)
- out.println((m2 e.toString())
- return arr
-
-
- QueueltNumbergt qn new QueueltNumbergt()
- Object a1 qn.method1(new Integer 1,2
- Object a2 qn.method1(new Object 1,2
36Generic Constructors
- A class declaration like class XltEgt allows any
type - To be more specific, only a specific subtype can
be allowed - This can be achieved in 2 ways
- in the class declaration (e.g. class YltE extends
Bookgt) - in a constructor declaration (e.g. Y(VectorltBytegt
e) ) - Generic methods and constructors are used to
introduce a type variable to constrain - the parameterized types of different parameters,
or - a parameter and the return type
- class XXltE extends Objectgt
- E element
- // any class
- XX(E e) element e
-
- class YYltE extends Numbergt
- E element
- // only Numbers
- YY(E e) element e
-
- class ZZltEgt
- E element
- // (E)e is an unchecked cast
- ltTgt ZZ(T e) element (E)e
-
- class WW
37Generic Invocations and Type Interface
- To parameterize a method invocation supply
requires type arguments for the methods type
variables - Explicit parameterizing is rarely needed
- Type inference is based on the static (i.e.
compile time) type
- ltTgt passThrough(T obj)
- return obj
-
- String s this.ltStringgtpassThrough(explicit
parame...) - s passThrough(inferred)
- s ltStringgtpassThrough(s) // compile error
- String s Also valid
- Object o1 passThrough(s) // T is String
- Object o1 passThrough((Object)s) // T is
Object - String s1 ? passThrough((Object)s) // compile
error
38Wildcard Capture
- Wildcards represent an unknown type, but the
compiler must be able to check the type - This specific (but still unknown type) is
referred to as the capture of the wildcard - XXltcapture of ?gt is not the same type as
XXltStringgt - The capture conversion relaxes this restriction
- class XXltEgt
- int ix
- E element
- XX(final E e) element e
- E replace(final E e)
- E old element
- element e
- return old
-
-
- XXlt?gt x new XXltStringgt(a string)
- x.replace(another) // a compile error
- x.ix 5 // OK, this one is immutable
the type of x
39Erasure and Raw Types
- For each generic type there is only 1 class
- Erasure is a process of removing all generic type
information from the complied code - The erasure of a generic type is the unadorned
type name, i.e. the raw type (e.g. for VectorltEgt
is just Vector) - The compiler inserts a cast when the erasure does
not match what is expected - The erasure process impacts
- The runtime actions that can involve generic
types - Method overloading and overriding
40Erasure at Runtime
- Nothing that needs to know the value of a type
argument at runtime is allowed - Therefore
- Instantiating a type that is a type parameter is
not allowed (e.g. new T() or new T) - instanceof cannot be used to check for
parameterized types, except for all unbounded
wildcards - A catch clause must know at compile time exactly
what exception it catches - A class literal expression does not allow
parameters (e.g. SomeClassltStringgt.class) - Casts involving type parameters or parameterized
types are replaced with casts to the erasure
41Overloading
- 2 methods have override-equivalent signatures if
their signatures are the same, or if the erasures
of their signatures are the same - 2 methods are overloaded if they have the same
name and do not have override-equivalent
signatures
- class BaseltTgt
- void m(int x)
- void m(T t)
- void m(String s)
- ltN extends Numbergt void m(N n)
- void m(Queuelt?gt q)
-
- // compiles into
- void m(int x)
- void m(Object t)
- void m(String s)
- void m(Number n)
- void m(Queue q)
- // an error if defined
- void m(Object t)
- void m(String s)
- ltG extends Stringgt void m(G g)
- void m(QueueltObjectgt q)
42 and Overriding
- A method in a subtype potentially overrides an
accessible method in a super type if the 2
methods have - the same name, and
- override-equivalent signatures
- The signature of the subclass method must be the
same as - either that of the superclass method, or
- the erasure of the signature of the superclass
method - Only a method without generic types can override
a method with generic types
- class DerivedltTgt extends BaseltTgt
- void m(Integer i) // new overload
- void m(Object o) // override
- void m(Number m) // override
-
- When overloading and overriding
- always consider the erasure of the method
signatures, and - remember that genericity cannot be added to an
inherited method
43Class Extension and Generic Types
- A nongeneric type can be extended to produce a
generic or nongeneric type - A generic type can be extended to produce a
generic subtype - A parameterized type can be extended to produce a
nongeneric subtype, or both can be combined - A class cannot inherit 2 interface types that are
different parameterizations of the same interface