0% found this document useful (0 votes)
162 views

Java Fundamentals PDF

This document provides an overview of Java fundamentals including programming paradigms, languages, the Java Virtual Machine, Java Runtime Environment, Java Development Kit, class structure, modifiers, OOP principles like encapsulation, inheritance, polymorphism and composition, interfaces, abstract classes, nested classes, annotations, enums, stack and heap memory, garbage collection, classpath, data types, operators, flow control, string operations and the string pool. It covers the core concepts needed to understand the Java programming language.

Uploaded by

Mari Marian
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
162 views

Java Fundamentals PDF

This document provides an overview of Java fundamentals including programming paradigms, languages, the Java Virtual Machine, Java Runtime Environment, Java Development Kit, class structure, modifiers, OOP principles like encapsulation, inheritance, polymorphism and composition, interfaces, abstract classes, nested classes, annotations, enums, stack and heap memory, garbage collection, classpath, data types, operators, flow control, string operations and the string pool. It covers the core concepts needed to understand the Java programming language.

Uploaded by

Mari Marian
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 106

“The secret of getting ahead is getting started.

” -Mark Twain
Java fundamentals

● Programming paradigms
● Machine code
● Procedural languages
● Object­oriented programming

● Programming languages

● Compiled
● Interpreted
Java fundamentals

● Java Virtual Machine
● abstract computing machine that enables a computer to run a 

Java program

● Java Runtime Environment (JRE)
● software package that contains what is required to run a Java 

program
● includes a Java Virtual Machine implementation together with 

an implementation of the Java Class Library

● Java Development Kit (JDK)
● is a superset of a JRE and contains tools for Java 

programmers
● javac

● jar
Java fundamentals

Execution flow
Java class

● template for creating objects with certain state and 
behaviour

● has state and behaviour (methods) which operates on the 
state

● objects are instances of the class, usually creted with 
the new java keyword

● naming conventions

● Class structure
● Fields

● Constructors

● Methods

● return / void
● Static blocks
Java class
Java modifiers

● access modifiers
● public
● protected
● default
● private

● non access modifiers
● abstract
● final
● static
● synchronized
Java modifiers
OOP principles

● Encapsulation

● Data Abstraction

● Inheritance

● Polymorphism
00P principles

● Composition in Java

● has­a relationship

● code reuse

● hide visibility to client classes
00P principles
Composition
OOP principles

● Inheritance in Java
● is­a relationship

● extends keyword

● final keyword

● code reusability

● subclass and superclass

● inheritance with access modifiers

● no multiple inheritance with classes

● type casting – upcasting & downcasting

● instanceof keyword

● overriding methods

● super keyword

● constructors and inheritance

● fields and inheritance
OOP principles
OOP principles
OOP principles

● Inheritance vs. Composition

● Advisable is to use composition versus inheritance 
because:

● inheritance makes code fragile to changes

● inheritance is flawed – we expose all the super class 
methods (including the flawed ones) to the client
 
● composition offers greater flexibility in invoking 
the methods 
● diamond problem

● Composition implies easy unit testing (easy mocking)
“Tell me and I forget, teach me and I may remember, involve me and I learn.”
– Benjamin Franklin
Interface

● interface keyword

● a way to achieve abstraction (vs. implementation)

● defines the contract that classes must implement(what vs. how)

● is default public and abstract

● all the interface's methods are public and abstract

● all the interface's attributes are public, static and final 
(constants)

● multiple inheritance

● implements keyword

● good for defining types and top level hierarchy
Interface
Abstract class

● similar to interface, but also having methods with 
implementation

● abstract keyword

● provides skeletal implementation (common methods, default 
implementation)

● no instantiation

● the subclass of abstract class must implement all the abstract 
methods unless the subclass is also an abstract class.

● can implement interfaces without even providing the 
implementation of interface methods.

● we can run abstract class like any other class if it has 
main() method.
Abstract class
Abstract class vs. Interface
● abstract vs. interface

● implements vs. extends

● abstract classes can have methods with implementation whereas 
interface provides absolute abstraction and can’t have any 
method implementations

● abstract classes can have constructors but interfaces can’t 
have constructors

● subclass can extend only one abstract class but it can 
implement multiple interfaces.

