Oracle Certified Associate
This is step one to become Certified Master. It is a mandatory step by the way. You will have to pass 3 exams and all of them cost around 200 euro, so a good preparation might be a money saving thing:
- Oracle Certified Associate
- Oracle Certified Programmer
- Oracle Certified Master
My aim is to at least become OCP, but of course if i have that i am going to try OCM as well. But first things first : i only had half of the assessment questions right on the OCA guide so here is an extract of the study guide.
Important
I will be putting hard statement and limits in these boxes. example : There are 8 primitive types : boolean , byte , char , short , int , long , float and double .
Java building blocks
This may come in handy to know beforehand. I may repeat it later.
Liskov substitution principle
If S is a Subtype of T then objects of type T may be replaced with objects of type S without altering any of the properties of T.
Class structure
!! important "classes can have 2 kinds of members"
fields and methods
The most minimal (usable) Class could be :
So no implementation at all, this compiles, but so does an empty file. Even smaller will compile :
| minimal class | |
|---|---|
fields
Fields are also called variables and they maintain the state of the program and objects.
methods
Method operate on the state of objects/classes. The full declaration of a method is called the signature. This includes the modifiers (public in this case)
comments
!! important "There are 3 kinds of comments"
single-line, multi-line and javadoc.
The comments are ignored, but not completely since they do act as whitespace :
imports
Important
the package java.lang.* is the only automatically imported package
Of course... also the current package is 'imported' but i always view that as 'already being inside' that package.
In case of conflicts the compiler is smart about most things. For instance Data is a class in both java.util and java.sql. But this will work : compiler knows which Date you mean and still can use the wildcards for the rest.
| import | |
|---|---|
packages
If you don't use a package name, java still assumes some 'default' package without any name. Otherwise the directory structure follows the package name but the compiler won't create it for you, you need to follow the source structure.
If you put this in Sample.java
| packages | |
|---|---|
It will compile, but the class is now called org.klopt.test.Sample so this will fail :
Put it into this structure and it will work :
| directory tree | |
|---|---|
variables and types
literals
K.. here are some new ones for me..
Important
Just like 0x... for hexadecimal, java7 and up have the 0b.. binary format. So 0b11 is 3 !!
Important
For clarity, you can use underscore in numbers to make thousands clearer, int x = 1_000_000, sadly also 1_00_00_00.00; but NOT _100 or 100_ or 100_.00
identifiers
Important
You should stick with : [_\(A-Za-z][_\)A-Za-z0-9], but you could* use all unicode letters. Actually do NOT use $ either. !!
- An identifier my start with a letter, _ or $.
- After that also numbers may be used.
- Reserved words are not allowed.
So legal are :
These examples are not legal:
| illegal identifiers | |
|---|---|
local,instance and class variables
- local variables are local to a member function, they contain garbage if not initialized, and so won't compile. Parameters to methods are also local.
- instance variables are members of objects, if they are not initialized they get a default value of something closest to 0.
- class variables or static variables are also initialized to 0, these are initialized once when the class is first loaded.
member functions can be called the same as the class name!
When it has a return type (even void !!) it is NOT a constructor. Think of it as: if a constructor should return anything, it would be the class itself.
| variables | |
|---|---|
initialization
Member variables can be initialized.
- directly in the declaration
- in one or more initialization blocks
- in the constructor
The initialization blocks can be nested like normal code blocks (though you should keep them small). They can be intermixed with declarations, and they are executed in order. Afterwards the body of the constructor is run. So this code will assign the following to X in this order : 10, 20, 30, 40.
| initialization | |
|---|---|
One detail about this , you can use variable as left hand side (assign to it) before it is declared, but not the right hand side (like print it) this code fails on the println command, and not on the assignment :
If you remove the second initialization block with the println, it will compile and print 20. But order still matters: if you change the declaration to int i=10; the program will print 10 !!.
So as i see it this next code :
| prints 20 | |
|---|---|
Triggers these actions :
- load class, initialize j to 0
- call the main function
- create an instance of X when encountering new X
- create a member variable called i uninitialized (random value)
- now walk all initializers, so start with making i 20
- assign i value 10
- next the constructor so i becomes 30
- now print the values: so 30 and 0
Note that even after the i=20; you still can't use it for printing. This is where it differs from local variables, where you cannot initialize them before the declaration, but you CAN use that as soon as they have a value:
| error | |
|---|---|
the compiler evaluates all possible paths
If there is a path in which a variable does not get a value but does get used, you get a compile error.
| error | |
|---|---|
freeing memory
In general you just drop an object by dropping it's reference. For instance when you let it go out of scope, or setting it null, or stop referencing the object it is a member of.
!! important "There is a function called System.gc() that does NOT invoke the garbage collector"
It just suggests to the garbage collector that now might be a good time to run, the VM itself decides if it will do so !
Objects are just blobs of data on the heap without any name, you don't get it's physical address just a reference that make you access it. And once the last reference is gone it goes on the candidate list for re-use.
finalize
finalize is a function that get's called when an object is collected by the garbage collector. So that might run much later then when you release the reference, or not at all, like when you exit the program.
Important
When you exit() java VM is not going to walk all finalizers, it just quits and frees all memory !
You can however rely on the fact that it does not get called twice. For instance if the garbage collector fails to reclaim an object en retries again later, the second time it does not call finalize() again!.
Important
finalize() get's called 0 or 1 time, never more.
An example of this is when you add 'this' to a list that still remains visible outside of the object. Suddenly the object is now referenced again and the object can no longer be reclaimed.. Now when you remove the object (or the whole list) the finalizer is not called again.
Don't use finalize for closing resources or things like that, you never know if or when it's called. Better yet:
Effective java, rule 7
Avoid finalizers
arrays
Both before and after the variable name is supported.
| arrays | |
|---|---|
Actually in parameter list there is a third notation, these all make an identical String array inside main :
| identical | |
|---|---|
character arrays
These could actually works as strings if you fill each element individually.
| c-style strings | |
|---|---|
object format
Arrays are also objects, so if you print them you get something like :
| format | |
|---|---|
The [ means array and this is followed by the type, I is for integer, D is for double, J is for long (not L it's use for objects) ... . If it is an object like string you get the whole type between 'L' and ';'. The last parts is not the address, but the HashCode !!.
In fact it seems that the default toString implementation from object is :
| probable toString | |
|---|---|
And indeed if you print .getClass().getName() for a String and of an array of String you get :
Including the trailing ;
printing
The java util Arrays class has a nice way of printing arrays, without having to loop over it:
This will come in handy for the sorting section next.
sorting
The sort function also comes from the java.util.Arrays class :
| sorting | |
|---|---|
searching
| binary search | |
|---|---|
There is no such thing as a linear search for unsorted arrays in the Arrays class. You will have to loop yourself.
multidimensional arrays
Arrays are objects, so you can create arrays of objects which are itself arrays.
| multidimensional | |
|---|---|
That also means that every sub-array can be any size, it's a separate array. As you can see, Arrays.toString does not go deeper and prints the object references, .. sad.. Also note that length is now a public member, and not a function.
length
length() is a method on Strings, length is a member on arrays.
In C/C++ arrays are contiguous slots in memory, so they have to be rectangular/cubic etc.. A java multidimensional array is exactly like an array of pointers to arrays in C++.
More instantiation forms :
| initialization | |
|---|---|
Printing the array is most terse using enhanced for loop :
| enhanced for | |
|---|---|
operators and statements
operators
Especially the precedence is important, but here is also a breakdown to remember :
| Operator | example | hint |
|---|---|---|
| Post-unary Pre-unary Other unary Multiplication Addition | a++ a--++a --a ~ + - ! * / % + - | a+++a becomes (a++)+a |
| Shifting | << >> >>> | binary shifts |
| Relational | < > <= | also : instanceof |
| Equality | == != | lower than < > |
| Logical | & | |
| Short circuit | && | |
| Ternary | ? : | only 1 flavour |
| Assignment | = += >>= | also binary but lowest |
Roughly, you could divide this in
- unary: in the order : x++, ++x, !~+-
- binary: *,+,>>,>=,==,&,&&
- ternary: ?:
- assignment: = += <<=
On the same level operators are evaluated left to right so !~+- is in no particular order, but the comma's mean lower levels.
Ok, after much nonsense threads i finally got an example of where postfix unary takes precedence over prefix :
| postfix wins | |
|---|---|
In this example you don't take a+(++a) but (a++)+a ... sigh! Notation like this do not compile :
assignment
Important
Whenever you risk losing information, you get a compiler error !
lossy conversion is not allowed by the compiler:
| assignment | |
|---|---|
!! important
All floating point literals are assumed to be of type double.
So this is a tricky one, because you have to use the 'f' notation for floats :
| use f | |
|---|---|
numeric promotion
In expressions:
- If two values are of different type, java will promote the smaller one to the larger one.
- If one is integer and the other a floating type, the integer is promoted to floating.
- All types smaller than int/32 bits (char,byte,short) are promoted to int even if no operand is that big.
- After all promotions are performed, the result will have the promoted type.
Some consequences of these rules :
| promotion | |
|---|---|
Since s1 and s2 are promoted to int, so you are now assigning a bigger type (int) to a smaller type.
casts
Important
casts are generally used to force bigger types into smaller ones. Be it int of floats into shorts or wider object types into subtypes etc.
Casting a larger type into a smaller one wraps/overflows if the high bits are set.
Important
note that overflow/underflow could be the wanted value in certain solutions !! though you should perhaps better use masking.
compound statements
Fairly straightforward : +=, -=, etc. But here is an extra advantage beside shorter notation.
| automatic cast | |
|---|---|
The compound operator performs the casts as shown in the last line.
Important
compound operators insert the casts when needed
relational operators
Weirdly these do not include the equality operators, but they DO include the instanceof operator.
instanceof
the relational operators are : <, <=, >, >= and instanceof
'a instanceof b' is true if a is an instance of b or a subclass of b or implements interface b.
Important
when comparing different types, numeric promotion is used, so 5.0 == 5 evaluates to true. "5" == 5 will not compile.
logical operators
&, | and ^ when used on numeric operands, perform bitwise and, or and xor like in C, when on boolean operands they are evaluated logical. All operands are evaluated. This in contrast with && and ||.
Important
&& and || only evaluate the right hand side if needed. boolean x = true || never_called() ; boolean y = false && never_called();
equality operators
These are use to compare :
- two numerical operands, in which case they are promoted to the largest type
- two boolean operands, 0 and 1 are not related to false or true !
- two objects, in which case they just compare references, so these are in fact the same object.
To compare the content of two different references, you can override the .equals() method. By default this just does the same as == but for instance for Strings it is overridden, so :
| equality operators | |
|---|---|
Note that a and d are referencing the same string in the string Pool, while c was explicitly requested as a new string.
Literal strings are gathered in one string pool
This is after concatenation, so "Hell"+"o"; and "He"+"llo" will become the same entry/same pointer/same hashEntry.
statements
When you create an obvious unreachable statement the compiler will complain:
But not with runtime evaluations like this :
| compiles | |
|---|---|
or even this will get no compiler complaint (good!)
ternary operator
In the expression :
| ternary | |
|---|---|
x must be a boolean expression, but y and z can be any type. This will work for instance for printing, but not for assignment.
| boolean | |
|---|---|
Because there is a println(String) as well as a println(int) line 1 will work. Line 2 just will not fit, normal assignment rules apply.
Important
From java 7 and up ,only one of the operands y and z are evaluated, watch out if you depend on side-effects
switch statement
Allowed types for a switch are :
- int and Integer
- byte and Byte
- short and Short
- char and Character
- int and Integer
- String
- enum values
Important
Remember the list above and note there is no boolean and no long, but there is String !!
This snippet shows that not every case is re-evaluated, it just chooses, sets the flow at that point and continues to the first break.
| switch | |
|---|---|
Also this show that :
Important
There is no requirement for the default to be at the end of the switch statement.
The case statements must match the type of the switch statement but you also cannot use common variables (except finals) :
Note that lastName fails because it is final but not constant since it is passed to a function.
Important
case statements must be a literal, enum constant, or final constant variable.
Important
With a final constant we mean a variable that was declared final and initialized with a literal in the same statement. (So not the lastName parameter above).
Look at it as if the compiler wants to prepare the complete switch with hardcoded values. The parameter lastName would be problematic there.
for statement
There are 2 loop statements in java :
- basic for loop (c style)
- enhanced for loop (for-each)
basic loop
Some pitfalls:
You cannot declare a variable again as a loop variable:
| similar problems | |
|---|---|
You can declare multiple variables in the for loop but that have to be of the same type !!
| same type only | |
|---|---|
But you CAN use them (and initialize. just not declare them).
| only usage works | |
|---|---|
for-each loop
These loops are of the form
for(type element : collection) should be read as for(each) element in collection.
The right hand side (the collection) must be a java built-in array or an object hat implements java.lang.Iterable ! The left hand side must include a declaration for an instance of a variable who's types matches that of an element of the collection(right hand).
Important
Note that the left hand can't be just a variable, it must be a declaration.
When for-each loops were added in java version 1.5 they where just converted at compile time to a regular for loop. Therefore these two constructs are equivalent.
| same as | |
|---|---|
For the objects that inherit java.lang.Iterable, the conversion is :
| short for | |
|---|---|
Notice that in both example, some part of the conversion appears inside the loop. This is probably why the left part MUST be a declaration.
Important
with a for loop you don't have access to the loop variable or index, making some constructs difficult.
For instance printing comma's between but not at the end of a list:
| skip comma in standard loop | |
|---|---|
This can't be done with a for-each without introducing a counter. So just use for-each loops when you cleanly want to traverse all members.
labels, break and continue
You can use labels to have more control over especially nested loops :
The structure of a loop and break is :
A label has little use in a single loop like this, but only in nested loops. The label does not have to be on the same line, so this example works.
This example would print only the first
control usage
The break and continue are not permitted in every statement.
| statement | allows labels | allows break | allows continue |
|---|---|---|---|
| if | yes | no | no |
| while | yes | yes | yes |
| do while | yes | yes | yes |
| for | yes | yes | yes |
| switch | yes | yes | no |
Important
labels are allowed before any block statement.
So this is a legal extension to the Loop class above:
Core java api
Strings
adding/concatenation
When using + operator, if either operand is a string the result is concatenation by converting the other operand to string.
That means when evaluating the operands left to right :
The string pool
Java uses a string pool to reuse string literals, but it does not use that when you use 'new'.
| string pool | |
|---|---|
This print two times the same value, one time a different one. The first two are the same in the string pool, the last one is a new pointer.
Note that using hashValue() prints the same number three times because that's simply the hash that is used to find strings in maps etc.
stringbuilder
Strings are immutable, StringBuilder is not.
Important
StringBuilder is the not-thread-safe version of StringBuffer but much more efficient because of that.
| basic usage | |
|---|---|
So you build your string, and in the end convert it for usage. Also to show that append returns a reference to the same mutable object :
| building | |
|---|---|
Here is a short display of the StringBuilder functions.
Array
| arrays | |
|---|---|
int[] is preferable
Like : "a is of int[]" Try to shake the C habit!!
Actually in parameter list there is a third notation, these all make an identical String array inside main :
| identical | |
|---|---|
ArrayList
This is a dynamic array. Probably the most used data structure ? Some basic usage.
Important
Always declare variables in their widest type. You can do more with the widest type !
| arraylist | |
|---|---|
Now some caveats :
Generics only works with object
Not primitives. so List
| add/remove | |
|---|---|
Converting ArrayList to an array must be done by providing an object of the wanted return type :
If you do it the other way round, the ArrayList will get references to the original so they become linked :
Date and Time
This has been changed for version 8, and i only handle the new formats.
Important
New Date and Time classes are from package java.time.* and start with Local[Date][Time]. These cannot be instantiated.
Important
The only units that are not just plain numbers are months and weekdays, and so these have enums called Month and DayOfWeek.
You use them with factory methods like so :
Besides that there are Period and Duration classes. But you cannot chain these :
Important
Durations and Periods have static member functions and can therefore not be chained.
Important
There is no point in chaining static methods because you cannot return your own 'this' object, since there isn't one.
So you need to pick a suitable factory method :
| periods and durations | |
|---|---|
Unix time stamp and formatting
Parsing
Finally, parsing strings into dates used DateTimeFormatter as well :
| parse date/time | |
|---|---|
Methods and encapsulations
Methods are built up the same :
[access modifiers] [specifier list] return_type method name ([parameter list]) [throws exceptionlist] {}
Simple way to remember is probably the main function. Which has one of each except .... the exceptions. 8)
| modifiers | |
|---|---|
All access modifiers
Access modifiers are empty, private, protected or public.
- If empty the access is default or 'package private'.
- public means accessible for anyone
- protected means accessible from with the package and for subclasses
- private means accessible for this class only
Important
Specifiers can be a combination of static, abstract, final, synchronized, native and strictfp. Logically not all combinations are possible.
- static : the method is not part of an instance
- abstract : this method does not have an implementation
- final : this method can not be overridden by a subclass
- synchronized: the methods can be called in a threadsafe way
- native : the method is implemented in another language, probably c
- strictfp : method used strict (portable) floating point calculations
Only Constructors have no return type
If you make a method with the name of the class and a return type (including void), it's just a normal method."
protected access
public and private access are pretty straightforward. The first allows anything, the second nothing outside the own class. package private is also simple, everything in the same package has access.
Protected has some more caveats. It starts out as having the same access as package private but with subclasses added. First for java to find the classes you need to setup the directory structure so keep it as simple as possible :
| directory | |
|---|---|
Both files need to be compiled together but i will comment them separate.
Important
The java compiler will automatically compile the other file as well if you only do javac first/Access.java
| first package | |
|---|---|
What we see here is that the reference type counts and not what it was created as. sa is a SubAccess type and has no access to x, a is an Access type and since we are within that class it has access to it's own members.
| second package | |
|---|---|
Here we are in a different package, so now this code can use the protected y member because it is within a subclass of Access. An access object itself can't use the y member because it is outside of the package, and outside of the Access class code.
Important
Access is granted to code within a class or package, not to an instance. Instantiating a class is completely outside the protection/privacy.
static methods
Note that since static methods are not related to an instance this is possible :
| static method | |
|---|---|
There is no need whatsoever for java to check the reference, it just looks at the class and returns the static member. So this just works !
static initialization
You can also initialize static data with an anonymous section, just put static in front of it:
| static initialization | |
|---|---|
Since there is no constructor involved these get called in order of appearance. And in this case (final) exactly 1 assignment has te be done.
static imports
Important
Static imports are for importing members, normal imports are for importing classes.
The static has to come after import and not before, but that's kinda logical since import is the 'command' or statement.
call by value
Important
All parameters to methods are call-by-value, there are copies on the stack.
This means you cannot alter the parameters themselves, only their content.
overloading methods
Important
The access modifiers and exception list are irrelevant to overloading, and so is the return type.
Important
A method overload if it has the same name as another method but different parameters.
Note again that int[] and int ... both boil down to an integer array, but there is a small difference, this will not compile :
| overloading | |
|---|---|
But you can only call the second one with oload(1,2,3). Only inside the function it's an int array. Outside you need to call the first version with :
So you could (ab)use the ... format to create an array :
autoboxing and integer promotion
Important
Java attempts conversion to a wider type (if needed) like short to int (promotion), or int to Integer (autoboxing) but not both at once : short to Integer.
Of course java will always match exact matches first, but with multiple variables the choice may become blurred.
- Exact match by type is first.
- Large primitive type conversion is tried next.
- Autoboxing is third.
- Varargs comes last.
Of course combinations are trickier, but this is not OCA material.. later.
Constructors
Important
A constructor is a method without return type and with the same name as it's class.
Important
If you do not create a constructor java will put a default constructor without parameters in itself.
You can view this with javap by the way:
The second command is "The Java Class File Disassembler" and it will generated this :
This is more an outline of the class, for instance the Constructor has no body, you can use javap -v or -c for more elaborate listings.
It seems unimportant that java physically generates this constructor because it does nothing, but in some cases it does matter, for instance with other generated code like super() see later on ...
Constructors can be overloaded and chained, but :
Important
A constructor can call either one this() or one super() constructor but it has to be the first statement of the constructor.
So you can't call different super() and this() constructors in a row.
javabeans naming conventions
Since this is considered good practice, just use this :
immutable classes
In general just don't provide a setter method, but beware of returning references to internal variables or they become mutable after all :
| immutable | |
|---|---|
lambda's
Somewhat like function pointers or closures, but this is an example that shows the idea :
The interface is needed to be able to pass the function as a parameter:
Important
An interface with one abstract method is called a 'functional interface'. Lambda's need a functional interface to work.
Important
View lambda' as an extra stackframe to sense what you can do with variables.
For instance :
- You can use local variables and parameters but not change them.
- Static and member variables can be used and changed.
- You cannot redeclare a local variable inside the block.
lambda syntax
The full form with 1 parameter could be :
| syntax | |
|---|---|
- Type name can be skipped.
- Parenthesis are only needed if there are more than 1 parameter.
- Brackets, return and ; can be skipped if there is only 1 statement
That means the shortest form of the lambda above is :
| minimal | |
|---|---|
predicates
If you use lambda's to test simple condition, for instance to loop over a list and pick out elements on a simple check, you can use a pre-built functional interface called Predicate:
| predicates | |
|---|---|
This is actually used by existing classes like ArrayList that makes this code work :
class design
class modifiers
Top classes cannot be made private of protected, nested classes can !
Important
The only access modifiers to a top level class are public or default(absent).
Important
Nested classes can be private or protected !! You can and should view nested classes as members of the enclosing class.
all classes are Object subclasses
All classes inherit from java.lang.Object one way or the other. Either they extend a class, or the compiler adds 'extend java.lang.Object' to it. Take this code :
| Object | |
|---|---|
When using the disassembler, with the -c(ode) option you can see some of the code insertion done by the compiler :
| under the hood code | |
|---|---|
First the invokespecial line calls the constructor for Sup() explicitly, while we did not do that ourselves. Second if you look at Sup :
| invokespecial | |
|---|---|
This one is short enough to print whole, and you see that it in turn invokes the constructor for Object(), also not in our code.
Personally i think this is a weak solution from java and it should have just throw a compile error if you omit a constructor.
Important
Define default constructors and super() calls explicitly yourself. Its just clearer.
Important
in java every first statement is a call to another constructor, either one of it's own by using this() or of it's parent using super().
Since you cannot keep calling this() recursively the call path of a constructor always ends up in a super() version.
Overriding methods
Important
You can override a method from a parent class by using the same signature and return type.
The rules for overriding are
- The method must have the same signature and return type as the one in the parent class
- The method in the child class must be at least as accessible as the parent.
- The method in the child may not throw a checked exception that is new or broader than the on in the parent. New of course is also broader then nothing.
- If the method returns a value, it must be the same as or a subclass of the type in the parent.
Important
Types that are the same or subclassed from a type are called covariant with that type.
redeclaring private methods
Attention
Private methods are not overridden, but just redeclared in the child class.
Best to look at it that for the child there is no method in the parent class if it's private: This means you just declare a new and fresh method.
Caution
All restriction mentioned in the list above do not apply since this is NOT an override but a completely different method.
hiding static methods
Important
When both parent and child methods have the same name + signature and are static, it is called hiding the method.
When you mix static and non static the compiler will not pass it, just like it wouldn't when you do :
| mix static and non-static | |
|---|---|
Important
Hiding static methods can lead to confusion, just use another name !
overriding vs hiding
Almost all these calls act like you expect except last s.func() call. If it's a Sup why does it print a Pref ?
If you look at it with a C/pointer eye it all makes sense. You created a Pref object with new Pref(), it's now just assigned to a wider pointer. It is still a Pref() !! The first reference s was created with new Sup() and so it's a Sup.
The static ones don't look at the content, they just print the static function which is why even the last call still works !!
creating final methods
making a method final means it cannot be overridden.
Important
Final methods cannot be overridden in their subclasses but also not hidden!
Making methods final means you are very certain that this is the behavior wanted. You could also make a method private if you don't want people to touch it but :
Important
The difference between making a method private and final is that the private one can't be called from the outside.
inheriting variables
Important
You can only hide variables, there is no overriding. Both for static and instance variables.
Important
You can reach the hidden variable with super. but it is bad practice and only leads to confusion. Just pick another name !
Important
An abstract class does not have to have any abstract methods.
Important
If any of the methods is abstract, the class has to be abstract.
creating abstract classes
Abstract classes and interfaces look alike, but :
You can declare whole classes as abstract but also separate methods.
Abstract methods may not have a body, not even empty braces. So they are always followed by a semicolon ;
| abstract | |
|---|---|
Important
In classes and methods you cannot use both abstract and final since the former says "start implementing here", and the latter says "stop implementing here".
Also private and abstract are incompatible.
Important
You cannot mark a method as both abstract and private. You can't override a method if you cannot call super() because it's private.
concrete classes
Abstract classes cannot be instantiated, only the first non-abstract class can be instantiated and it has to provide implementations for all abstract methods left.
Important
You can have a hierarchy of a number of subclasses each implementing some abstract methods, or even introducing new abstract methods on the way down...
Important
... The first subclass that is not abstract can be instantiated, becoming a concrete class. This class has to implement all remaining abstract methods.
defining interfaces
Important
An interface is an abstract data type that defines a list of abstract public methods that any class implementing the interface must provide.
Important
The keyword abstract is assumed and not required.
Important
If an interface is declared public it too has to be in it's own file. It can only be public or default.
- An interface may not be instantiated directly.
- An interface is not required to have any methods.
- An interface may not be marked as final.
- All top level interfaces (as opposed to inner interfaces!) cannot be final, private or protected.
- All non-default (java 8 feature) methods are assumed abstract and public. So private,protected and final trigger compiler errors.
Important
Adding the abstract keyword is not required but considered good practice, i would personally do this. It is just not in the way in any sense.
inheriting from an interface
Extending is not implementing !!
You can extend an interface with another interface much like abstract classes.
There are 2 rules when extending an interface:
- An interface that extends another as well as an abstract class that implements an interface inherits all of the abstract methods as it's own abstract methods.
- The first concrete class that implements an interface or extends an abstract class must provide an implementation for all the inherited abstract methods (left).
Important
The only connection between class and interface is : class implements interface.
- A class can extend a class.
- An interface can extend an interface.
- A class can implement an interface.
Important
An interface can not be a descendant of a class.
Multiple inheritance
You can implement multiple interfaces, but also extend multiple interfaces.
Important
For interfaces it is possible te extend multiple interfaces, single inheritance is merely for classes extending classes.
When two interfaces define the same function you have to implement only one and both will be satisfied.
Important
If a method from two inherited interfaces has the same name but different signature, it is like an overloaded method, and so you will have to supply both methods.
This leads to a very nasty 'bug' in the java design in my taste:
Important
You cannot inherit from two interfaces that have the same method signature but different return type.
This does mean that classes that have a similar method but different return type you will have to choose one !!
This does not compile
| multiple inheritance | |
|---|---|
This is a rather nasty one no-one tells about !!?!
interface variables
Important
Interface variables are expected to be public, static and final. And so they should be set on declaration.
Since that are static, no instance is needed to refer to a variable :
default interface methods
This one is new in java 8, if you prepend a method with the 'default' keyword it is not forced to be abstract and can provide a default implementation.
| default | |
|---|---|
Important
The default method was partly(mainly?) added to be able to add new methods to interfaces after distribution. Without it everyone implementing the interface would have to recompile with the new method implemented.
- a default method may only be declared within an interface, not within an (abstract) class.
- a default method must be marked with the keyword 'default', and must provide a method body.
- a default method is not assumed to be final, static or abstract, as it may be used or overridden by a class implementing the interface.
- like all methods in an interface a default method is assumed to be public and will not compile if its' private or protected.
An interface may override the default method when implementing the interface
In that case the standard overwriting rules apply (not more restrictive access, covariant return types..)
Important
An interface me declare the method abstract, forcing any lower implementations to implement the method.
default methods and multiple inheritance
This was one of my first thoughts: what about the diamond problem ? If a class implements two interfaces with the same method it depends on if the class implements that method what happens.
- there will be a compile error if it does not implement it, so the compiler cannot choose.
- it will compile if it does compile it, because then the ambiguity is removed.
static interface methods
Also new in java 8. These behave almost like static methods in classes except that they are not inherited by classes implementing the interface. You always have to use the interface name to call these methods. This is also a way to avoid multiple inheritance problems.
polymorphism
Literally it means multiple forms. In java you can assign references to object types wider then their current type.
Important
A java object may be referenced with a reference to all super classes and all super interfaces, including of course itself.
The other way around is not allowed without a cast. In this case you can see it as c-structures.
Important
In memory classes are just like structs, they get their structure from the new() call, reference are like pointers they are allowed to provides less detail (members) not more (because they are not there in memory).
- The type of an object determines it's properties in memory
- The type of the reference determines with properties are accessible to the java program. So this can never be more than in memory.
casting
You could put different types of animal in the same list by assigning them to superclass animal, but when you want your kangaroo back you are not allowed unless you use a cast.
virtual methods
Virtual methods are methods of which the implementation is not known until runtime.
Important
Every non-static, non-final and non-private method is considered a virtual method.
Virtual methods are the most important feature of polymorphism and one of the primary reasons we have class structure at all.
Important
Virtual methods behave like member variables in the object. Like a function pointer remembering which version to use. Reassigning a reference to another object type would not affect that pointer.
Note that the static version does not even need a valid object behind the reference. Note that although B.func() is inside B, this.getName() is an A structure and thus calls A.getName()..
Important
For types available outside a class like parameters and return types it is considered good practice to use the widest version (superclass or interface).
For example List is more versatile than ArrayList :
| example | |
|---|---|
Exceptions
Important
Don't use exceptional return codes like null or -1 because these can be forgotten or ignored by the caller, exceptions shout "Deal with Me !"
Two mayor types are java.lang.Error, and java.lang.Exception which are both subclasses of java.lang.Throwable. Furthermore RuntimeException is a subclass of Exception.
Important
All exceptions (all throwables) happen at runtime, otherwise it would be a compile error. You therefore can better read RuntimeException as "unchecked Exception".
- Errors mean something went horribly wrong: like StackOverflowError, you should not attempt to handle it, maybe rewrite code so it does not happen anymore.
- unchecked exceptions mean something unexpected happened but you can reasonably recover from it : accessing an invalid array index, or division by 0
- checked exception mean something happens you could have foreseen : trying to read a file that does not exist.
The last one therefore is checked at compile time that you either handle the exception or pass (throw) it on to a higher level to handle.
Type Ok for program to catch ? Program required to handle
Runtime exception Yes No Checked exception Yes Yes Error No No
try statement
The smallest form of try statement is :
Important
The try and catch blocks are also called clauses and are similar to functions in that the curly braces are required.
Important
At least try and 1 catch block are required.
The try clause is the normal programming logic and it will continue until an exception is thrown, or until the end of the block. If an exception is thrown there is a direct jump to the catch block, or the best matching catch block if there are more.
| jump | |
|---|---|
Important
Exceptions are just classes, so you have to create an instance before you can throw one.
finally
An optional clause is the finally clause.
Important
If you use finally it should always be the last clause: try{} catch() {} ... catch() {} finally {}
The finally clause is 'always' called regardless if an exception occurred.
Important
Finally is 'always' executed, with 'always' in quotes because it will not be called when you hard exit the program.
As an example :
With the return this will print :
Switch the return and the exit and it will be :
So this does imply that when return is called the compiler first visits the finally clause.
Important
You cannot put a less specific Exceptions before a more specific one in catch blocks. The compiler will not allow that and print en unreachable statement error.
throwing a second exception
You can have more try blocks nested inside all clauses, but that could sometimes lead to multiple exceptions being thrown, however only 1 (the last) is actually thrown.
Important
Only the last exception to be thrown matters !!
For instance :
This prints :
| output | |
|---|---|
- The first exception is thrown on line 7,
- and immediately caught on line 8.
- So now first the catch block runs, throwing an exception on line 10,
- and then finally runs throwing an exception on line 13
Obviously the exception on line 10 never happens, java takes the last one and removes all others.
Exception types
Runtime exceptions
| Exception | Thrown By | description |
|---|---|---|
| ArithmeticException ArrayIndexOutOfBounds |
JVM JVM | mainly : division by zero |
| ClassCast | JVM | when casting an object to a subclass of which it is not an instance |
| IllegalArgument | programmer | after parameter checks |
| NullPointerException | JVM | when trying to dereference null |
| NumberFormatException | programmer | when wrong number format is used |
checked exceptions
| Exception | Thrown By | description |
|---|---|---|
| FileNotFoundException | IO code | trying to open a nonexistent file |
| IOException | IO code | problems trying to read or write a file |
errors
| Error | Thrown By | description |
|---|---|---|
| ExceptionInIntialzeError | JVM | when a static initializer throws an exception java can't start using it |
| StackOverflowError | JVM | normally a recursion error |
| ClassNotFoundError | JVM | a class was found at compile time but not at runtime |
subclasses
When a class overrides a method from a superclass, or implements a method from an interface, it may not add new checked exceptions to that overridden method.
Important
I think this is a java design flaw since more detailed classes are bound to encounter more exception types. You will now have to add any new exception up along the class hierarchy.
Important
Exceptions thrown by overridden methods may only become more specific on the way down, never broader.
Important
This means every exception in the exception list has to be a subclass of the parents exception list. The exception list of the subclass may be shorter or absent.