Head First Java, 2nd Edition

Chapter 1 – Breaking the Surface

  • Java is alluring because of the “write-once, run anywhere” principle
  • Works by compiling source code into bytecode, the Java Virtual Machine (JVM) runs this bytecode
  • Java 1.02 (applets) -> Java 1.1 (better GUI code) -> Java 2 (includes MicroEdition J2ME, Standard Edition J2SE, and Enterprise Edition J2EE) -> Java 5 (more power and easier to develop with) -> Java 6 (more features to J2SE and J2EE) -> Java 7 (improvements like using String in switch statement, multiple exception catching) -> Java 8 (forEach method in Iterable interface, functional interfaces and lambda expressions)

Chapter 2 – Classes and Objects

  • The benefits of object-oriented programming include flexibility and extensibility
  • When classes share a common functionality, the features can be put into a superclass and then be inherited by the subclasses (Shape can be your superclass, and then Square, Circle, and Triangle are all subclasses of Shape)
  • Subclasses can override methods in the superclass, defining a unique behavior that is specific to that particular class
  • When designing classes, think of what the object should know (instance variables) and what the object should do (methods)
  • A class is not an object, but is used to construct them; a class is a blueprint for an object

Chapter 3 – Primitives and References

  • Variables must have a type, and can be primitive or object reference
  • Local variables are declared within a method
  • Arguments are values sent to a method and return types are values sent back to the caller of the method
  • Primitive types are byte, short, int, long, float, double, boolean, and char
  • There is no such thing as an object variable, only an object reference variable; doesn’t hold the object itself, but rather something like a pointer or address that represent a way to access an object
  • When writing “Dog myDog = new Dog();” the JVM allocates space for a reference variable of type Dog, creating an object on the heap, and assigns the Dog object to the reference variable
  • “Book book2 = book1;” declares a new book reference variable, but not a new object, assigning the value of the variable book2 to the value of variable book1 (assuming object book2 already exists)
  • When an object has no references, there is eligibility for garbage collection
  • Arrays are always objects

Chapter 4 – Methods Use Instance Variables

  • Objects have state (instance variables) and behavior (methods)
  • A method uses parameters and a caller passes arguments
  • Java is pass-by-value, that means pass-by-copy
  • A method doesn’t change the original variable that was passed in, rather the method manipulates a copy of the variable
  • Encapsulation is where data is secured in classes, can be done by declaring instance variables as private, and then using getter and setter methods to access them
  • Instance variables always get a default value if one is not explicitly assigned to them, can be 0, false, or null
  • Instance variables are declared inside a class but not within a method, while local variables are declared within a method
  • To compare two primitives (check for same value) and two references (check for same object), use the “==” operator

Chapter 5 – Writing a Program

  • A for loop initializes, does a boolean test, and finally iterates
  • A while loop is good for when you don’t know how many times to loop but have to keep going until a condition is met
  • “int x = 0;       int z = ++x” results in x and z being 1
  • “int x = 0;       int z = x++” results in x being 1 and z being 0, because z gets assigned the value of x and then x is incremented
  • An enhanced for loop can be written as “for (String name : nameArray)” to iterate through all items in the nameArray collection

Chapter 6 – Get to Know the Java API

  • The Java library is known as the Java API
  • To use a Java API you need to know which package the class is in and then import the library
  • One useful class in the library is the ArrayList, which has “add”, “remove” (by index and by element), “contains”, “isEmpty”, “indexOf”, “size”, and “get” functions
  • Boolean operators are && (AND) and || (OR) along with != (not equals)
  • && and || are short circuit operators, meaning once determined if the left side of a && is false, the JVM won’t bother checking the right side, and in a similar fashion if with a || comparison the left hand side is true the JVM won’t bother checking the right side because the condition was satisfied
  • The & and | operators are non short circuit operators, meaning they force the JVM to check both sides of the expression