● abstract classes can extend other class and implement 
interfaces but interface can only extend other interfaces.

● we can run an abstract class if it has main() method but we 
can’t run an interface because it can’t have main method 
implementation.

● interface is usually a better idea than abstract lass
● BUT, it's easier to evolve an abstract class.
● Nested classes

● 4 types :
● static nested class

OuterClass.StaticNestedClass nestedObject =
     new OuterClass.StaticNestedClass();
● inner class
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new 
InnerClass();
● local inner class
● defined in a method body
● local anonymous class
● local inner class without a body 
● always extends a class or implements an interface
● not possible to define a constructor for such a class
Annotation

● 3 built­in annotations : 

● @Override 

● @Deprecated

● @SuppressWarnings
Annotation

● Introduced in Java 1.5
● metadata about the program contained in the program itself
● can be parsed by a compiler or by an annotation parsing tool
● it's definition is similar with the definition of an interface
● annotation methods can’t have parameters
● annotation methods return types are limited to primitives, String, 
Enums, Annotation or array of these
● annotation methods can have default values
● annotations can have meta annotations attached to them
● @Documented – indicates that elements using this annotation should be 
documented by javadoc and similar tools
● @Target – indicates theprogram element to which an annotation type is 
applicable. Some possible values are TYPE, METHOD, CONSTRUCTOR, FIELD 
etc. If Target meta­annotation is not present, then annotation can be 
used on any program element.
● @Inherited – indicates that an annotation type is automatically 
inherited. 
● @Retention – indicates how long annotations with the annotated type 
are to be retained. It takes RetentionPolicy argument whose possible 
values are SOURCE, CLASS and RUNTIME
Annotation
Enum
● enum keyword
● introduced in Java 1.5
● type which consists of fixed sets of constants
● implicitly extends java.lang.Enum class that 
extends Object class and implements Serializable 
and Comparable interfaces
● can implement interfaces
● it's constructors are always private
● can't construct instances of enum using new 
operator
● can define abstract methods in enums and enum 
fields can implement it
● can define a method in enum and enum fields can 
override it
● can be used in switch statement
● enum fields are constants so they are static and 
final
Enum
“The way to get started is to quit talking and begin doing.”– Walt Disney
Stack and heap

● Heap memory is used by java runtime to allocate 
memory to Objects and JRE classes

● Java Stack memory is used for execution of a thread

● Java Stack memory contains method specific values 
that are short­lived and references to other 
objects in the heap that are getting referred from
the method
Garbage collection

● Automatic garbage collection is the process of 
looking at heap memory,identifying which objects 
are in use and which are not, and deleting the
unused objects.
Classpath

● The classpath tells Java where to look in the 
filesystem for files defining classes.

● windows
● java ­classpath ".;c:\mylib*" com.example.MyApp

● linux
● java ­classpath '.:/mylib/*' MyApp

● jar files

● jar files

● manifest file
● Main­Class: org.mypackage.HelloWorld

● Class­Path: lib/supportLib.jar
Data types and operators
Data types and operators
Data types and operators
Data types and operators
Flow control

● if/else
● switch
● do while
● while
● for
● for each
● break
● continue
“It’s not that I’m so smart, it’s just that I stay with problems longer.” – Albert Einstein
String operations

● String is immutable (and therefore secured for 
modifications and thread safe)

● It's hashcode is calculated at the time of the 
creation and it doesn't need to be calculated again
● very good candidate for Map key

● As a paranthesis
● classes should be immutable unless there’s a very 

good reason to make them mutable
● Immutable objects are good for caching and are 

thread­safe
● If a class cannot be made immutable, limit its 

mutability as much as possible
How to implement an immutable class?

● declare the class as final so it can’t be extended.

● make all fields private so that direct access is not allowed.

● don’t provide setter methods for variables

● make all mutable fields final so that it’s value can be 
assigned only once.

● initialize all the fields via a constructor performing deep 
copy.

● perform cloning of objects in the getter methods to return a 
copy rather than returning the actual object reference.
String operations

String pool
String operations

● subString & subSequence (CharSequence interface) methods

● compareTo (Comparable interface) & compareToIgnoreCase methods

● toCharArray, charAt, getChars methods

● split method and regular expressions

● getBytes method

● toCharArray method

● format method

● + concatenation operator