Chapter 7 – Inheritance and Polymorphism

  • When you use inheritance you put common code in a class (superclass) and then have subclasses extend the functionality (using the extends keyword) so that the subclasses can inherit methods of the superclass
  • The subclass inherits members of the superclass, including instance variables and methods
  • To design a superclass, look for what all objects have in common and how they are related
  • Use the “IS-A” relationship to check if one item should extend another, Triangle IS-A Shape, thus verifying that Triangle can be a subclass of Shape
  • Use the “HAS-A” relationship to organize related classes, since Bathroom HAS-A Tub, then you should create a Bathroom class with a Tub instance variable and a separate Tub class, keep in mind that Bathroom DOES NOT extend the Tub class
  • To call the methods of a superclass from a subclass, use the “super” keyword
  • public members are inherited and private members are not inherited
  • Inheritance allows you to avoid duplicated code and define a common protocol for a group of classes
  • With polymorphism, the reference and the object can be different, such as Animal myDog = new Dog(); , showing a reference variable of type Animal but an object created is a Dog
  • Polymorphism allows the reference type to be a superclass of the object type, since Animal is the superclass of Dog, the above example works
  • You can have polymorphic arguments and return types, methods can take a superclass as a parameter (say, Animal) but you can pass in subclass objects such as a Dog or Cat
  • Polymorphism allows you to write code that doesn’t have to change when a new subclass is introduced
  • When overriding methods of a superclass from a subclass, the arguments must be the same and the return types must be compatible
  • When overloading methods, you can make multiple versions of a method with different argument lists and the compiler will know which method to call based on how you call the method
  • Overloading allows the return type to be different, but you can’t only change the return type, must change the the method parameters

Chapter 8 – Interfaces and Abstract Classes

  • You can use an abstract class to prevent a class from being instantiated, so you cannot create a new object of that type
  • Concrete classes are specific enough to be instantiated
  • An abstract class’ main value is to be extended
  • An abstract method means the method must be overridden, and has no body so that subclasses can define their own unique implementation
  • An abstract method must be defined in an abstract class
  • Every class in Java extends the Object class
  • The Object class has the following methods: equals (compare objects), getClass (return class of object), hashcode (prints unique object hash, a sort of id that every object has), and toString (prints a String pertaining to the object’s memory)
  • The compiler decides whether you can call a method based on the reference type, not the actual object type
  • You can cast the class type onto an Object so that you can use the methods of that class, you can ensure the correct class by using the instanceof operator
  • The way an interface works in Java is like a 100% pure abstract class, you can think of all methods in an interface to be abstract, meaning any subclass that implements the interface has to implement all methods defined in the interface
  • Since all interface methods are abstract, they have no body
  • A class can implement multiple interfaces, separated by a comma
  • Make a class that doesn’t extend anything when your class doesn’t pass the IS-A test for any type, make a subclass when you need to make a more specific version of a class, use an abstract class when you want to define a template for a group of subclasses with implementation code that all subclasses can use…also for when nobody should make objects of that, and use an interface when you want to define a role that other classes can play, no matter where they are in the inheritance tree
  • One way to make abstract classes is to have methods with some set-up code defined, and then the subclasses that will extend this abstract class can use the super keyword to call that initial setup in their overridden method, and finally follow up with code for their own implementation

Chapter 9 – Constructors and Garbage Collection

  • The stack is where method calls and local variables live
  • The heap is where all objects live
  • Instance variables are variables declared inside a class, but not within any method
  • Local variables are declared inside a method, including method parameters
  • When you call a method, the method lands on the top of the stack…the method at the top of the stack is always currently running
  • All objects live on the heap, regardless whether the reference is a local or instance variable
  • When a new object has instance variables that are object references rather than primitives, Java makes space only for the reference variable, until the actual instance variable object is created
  • An object is declared (the reference variable type and name, “Dog dog”), created (“new Dog()”), and assigned (“=”)
  • A constructor is code that runs when you create a new object, instantiates the object
  • If you don’t have a no-argument constructor, Java supplies a default one, however if you do have a constructor that has arguments, then you must make the no-argument constructor yourself
  • If you have multiple constructors (overloaded), then the argument list must differ in order and/or types of the variables
  • When a new sub-class object is created, then one object on the heap is created but it contains instance variables of the subclass and of all superclass instance variables
  • All constructors in an object’s inheritance tree must run when you create a new object
  • When a constructor runs, it calls its superclass constructor all the way up to class Object constructor, constructor chaining
  • The compiler always puts a call to super() in every constructor, but it has to be the first statement in your constructor if written explicitly
  • You can use the keyword this() to call a constructor from another overloaded constructor in the same class, can only be used in a constructor, and must be the first statement
  • “this” refers to the current object
  • A constructor can have a call to super() or this(), but not both
  • A local variable lives only within a method, and an instance variables lives as long as the object does
  • Garbage collection automatically destroys eligible objects when your program gets low on memory
  • An object becomes eligible for GC when its last live reference disappears: when reference goes out of scope (a local variable’s method ends), when assigned to another object, and when explicitly set to null