● StringBuilder & StringBuffer
Regular expressions 

● java.util.regex package

● Pattern: 
● Pattern object is the compiled version of the regular 

expression. 
● Pattern class doesn’t have any public constructor and we use 

it’s public static method compile to create the pattern 
object by passing regular expression argument.

● Matcher:
●  Matcher is the java regex engine object that matches the 

input String pattern with the pattern object created.
●  Matcher class doesn’t have any public constructor and we get 

a Matcher object using pattern object matcher method that 
takes the input String as argument. 
● We then use matches method that returns boolean result 

based on input String matches the regex pattern or not.

● PatternSyntaxException: 
● PatternSyntaxException is thrown if the regular expression 

syntax is not correct.
arrays

● container which can hold a fixed number of elements of the 
same type
● can be one­dimensional or multi­dimensional
● array initialization
● array memory allocation
● copy arrays (full & partial copy)
● Object.clone()

● System.arraycopy()

● Arrays.copyOf()

● Arrays.copyOfRange()

● Arrays utility class 
● Arrays.sort()

● Arrays.toString()

● Varargs 
● only one varargs in the method

● only the last argument of a method can be varargs.

● according to java documentation, we should not overload a 

varargs method
● don't use varargs as a substitute for array, use varargs only 

when a variable number of parameters is needed
arrays

int[] testScores = new int[4];


arrays

int[] testScores = new int[4];


arrays
“Start by doing what’s necessary; then do what’s possible; and suddenly you are doing the impossible.”
– Francis of Assisi
Java Generics
● Introduced in Java 1.5

● Compile­time checking (type­safe, removes risk of 
ClassCastException at runtime)

● Type erasure at runtime

● @SuppressWarnings("rawtypes") – used only when type­safety is 
implied

● Terminology
● Parameterized type: List<String>

● Actual type parameter: String

● Generic type: List<E>

● Formal type parameter: E

● Unbounded wildcard type: List<?>

● Raw type: List

● Bounded type parameter: <E extends Number> (upper bounded 

by Number), <T super A> (lower bounded by A), <T extends A 
& B & C>
● Recursive type bound: <T extends Comparable<T>> 

● Bounded wildcard type: List<? extends Number>

● Generic method static: <E> List<E> asList(E[] a) 

● Type token: String.class
Java Generics

● Naming convention:

● E – Element (used extensively by the Java 
Collections Framework, for example ArrayList, 
Set etc.)
● K – Key (Used in Map)
● N – Number
● T – Type
● V – Value (Used in Map)
● S,U,V etc. – 2nd, 3rd, 4th types
Java Generics

● Java generics and inheritance
●  not allowed to assign TestClass<String> variable to 

TestClass<Object> variable
● TestClass<String> parent is Object

● Java Generic Classes and Subtyping
● we can subtype a generic class or interface by 

extending or implementing it
● interface TestList<E,T> extends List<E>{}

● Subtyping using Generics Wildcard
● List<? extends Integer> intList = new ArrayList<>();

● List<? extends Number>  numList = intList;   
Java Generics

● Restrictions   
● Can't have static field of type T

public class GenericsExample<T>
{
   private static T member; //This is not allowed
}

● Can't create instance of T
public class GenericsExample<T>
{
   public GenericsExample(){
      new T();
   }
}
● Generics are not compatible with primitives in declarations
final List<int> ids = new ArrayList<>();    //Not allowed 
● final List<Integer> ids = new ArrayList<>(); //Allowed