Chapter 10 – Numbers and Statics

  • The Math class doesn’t have any instance variables, and because the methods are “static“, you don’t need to have an instance of Math
  • A static method means “behavior is not dependent on the instance variable, so no instance/object is required”
  • You can prevent instantiating a class by marking the constructor as private
  • Static methods can’t use non-static instance variables and non-static methods
  • A variable declared as static has the same value for all instances of the classes
  • A variable declared as final cannot change its value
  • Static final variables are constants
  • A final method means you can’t override the method and a final class means you can’t extend the class

Chapter 11 – Exception Handling

  • One method can catch what another method throws, the method that throws has to declare that it might throw the exception
  • Put the throws keyword on the same line as the method declaration
  • Catch the exception by use a try-catch block
  • The compiler cares about ‘checked exceptions‘, basically anything other than RuntimeExceptions
  • A finally block runs regardless of an exception
  • You can run exception prone code without a try-catch block by declaring that the method throws an exception

Chapter 12 & 13 – Events, Graphics, and Swing

  • A GUI starts with a window called a JFrame, which you can add widgets to (buttons, text fields, etc.)
  • To know when a user clicks or takes an action on a button/field, you need to listen for a GUI event
  • An inner class can use the outer class’s variables and methods, even if they are private
  • Layout managers control the size and location of components nested within other components
  • The BorderLayout lets you add components in one of five regions: NORTH, SOUTH, EAST, WEST, CENTER
  • The FlowLayout places components left to right, top to bottom, in the order they were added
  • The BoxLayout lets you align components stacked vertically

Chapter 14 – Serialization and File I/O

  • You can save an object’s state using serialization, by using the ObjectOutputStream package
  • Connection streams can represent a connection to a source or destination: files, network sockets, or the console
  • To serialize an object to a file, using FileOutputStream chained to an ObjectOutputStream
  • To serialize an object, call writeObject(Object) and to read objects readObject()
  • The return type of readObject() is of type Object, so deserialized objects must be cast to their real type
  • To be serialized, an object must implement the Serializable interface
  • Mark instance variables with the transient keyword to skip serialization for them
  • Static variables are not serialized, because all objects of that type share only a single value

Chapter 15 – Networking and Threads

  • Client and server applications communicate over a Socket connection
  • A Socket represents a connection between two applications
  • A client must know the IP (or domain name) and TCP port number of the server
  • A TCP port is a 16-but unsigned number assigned to a server application, allowing for different clients to connect to the same server
  • The port numbers from 0 to 1023 are reserved for services such as HTTP, FTP, SMTP, etc.
  • Once connected, a client can get input and output streams from the socket
  • To read text data from the server, create a BufferedReader chained to an InputStreamReader
  • To write text data to the server, create a PrintWriter chained directly to the Socket’s output stream
  • Servers use a ServerSocket that waits for client requests on a particular port number
  • When a ServerSocket gets a request, it accepts the request by making a Socket connection with the client
  • Java has multi-threading built into the language, you can create a separate thread of execution with its own call stack
  • To launch a new thread make a Runnable object (the thread’s job), a thread object (the worker) that has the Runnable as an argument (the job), and finally start the thread
  • The Runnable Interface has just a single method, run(), which goes on the bottom of the new call stack
  • A thread is in the NEW state when you have instantiated a Thread object, in the RUNNABLE state when you call the start method, and RUNNING when the JVM’s thread scheduler has selected it to be the currently running thread
  • A thread can be moved from RUNNING to BLOCKED because it’s waiting for data, gone to sleep, or is waiting for an object’s lock
  • Thread scheduling is not guaranteed to work in a way where threads will take turns nicely, but you can influence turn-taking by putting threads to sleep periodically
  • You can have serious problems with threads if two or more threads have access to the same object on the heap, leading to data corruption
  • To make objects thread-safe, decide which methods run to completion before another thread enters the method on the same object
  • Use the keyword synchronized to modify a method declaration, to prevent two threads from entering that method
  • When a thread wants to enter a synchronized method, the thread must get the key for the object, if the key is not available (because another thread is using it) then the thread goes into a waiting mode until the key is available

Chapter 16 – Collections and Generics

  • Java has the following collections besides ArrayList: TreeSet (all elements sorted and prevents duplicates), HashMap (stores elements in key/value pairs), LinkedList (better performance when inserting or deleting from the middle of the collection), HashSet (prevents duplicates and can search for elements quickly), and LinkedHashMap (like regular HashMap, but order in which elements were inserted)
  • Lists are for when sequence matters, Sets are for uniqueness matters, and Maps are for when finding something by key matters
  • You can create generic classes, variables, and methods
  • A generic class is declared as “public class example_class<T>” , where <T> is the placeholder for the real type you use when you declare and create the class
  • A generic method is declared as “public void example_method(T data)”
  • If the type parameter was not declared in the class declaration you must do “public <T extends Animal> void example_method(T data)”, which says that T can be any type of Animal
  • The above is different than just taking in an “ArrayList<Animal>” in the method parameters because this means only an ArrayList of type Animal is valid, not ArrayList<Dog>, ArrayList<Cat>, etc. unless you use a wildcard (however for regular arrays, this is valid)
  • The Map interface doesn’t extend the Collection interface, but is still considered to be part of the “Collections Framework”
  • Reference equality is when two references refer to the same object on the heap
  • Object equality  is when you have two references and two objects on the heap, you must override both hashCode() and equals() methods inherited from class Object to treat them as equal
  • Array types are checked at runtime, but collection type checks happen only when you compile

Other Topics

  • Bit Manipulation
    • NOT (~) flips all bits, AND (&) makes bits 1 only if both bits were 1, OR (|) makes bits 1 if either bit was 1, XOR (^) makes bits 1 only if a single bit was 1
    • Left shift (<<) multiplies a number by a power of two and right shift (>>) divides by a power of two
    • Unsigned right shift (>>>) is like the right shift operator but ALWAYS fills the leftmost bits with zeros, so the sign bit may change
  • Immutability
    • When you make a new String, the JVM puts it into a special part of memory called the String Pool
    • If the String Pool contains the same String you’re trying to create, then the JVM refers your reference variable to the existing entry
    • The garbage collector doesn’t go into the String Pool, so you must be careful with memory management
  • Assertions
    • Add assert statements when you believe something must be true, used for debugging code
    • “assert (height > 0);” means if true then the program continues normally, but if false, throws an AssertionError
  • Anonymous Inner Classes
    • When you create an inner class and instantiate it right away
    • Example: button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) {} }
  • Access Levels and Modifiers
    • public means code can be accessed from anywhere, protected means code in the same package has access and also subclasses outside the package can inherit the protected item, default means that only code within the same package can access, private means that code within the same class can access
  • Strings
    • StringBuilder can be a lot more efficient for manipulating a String
    • StringBuffer should only be used when you want your String manipulations to be thread-safe
  • Multidimensional Arrays
    • Declared as “int[][] twoD_array = new int [4][2]”, which creates an array with 4 elements, with each element being a reference variable referring to a newly created array with 2 elements
  • Enumerations
    • Enumerations are a set of constant values to represent the only valid values for a variable
    • Declared as “public enum Members { JERRY, BOBBY };”
    • If you then say “public Members bandMembers;” then bandMembers can only have a value of “JERRY” or “BOBBY”