● Can’t create generic exception class
// causes compiler error
● public class GenericException<T> extends Exception {
Java Generics

● PECS – Producer Extends Consumer Super   

● Use the <? extends T> wildcard if you need to 
retrieve object of type T from a collection. 
(Producer Extends)

● Use the <? super T> wildcard if you need to put 
objects of type T in a collection. (Consumer 
Super)

● If you need to satisfy both things, don’t use any 
wildcard.
Java Generics
Java Collections
● Collections are containers that group objects known as elements
● Java Collections framework consists of :
● Interfaces
● java.util.Collection : root interface
● java.util.List, java.util.Set, java.util.SortedSet java.util.Queue, 
java.util.Dequeue java.util.Map, java.util.SortedMap
● java.util.Iterator, java.util.ListIterator
● Implementations
● java.util.ArrayList, java.util.LinkedList, java.util.HashMap, 
java.util.TreeMap, java.util.HashSet, java.util.TreeSet
● java.util.concurrent.CopyOnWriteArrayList, 
java.util.concurrent.ConcurrentHashMap, 
java.util.concurrent.CopyOnWriteArraySet
● Algorithms
● java.util.Collections
● sorting
● shuffling
● searching
● frequency
● disjoint
● min
● max
● java.util.Arrays
● Synchronized wrappers
Java Collections
Java Collections
Java Collections
Java Collections
“Energy and persistence conquer all things.”– Benjamin Franklin
Java I/O

● InputStream – abstract class, is the superclass of all classes representing
 an input stream of byte
● FileInputStream
● ByteArrayInputStream
● GZIPInputStream
● OutputStream ­ abstract class is the superclass of all classes representing
an output stream of bytes
● FileOutputStream 
● ByteArrayOutputStream
● GZIPOutputStream
● Reader – abstract class for reading character streams
● BufferedReader
● InputStreamReader
● FileReader
● Writer ­ abstract class for writing to character streams
● BufferedWriter
● PrintWriter
● FileWriter
● Scanner ­ simple text scanner which can parse primitive types and strings using 
regular expressions
● RandomAccessFile
● File
● Nio
● Files
● Path
● Paths
Java I/O
Java I/O
Java I/O
Java I/O
Java I/O

Recursively delete a directory using java.nio Files and Path classes
Java Exceptions
Java Exceptions

● Keywords
● throw
● throws
● try­catch
● finally
● @throws
Java Exceptions

● Catch multiple exceptions
catch(IOException | SQLException | Exception ex){
     logger.error(ex);
     throw new MyException(ex.getMessage());
}

● try with resources
Java Exceptions
Java Reflection

● Introspection
● Class

● Constructor

● Method

● Field
Java Reflection
Java Reflection
Java Reflection
Java Reflection
Java Reflection
Java Reflection
“Believe you can and you’re halfway there.” - Theodore Roosevelt
Java multi­threading

● Process

● A process is a self contained execution environment and it 
can be seen as a program or application.

● It cannot directly access shared data in other processes. 

● The resources of the process, e.g. memory and CPU time, are 
allocated to it via the operating system. 

● Thread

● A thread is a so called lightweight process. 

● It has its own call stack, but can access shared data of 
other threads in the same process.

● Every thread has its own memory cache. If a thread reads 
shared data it stores this data in its own memory cache.
Java Threads

● Runnable vs. Thread

● Base unit for concurrency in Java is java.lang.Thread class.

● A thread executes an object of type java.lang.Runnable.
●  Runnable represents the task to be done.

● Thread represents the worker who performs the task.
Thread states
Java Threads

● Disadvantages for using Thread class directly:

● Creating a new thread is resource cosuming causing 
performance overhead

● Too many threads can lead to reduced performance, as the 
CPU needs to switch context between these threads.

● You may run into out of memory errors due to too many 
threads.

● The solution? ­ Thread pools with the Executor 
framework
Concurrency in Java

● Locks and thread synchronization

● Java provides locks to protect certain parts of the code to 
be executed by several threads at the same time. 

● The simplest way of locking a certain method or 
block of code is using the synchronized keyword.

● The synchronized keyword in Java ensures:

● that only a single thread can execute a block of code at 
the same time

● that each thread entering a synchronized block of code 
sees the effects of all previous modifications that were 
guarded by the same lock
Concurrency in Java

● Locks and thread syncronization

● Syncronized method
public synchronized void addElement(Integer element){
System.out.println("Add element: " + element);
if(element != null){
elements.add(element);
}
System.out.println(elements);
}

● Syncronized block
public void addElement2(Integer element){
System.out.println("Add element : " + element);
synchronized(mutex){
if(element != null){
elements.add(element);
}
System.out.println(elements);
}
}
Deadlock
Deadlock
Concurrency in Java

● Volatile

● If a variable is declared with the volatile keyword then it 
is guaranteed that any thread that reads the field will see 
the most recently written value.

● The volatile keyword will not perform any mutual exclusive 
lock on the variable.

● Not feasible for read – update – write operations (for 
these one use atomic types, eg. AtomicInteger, AtomicLong 
etc.)
Concurrency in Java

● Immutability

● The simplest way to avoid problems with 
concurrency is to share only immutable data 
between threads.

● Immutable data is data which cannot changed.
Java multi­threading

● Non­blocking algorithms

● Java 5.0 provides supports for additional atomic 
operations.

● This allows to develop algorithm which are non­blocking 
algorithm, e.g. which do not require synchronization, but 
are based on low­level atomic hardware primitives such as 
compare­and­swap (CAS). A compare­and­swap operation check 
if the variable has a certain value and if it has this 
value it will perform this operation.

● Non­blocking algorithms are typically faster than blocking 
algorithms, as the synchronization of threads appears on a 
much finer level (hardware).

● Hazards like priority inversion and deadlock are avoided, 
contention is less expensive, and coordination occurs at a 
finer level of granularity, enabling a higher degree of 
parallelism and higher throughput.
Java multi­threading
● Atomic variables

● java.util.concurrent.atomic package 

● The atomic variable classes all expose a compare­and­set primitive 
(similar to compare­and­swap), which is implemented using the 
fastest native construct available on the platform 

● Nine flavors of atomic variables are provided:
● AtomicInteger
● AtomicLong
● AtomicReference
● AtomicBoolean
● array forms of atomic integer, long, reference
● AtomicReference
● AtomicStampedReference

● Can be higher­performance replacement for shared counters, sequence 
number generators, and other independent shared variables that 
otherwise would have to be protected by synchronization.

● The classes in java.util.concurrent (e.g ConcurrentLinkedQueue, 
ConcurrentHashMap) are in turn built on these low­level atomic 
variable facilities 
Java multi­threading
● Atomic variables

● java.util.concurrent.atomic package 

● The atomic variable classes all expose a compare­and­set primitive 
(similar to compare­and­swap), which is implemented using the 
fastest native construct available on the platform 

● Nine flavors of atomic variables are provided:
● AtomicInteger
● AtomicLong
● AtomicReference
● AtomicBoolean
● array forms of atomic integer, long, reference
● AtomicReference
● AtomicStampedReference

● Can be higher­performance replacement for shared counters, sequence 
number generators, and other independent shared variables that 
otherwise would have to be protected by synchronization.

● The classes in java.util.concurrent (e.g ConcurrentLinkedQueue, 
ConcurrentHashMap) are in turn built on these low­level atomic 
variable facilities 
Java multi­threading
Fork­Join framework

● Hardware trends drive programming idioms
● In 1995 threads were used primarily for expressing asynchrony, 
not concurrency,and as a result the synchronization primitives 
like synchronized, or volatile and classes such Thread were 
sufficient.

● In Java 5, the java.util.concurrent package was added to the Java 
platform, providing a set of useful components for building 
concurrent applications: concurrent collections, queues, 
semaphores, latches, thread pools, and so on. 
● These were ment to exploit the hardware parallelism of 
multiprocessor system which were starting to emerge.

● Suited for coarse­grain parallelism, using the processing of a 
single request as the unit of work in a web server, mail 
server, or database server.

● In Java 7, the fork­join framework addresses the problem of fine­
grained parallelism for the new multi­core processors.

● In Java 8 we have parallel stream
Fork­Join framework

● Divide and conquer

Result solve(Problem problem) { 
    if (problem.size < SEQUENTIAL_THRESHOLD)
        return solveSequentially(problem);
    else {
        Result left, right;
        INVOKE­IN­PARALLEL { 
            left = solve(extractLeftHalf(problem));
            right = solve(extractRightHalf(problem));
        }
        return combine(left, right);
    }
}

● Fork­join uses decomposition because executing a task forks 
(starts) multiple subtasks and then joins (waits for 
completion) with them.
Fork­Join framework
Fork­Join framework

● java.util.concurrent.ForkJoinPool ­ special thread pool which is 
designed to work well with fork­and­join task splitting
● All its threads are in daemon mode, no need to shutdowm

ForkJoinPool pool = new ForkJoinPool(numberOfProcessors);

where numberOfProcessors = 
Runtime.getRunTime().availableProcessors();

● There are three different ways of submitting a task to the 
ForkJoinPool:
● execute() 

● invoke()

● submit()

● ForkJoinTask ­ abstract class for creating tasks that run within 
a ForkJoinPool
● RecursiveAction (does't return result)

● RecursiveTask (returns a result)
Thread pools and Executor framework

● Thread pools

●  Manage a pool of worker threads

●  Contains a work queue which holds tasks waiting to 
get executed (Runnable objects)

● Executor

● An object that executes submitted Runnable tasks.

● This interface provides a way of decoupling task 
submission from the mechanics of how each task will be 
run, including details of thread use, scheduling, etc.

● new Thread(new(RunnableTask())).start()
vs.
● Executor executor = anExecutor;
executor.execute(new RunnableTask());
Thread pools and Executor framework

● ExecutorService

● An Executor that provides methods to manage termination and 
methods that can produce a Future for tracking progress of 
one or more asynchronous tasks.

● shutdown method will allow previously submitted tasks to 
execute before terminating

● shutdownNow method prevents waiting tasks from starting 
and attempts to stop currently executing tasks. Upon 
termination, an executor has no tasks actively executing, 
no tasks awaiting execution, and no new tasks can be 
submitted

● submit method extends base method 
Executor.execute(Runnable) by creating and returning a 
Future that can be used to cancel execution and/or wait 
for completion. 
Thread pools and Executor framework

● ScheduledExecutorService

● An ExecutorService that can schedule commands to run after a 
given delay, or to execute periodically.

● The schedule methods create tasks with various delays and 
return a task object that can be used to cancel or check 
execution. 

● The scheduleAtFixedRate and scheduleWithFixedDelay methods 
create and execute tasks that run periodically until 
cancelled.
Thread pools and Executor framework

● Executors – class which defines utility methods for 
Executor, ExecutorService, ScheduledExecutorService, 
ThreadFactory classes

● create and return an ExecutorService set up with commonly 
useful configuration settings.
● newFixedThreadPool

● newCachedThreadPool

● newSingleThreadExecutor

● create and return a ScheduledExecutorService set up with 
commonly useful configuration settings.
● newScheduledThreadPool

● newSingleThreadScheduledExecutor

● create and return a ThreadFactory that sets newly created 
threads to a known state.
● defaultThreadFactory

● privilegedThreadFactory
Thread pools and Executor framework
Futures and Callables

● java.util.concurrent.Callable – interface similar to java.lang.Runnable, 
in that both are designed for classes whose instances are potentially 
executed by another thread.

● Single method : V call() throws Exception;

● The Executors class contains utility methods to convert from other 
common forms to Callable classes.

● java.util.concurrent.Future ­ represents the result of an asynchronous 
computation.

● Methods are provided to check if the computation is complete, to wait 
for its completion, and to retrieve the result of the computation.

● The result can only be retrieved using method get when the 
computation has completed, blocking if necessary until it is ready.

● Cancellation is performed by the cancel method. 

● On the Executor you can use the method submit to submit a Callable 
and to get a Future. To retrieve the result of the future use the 
get() method.
Futures and Callables
Futures and Callables
CompletableFuture
● Limitation with java.util.concurrent.Future : you can't register a callback 
method, once the Callable is finished (you can extract only the result)

● CompletableFuture
● extends the functionality of the Future interface for asynchronous calls.
● implements the CompletionStage interface.
● CompletionStage
● A stage of a possibly asynchronous computation, that performs an action or 
computes a value when another CompletionStage completes. 

● A stage completes upon termination of its computation, but this may in turn 
trigger other dependent stages.

● The computation performed by a stage may be expressed as a Function, Consumer, 
or Runnable  (using methods with names including apply, accept, or run, 
respectively) depending on whether it requires arguments and/or produces 
results.

● One stage's execution may be triggered by completion of a single stage, or 
both of two stages, or either of two stages (combine or either)

● execution of a new stage's computations may be arranged in any of three ways: 
default execution, default asynchronous execution (using methods with suffix 
async that employ the stage's default asynchronous execution facility), or 
custom (via a supplied Executor)

● Provides methods that can handle both normal and exceptional termination
handle, for functions that take a value and a Throwable and return a value;
whenComplete, for functions that take a value and a Throwable and return 
void.
CompletableFuture
“It always seems impossible until its done.” -Nelson Mandela

You might also like