Java SE
Java Standard Edition
Developer's Report - Developer's Tools
Developer's Tools
- Java Development Kit 1.7
- Eclipse with Oracle Plugin
- Java Media Framework
Installation Guide
- Install jdk to program files
- Install eclipse to program files
- Install java media framework
Java Services (1.7, 1.8)
- Editor: Eclipse, Netbeans, JDeveloper, Sun Studio
- Application Servers: Tomcat, Weblogic, Websphere, Oracle 11g
- Build: Ant, Maven
- Install: Install4J, Jar
- Test: JUnit, Cruise Control, Hudson/Jenkins
- Project: Trac, Bugzilla, Solaris Project
- Configuration Management: CVS, Subversion
- Profiler: JProfiler
- OS: Windows, Apple, Solaris/Linux
- Desktop: Swing, SWT, JavaFX
- Graphics: Java3D, JOGL (Java + Open GL)
- Web: J2EE, JavaFX, JSF
- Browser: Firefox, Chrome
- Languages: Java, JRuby, JSP, HTML5, CSS, JavaScript
Document : Environment
Environment Tools
- Oracle XE Database Release 10.2.0.1.0
- Apache Tomcat 7.0
Oracle XE Database Release 10.2.0.1.0: Find Getting Started Database:
- Start | run | cmd
- tnsping localhost => HOST=127.0.0.1, PORT=1521
Eclipse On Windows platforms:
- Add [ORACLE_HOME]\jdbc\lib\classes12.jar to your CLASSPATH if you use JDK 1.2 or 1.3. Add [ORACLE_HOME]\jdbc\lib\ojdbc14.jar to your CLASSPATH if you use JDK 1.4.
- Add [ORACLE_HOME]\jlib\orai18n.jar to your CLASSPATH if needed.
- Add [ORACLE_HOME]\bin to your PATH if you are using the JDBC OCI driver.
Programmer Review
Chapter 1- Java Language Fundamentals
Java Programming Language Keywords
- Keywords cannot be used as identifiers (names) for classes, methods, variable, or anything else in your code.
- All keywords start with a lowercase letter
Literals and Ranges of All Primitive Data Types
- All six number types in Java are signed, so they can be positive or negative
- Use the formula -2^ (bits -1) to 2^ (bits – 1) – 1 to determine the range of an integer type.
- A char is really a 16-bit unsigned integer.
- Literals are source code representations of primitive data types, or String.
- Integers can be represented in octal (0127), decimal (1245), and hexadecimal (0XCAFE).
- Number literals cannot contain a comma
- A char literal can be represented as a single character in single quotes (‘A’)
- A char literal can also be represented as a Unicode value (‘\u0041’)
- A char literal can also be represented as an integer, as long as the integer is less than 65536
- A Boolean literal can be either true or false
- Floating-point literal are always double by default, if you want a float, you must append an F or f to the literal.
Array Declaration, Construction, and Initialization
- Arrays can hold primitives or objects, but the array itself is always an object
- When you declare an array, the brackets can be to the left or right of the variable name
- It is never legal to include the size of any array in the declaration (before equals sign)
- You must include the size of an array when you construct it (using new) unless you are creating an anonymous array.
- Elements in an array of objects are not automatically created, although primitive array elements are given default values.
- You’ll get a NullPointerException if you try to use an array element in an object array, if that element does not refer to a real object
- Arrays are indexed beginning with zero. In an array with three elements, you can access element 0, element 1, and element2
- You’ll get an ArrayIndexOutOfBoundsException if you try to access outside they range of an array
- Arrays have a length variable that contains the number of elements in the array
- The last index you can access is always one less than the length of the array
- Multidimensional arrays are just arrays of arrays.
- The dimensions in a multidimensional array can have different lengths
- An array of primitives can accept any value that can be promoted implicitly to the declared type of the array. For example, a byte variable can be placed in an int array
- An array of objects can hold any object that passes the IS-A (or instanceof) test for the declared type of the array. For example, if Horse extends Animal, then
- Horse object can go into an Animal array
- If you assign an array to a previously declared array reference, the array you’re assigning must be the same dimension as the reference you’re assigning it to.
- You can assign an array of one type to a previously declared array reference of one of its super types. For example, a Honda array can be assigned to an array declared as type Car (assuming Honda extends Car)
Using a Variable or Array Element that is uninitialized an unassigned
- When an array of objects is instantiated, objects within the array are not instantiated automatically, but all the references get the default value of null.
- When an array of primitives is instantiated, all elements get their default values
- Just as with array elements, instance variables are always initialized with a default value.
- Local/automatic/method variables are never given a default value. If you attempt to use one before initializing it, you’ll get a compiler error.
Command-Line Arguments to Main
- Command-line arguments are passed to the String array parameter in the main method.
- The first command-line argument is the first element in the main String array parameter
- If no arguments are passed to main, the length of the main String array parameter will be zero
Chapter 2 – Declarations and Access Control
Class Access Modifiers
- There are three access modifiers: public, protected, and private
- Three are four access levels: public, protected, default, and private
- Classes can have only public or default access
- Class visibility revolves around whether code in one class can:
Create an instance of another class
- Extend (or subclass), another class
Access methods and variables of another class
- A class with default access can be seen only by classes within the same package
- A class with public access can be seen by all classes from all packages
Class Modifiers (nonaccess)
- Classes can also be modified with final, abstract, or strictfp
- A class cannot be both final and abstract
- A final class cannot be subclassed
- An abstract class cannot be instantiated
- A single abstract method in a class means the whole class must be abstract
- An abstract class can have both abstract and nonabstract methods
- The first concrete class to extend an abstract class must implement all abstract methods
Members Access Modifiers
- Methods and instance (nonlocal) variables are known as “members.”
- Members can use all four access levels: public, protected, default, private
- Member access comes in two forms: Code in one class can access a member of another class or A subclass can inherit a member of its superclass
- If a class cannot be accessed, its members cannot be accessed
- If a superclass member is public, the subclass inherits it – regardless of package
- Determine class visibility before determining member visibility
- Public members can be accessed by all other classes, even in different packages
- Members accessed without the dot operator (.) must belong to the same class
- this. always refers to the currently executing object
- this.aMethod() is the same as just invoking aMethod()
- Private members can be accessed only by code in the same class
- Private members are not visible to subclasses, so private members cannot be inherited
- Default and protected members differ only in when subclasses are involved
- Default members can be accessed only by other classes in the same package
- Protected members can be accessed by other classes in the same package, plus subclasses regardless of package
- Protected = package plus kids (kids meaning subclasses)
- For subclasses outside the package, the protected member can be accessed only through inheritance; a subclass outside the package cannot access a protected member by using a reference to an instance of the superclass (in other words, inheritance is the only mechanism for a subclass outside the package to access a protected member of its superclass).
- A protected member inherited by a subclass from another package is, in practice, private to all other classes (in other words, no other classes from the subclass package or any other package with have access to the protected member from the subclass)
Local Variables
- Local (method, automatic, stack) variable declarations cannot have access modifiers.
- Final is the only modifier available to local variables
- Local variables don’t get default values, so they must be initialized before use.
Other Modifiers – Members
- Final methods cannot be overridden in a subclass
- Abstract methods have been declared, with a signature and return type, but have not been implemented
- Abstract methods end in a semicolon – no curly braces
- Three ways to spot a nonabstract method:
- The method is not marked abstract
- The method has curly braces
- The method has code between the curly braces
- The first nonabstract (concrete) class to extend an abstract class must implement all the abstract class’ abstract methods
- Abstract methods must be implemented by a subclass, so they must be inheritable.
- For that reason:
- Abstract methods cannot be private
- Abstract methods cannot be final
- The synchronized modifier applies only to methods
- Synchronized methods can have any access control an can also be marked final
- Synchronized methods cannot be abstract
- The native modifier applies only to methods
- The strictfp modifier applies only to classes and methods.
- Instance variables can: Have any access control, Be marked final or transient
- It is legal to declare a local variable with the same name as an instance variable; this is called “shadowing”
- Final variables have the following properties:
- Final variables cannot be reinitialized once assigned a value.
- Final reference variables cannot refer to a different object once the object has been assigned to the final variable
- Final reference variables must be initialized before the constructor completes
- There is no such thing as a final object. An object reference marked final does not mean the object itself is immutable
- The transient modifier applies only to instance variables
- The volatile modifier applies only to instance variables
Static variables and methods
- They are not tied to any particular instance of a class
- An instance of a class does not need to exist in order to use static members of the class.
- There is only one copy of a static variable per class and all instances share it
- Static variables get the same default values as instance variables
- A static method (such as main()) cannot access a nonstatic (instance) variable.
- Static members are accessed using the class name:
- someObj.theStaticMethodName()
- Static members can also be accessed using an instance reference variable,
- someObj.theStaticMethodName() but that’s just a syntax trick; the static method won’t know anything about the instance referred to by the variable used to invoke the method. The compiler uses the class type of the reference variable to determine which static method to invoke
- Static methods cannot be overridden, although they can be redeclared / redefined by a subclass. So although static methods can sometimes appear to be overridden, polymorphism will not apply
Declaration Rules
- A source code file can have only one public class
- If the source file contains a public class, the file name should match the public class name
- A file can have only one package statement, but can have multiple import statements
- The package statement (if any) must be the first line in a source file.
- The import statement (if any) must come after the package an before the class declaration.
- If there is not package statement, import statements must be the first statement in the source file
- Package and import statements apply to all classes in the file
- A file can have more than one nonpublic class
- Files with no public classes have no naming restrictions
- In a file, classes can be listed in any order (there is no forward referencing problem)
- Import statements only provide a typing shortcut to a class’ fully qualified name.
- Import statements cause no performance hits and do not increase the size of your code
- If you use a class from a different package, but do not import the class, you must the fully qualified name of the class everywhere the class is used in code.
- Import statements can coexist with fully qualified class names in a source file
- Imports ending in ‘.*;’ are importing all classes within a package
- Import ending in ‘;’ are importing a single class
- You must use fully qualified name when you have different classes from different packages, with the same class name; an import statement will not be explicit enough
- Properties of main()
- It must be marked static
- It must have a void return type
- It must have a single String array argument; the name of the argument is flexible, but the convention is args
- For the purposes of the exam, assume that the main() method must be public
- Improper main() method declarations (or the lack of a main() method) cause a runtime error, not a compiler error
- In the declarations of main() can exist legally in the class, but if none of them match the expected signature for the main() method, then the JVM won’t be able to use that class to start your application running.
- Other overloaded methods named main() can exist legally in the class, but if none of them match the expected signature for the main() method, then the JVM won’t be able to use that class to start your application running
Java.lang.Runnable
- You must memorize the java.lang.Runnable interface, it has a single method you must implement: public void run()
Interface Implementation
- Interfaces are contracts for what a class can do, but they say nothing about the way in which the class must do it.
- Interfaces can be implemented by any class, from any inheritance tree
- An interface is like a 100-percent abstract class, and is implicitly abstract whether you type the abstract modifier in the declaration or not.
- An interface can have only abstract methods, no concrete methods allowed
- Interfaces are by default public and abstract – explicit declaration of these modifiers is optional
- Interfaces can have constants, which are always implicitly public, static, and final
- Interface constants, which are optional in any combination
- Interface constant declarations of public, static, and final are optional in any combination
- A legal nonabstract implementing class has the following properties:
- It provides concrete implementations for all methods from the interface
- It must follow all legal override rules for the methods it implements
- It must not declare any new checked exceptions for an implementation method
- It must not declare any checked exceptions that are broader than the exceptions declared in the interface method
- It may declare runtime exceptions on any interface method implementation regardless of the interface declaration
- It must maintain the exact signature and return type of the methods it implements (but does not have to declare the exceptions of the interface).
- A class implementing an interface can itself be abstract
- An abstract implementing class does not have to implement the interface methods (but the first concrete subclass must)
- A class can extend only one class (no multiple inheritance), but it can implement many
- Interfaces can extend one or more other interfaces
- Interfaces cannot extend a class, or implement a class or interface
Chapter 3 – Operators and Assignments
Java Operators
- The result of performing most operations is either a Boolean or a numeric value
- Variables are just bit holders with a designated type
- A reference variable’s bits represent a way to get to an object
- An unassigned reference variable’s bits represent null
- There are 12 assignment operators: =, *=, /=, %=, +=, -=, <<=, >>=, >>>=, &=, ^=, |=
- Numeric expressions always result in at least an int-sized result- never smaller
- Floating-point numbers are implicitly doubles (64 bits)
- Narrowing a primitive truncates the high-order bits
- Two’s complement means: flip all the bits, then add 1
- Compound assignments (e.g. +=) perform an automatic cast
Reference Variables
- When creating a new object, e.g., Button b = new Button();, three things happen
- Make a reference variable named b, of type Button
- Create a new Button object
- Refer the reference variable b to the Button object
- Reference variables can refer to subclasses of the declared type but not superclasses
String Objects and References
- String objects are immutable, cannot be changed
- When you use a String reference variable to modify a String:
- A new string is created (the old string is immutable)
- The reference variable refers to the new string
Comparison Operators
- Comparison operators always result in a Boolean value (true or false)
- There are four comparison operators: >, >=, <, <=
- When comparing characters, Java uses the ASCII or Unicode value of the number as the numerical value
Instanceof Operator
- instanceof is for reference variables only, and check for whether this object is of a particular type
- The instanceof operator can be used only to test objects (or null) against class types that are in the same class hierarchy
- For interfaces, an object is “of a type” if any of its superclasses implement the interface in question
Equality Operator
- Four types of things can be tested: numbers, characters, Booleans, reference variables
- There are two equality operators: == and !=
Arithmetic Operators
- There are four primary operators: add, subtract, multiply, and divide
- The remainder operator returns the remainder of a division
- When floating-point numbers are divided by zero, they return positive or negative infinity
- When the remainder operator performs a floating-point divide by zero, it will not cause a runtime exception
- When integers are divided by zero, a runtime ArithmeticException is thrown
- When the remainder operator performs an integer divide by zero, a runtime ArithmeticException is thrown
String Concatenation Operator
- If either operand is a String, the + operator concatenates the operands
- If both operands are numeric, the + operator adds the operands
Increment/Decrement Operators
- Prefix operator runs before the value is used in the expression
- Postfix operator runs after the value is used in the expression
- In any expression, both operands are fully evaluated before the operator is applied
- Final variables cannot be incremented or decremented
Shift Operators
- There are three shift operators: >>, <<, >>>; the first two are signed, the last is unsigned
- Shift operators can only be used on integer types
- Shift operators can work on all bases of integers (octal, decimal, or hexadecimal)
- Bits are filled as follows:
- << fills the right bits with zeros
- >> fills the left bits with whatever value the original sign bit (leftmost bit) held
- >>> fills the left bits with zeros (negative numbers will become positive)
- All bit shift operands are promoted to at least an int
- For int shifts > 32 or long shifts > 64, the actual shift value is the remainder of the right operand / divided by 32 or 64, respectively
Bitwise Operators
- There are three bitwise operators - &, ^, | and a bitwise complement, operator ~
- The & operator sets a bit to 1 if both operand’s bits are set to 1
- The ^ operator sets a bit to 1 if exactly one operand’s bit is set to 1
- The | operator sets a bit to 1 if at least on operand’s bit is set to 1
- The ~ operator reverses the value of every bit in the single operand
Ternary (Conditional Operator)
- Returns one of two values based on whether a Boolean expression is true or false
- The value after the ? is the ‘if true return’
- The value after the : is the ‘if false return’
Casting
- Implicit casting (you write no code) happens when a widening conversion occurs
- Explicit casting (you write the cast) happens when a narrowing conversion occurs
- Casting a floating point to an integer type causes all digits to the right of the decimal point to be lost (truncated)
- Narrowing conversions can cause loss of data – the most significant bits (leftmost) can be lost
Logical Operators
- The are four logical operators: &, |, &&, ||
- Logical operators work with two expressions that must resolve to Boolean values
- The && and & operators return true only if both operands are true
- The || and | operators return true if either or both operands are true
- The && and || operators are known as short-circuit operators
- The && operator does not evaluate the right operand if the left operand is false
- The || does not evaluate the right operand if the left operand is true
- The & and | operators always evaluate both operands
Passing Variables into Methods
- Methods can take primitives and/or object reference as arguments
- Method arguments are always copies – of either primitive variables or reference variables
- Method arguments are never actual objects (they can be references to objects)
- In practice, a primitive argument is a completely detached copy of the original primitive
- In practice, a reference argument is another copy of a reference to the original object
Chapter 4 – Flow Control, Exceptions, and Assertions
Writing Code using if and switch Statements
- The if statement must have all expressions enclosed by at least one pair of parentheses
- The only legal argument to an if statement is a Boolean, so the if test can be only on an expression that resolves to a Boolean or a boolean variable
- Watch out for boolean assignments (=) that can be mistaken for boolean equality (==) tests: boolean x= false; if (x = true) { } // assignment, so x will always be true!
- Curly braces are optional for if blocks that have only one conditional statement.
- But watch out for misleading indentations.
- Switch statements can evaluate only the byte, short, int, and char data types. You can’t say long s= 30; switch(s) { }
- The case argument must be a literal for final variable! You cannot have a case that includes a non-final variable, or a range of values
- If the condition in a switch statement matches a case value, execution will run through all code in the switch following the matching case statement until a break or the end of the switch statement is encountered. In other words, the matching case is just the entry point into the case block, but unless there’s a break statement, the matching case is not the only case code that runs.
- The default keyword should be used in a switch statement if you want to execute some code when none of the case values match the conditional value.
- The default block can be located anywhere in the switch block, so if no case matches, the default block will be entered, and if the defaults does not contain a break, then code will continue to execute (fall-through) to the end of the switch or until the break statement is encountered.
Writing Code using loops
- A for statement does not require any arguments in the declaration, but has three parts: declaration and/or initialization, boolean evaluation, and the iteration expression
- If a variable is incremented or evaluated within a for loop, it must be declared before the loop, or within for loop declaration
- A variable declared (not just initialized) within the for loop declaration cannot be accessed outside the for loop (in other words, code below the for loop won’t be able to use the variable).
- You can initialize more than one variable in the first part of the for loop declaration; each variable initialization must be separated by a comma
- You cannot use a number (old C-style language construct) or anything that does not evaluate to a boolean value a condition for an if statement or looping construct.
- You can’t for example, say: if (x) unless x is a boolean variable
- The do-while loop will enter the body of the loop at least once, even if the test condition is not met.
Using break and continue
- An unlabeled break statement will cause the current iteration of the innermost
- looping construct to stop and the next line of code following the loop to be executed
- An unlabeled continue statement will cause the current iteration of the innermost loop to stop, and the condition of that loop to be checked, and if the condition is met, perform the loop again
- If the break statement or the continue statement is labeled, it will cause similar action to occur on the labeled loop, not the innermost loop
- If a continue statement is used in a for loop, the iteration statement is executed, and the condition is checked again
Catching an Exception using try and catch
- Exceptions come in two flavors: checked and unchecked
- Checked exceptions include: all subtypes of Exception, excluding classes that extend RuntimeException
- Checked exceptions are subject to the handle or declare rule; any method that might throw a checked exception (including methods that invoke methods that can throw a checked exception) must either declare the exception using the throws keyword, or handle the exception with an appropriate try/catch
- Subtypes of Error or RuntimeException are unchecked, so the compiler doesn’t enforce the handle or declare rule. You’re free to handle them and you’re free to declare them, but the compiler doesn’t care one way or the other
- If you use an optional finally block, it will always be invoked, regardless of whether an exception in the corresponding try is thrown or not, an regardless of whether a thrown exception is caught or not
- The only exception to the finally-will-always-be-called rule is that a finally will not be invoked if the JVM shuts down. That could happen if code from the try or catch blocks calls System.exit(), in which case the JVM will not start your finally block
- Just because finally is invoked does not mean it will complete. Code in the finally block could itself raise an exception or issue a System.exit()
- Uncaught exceptions propagate back through the call stack, starting from the method where the exception is thrown and ending with either the first method that has a corresponding catch for that exception type or a JVM shutdown (which happens if the exception gets to main(), and main() is “ducking” the exception by declaring it)
- You can create your own exceptions, normally by extending Exception or one of its subtypes. Your exception will then be considered a checked exception, and the compiler will enforce the handle or declare rule for that exception.
- All catch blocks must be ordered from most specific to most general. For example, if you have a catch clause for both IOException and Exception, you must put the catch for IOException first (in order, top to bottom in your code).
- Otherwise, the IOException would be caught by catch(Exception e), because catch argument can catch the specified exception or any of its subtypes! The compiler will stop you from defining catch clauses that can never be reached (because it sees that the more specific exception will be caught first by the more general catch).
Working with the Assertion Mechanism
- Assertions give you a way to test your assumptions during development and debugging.
- Assertions are typically enabled during testing but disabled during deployment
- You can use assert as a keyword or an identifier, but not both together. To compile older code that uses assert as an identifier (for example, a method name)
- use the –source 1.3 command-line flag to javac
- Assertions are disabled at runtime by default. To enable them, use a commandline: flag –ea or –enableassertions
- You can selectively disable assertions using the –da or –disableassertions flag
- If you enable or disable assertions using the flag without any arguments, you’re enabling or disabling assertions in general. You can combine enabling and disabling switches to have assertions enabled for some classes and/or packages, but not others.
- You can enable or disable assertions using the flag without any arguments, you’re enabling or disabling assertions in general. You can combine enabling and disabling switches to have assertions enabled for some classes and/or packages, but not others.
- You can enable or disable assertions in the system classes with the –esa or –dsa flags
- You can enable and disable assertions on a class-by-class basis, using the following syntax: java –ea –da:MyClass TestClass
- You can enable and disable assertions on a package basis, and any package you specify also includes any subpackages (packages further down the directory hierarchy)
- Do not use assertions to validate arguments to public method
- Do not use assert expressions that cause side effects. Assertions aren’t guaranteed to always run, so you don’t want behavior that changes depending on whether assertions are enabled.
- Do use assertions – even in public methods – to validate that a particular code block will never be reached. You can use assert false; for code that should never be reached, so that as assertion error is thrown immediately if the assert statement is executed.
- Do not use assert expressions that can cause side effects.
Chapter 5 – Object Orientation, Overloading, and Overriding,
- Constructors, and Return Types
Encapsulation, IS-A, HAS-A
- The goal of encapsulation is to hide implementation behind an interface
- Encapsulated code has two features: Instance variables are kept protected (usually with the private modifier)
- Getter and setter methods provide access to instance variables
- IS-A refers to inheritance
- IS-A is expressed with the keyword extends
- “IS-A”, “inherits from,” “is derived from,” and “is a subtype of” are all equivalent expressions
- HAS-A means an instance of one class “has a” reference to an instance of another class
Overriding and Overloading
- Methods can be overridden or overloaded; constructors can be overloaded but not overridden
- Abstract methods must be overridden by the first concrete (nonabstract) subclass
- With respect to the method it overrides, the overriding method
- Must have the same argument list
- Must have the same return type
- Must not have a more restrictive access modifier
- May have a less restrictive access modifier
- Must not throw new or broader checked exceptions
- May throw fewer or narrower checked exceptions, or any unchecked exception
- Final methods cannot be overridden
- Only inherited methods may be overridden
- A subclass uses super.overriddenMethodName to call the superclass version of an overridden method
- Overloading means reusing the same method name, but with different arguments
- Overloaded methods
- Must have different argument lists
- May have different return types, as long as the argument lists are also different
- May have different access modifiers
- May throw different exceptions
- Methods from a superclass can be overloaded in a subclass
- Polymorphism applies to overriding, not to overloading
- Object type determines which overridden method is used at runtime
- Reference type determines which overloaded method will be used at compile time
Instantiation and Constructors
- Objects are constructed
- You cannot create a new object without invoking a constructor
- Each superclass in an object’s inheritance tree will have a constructor called
- Every class, even abstract classes, has at least one constructor
- Constructors must have the same name as the class
- Constructors do not have a return type. If there is a return type, then it is simply a method with the same name as the class, and not a constructor
- Constructor execution occurs as follows:
- The constructor calls its superclass constructor, which calls its superclass constructor, and so on all the way up to the Object constructor
- The Object constructor executes and then returns to the calling constructor, which runs to completion and then returns to its calling constructor, and so on back down to the completion of the constructor of the actual instance being created
- Constructors can use any access modifier (even private)
- The compiler will create a default constructor if you don’t create any constructors in your class
- The default constructor is a no-arg constructor with a no-arg call to super()
- The first statement of every constructor must be a call to either this() (an overloaded constructor) or super()
- The compiler will add a call to super() if you do not, unless you have already put in a call to this()
- Instance methods and variables are only accessible after the super constructor runs
- Abstract classes have constructors that are called when a concrete subclass is instantiated
- Interfaces do not have constructors
- If your superclass does not have a no-arg constructor, you must create a constructor and insert a call to super() with arguments matching those of the superclass constructor
- Constructors are never inherited, thus they cannot be overridden
- A constructor can be directly invoked only by another constructor (using a call to super() or this())
- Issues with calls to this();
- May appear only as the first statement in a constructor
- The argument list determines which overloaded constructor is called
- Constructors can call constructors can call constructors, and so on, but sooner or later one of them better call super() or the stack will explode
- This() and super() cannot be in the same constructor. You can have one or the other, but never both
Return Types
- Overloaded methods can change return types; overridden methods cannot
- Object reference return types can accept null as a return value
- An array is a legal return type, both to declare and return as a value
- For methods with primitive return types, any value that can be implicitly converted to the return type can be returned
- Nothing can be returned from a void, but you can return nothing. You’re allowed to simply say return, in any method with a void return type, to bust out of a method early. But you can’t return nothing from a method with a non-void return type.
- For methods with an object reference return type, a subclass of that type can be returned
- For methods with an interface return type, any implementer of that interface can be returned.
Chapter 6 – java.lang – The Math Class, Strings, and Wrappers
Using the java.lang.String Class
- String objects are immutable, and String reference variables are not
- If you create a new String without assigning it, it will be lost to your program
- If you redirect a String reference to a new String, the old String can be lost
- String methods use zero-based indexes, except for the second argument of substring
- The String class is final – its methods can’t be overridden
- When a String literal is encountered by the VM, it is added to the pool.
- Strings have a method named length(), arrays have an attribute named length
- Important methods in the String Class
- public char charAt(int index)
- public String concat(String s)
- public Boolean equalsIgnoreCase(String s)
- public int length()
- public String replace(char old, char new)
- public String substring(int begin)
- public String substring(int begin, int end)
- public String toLowerCase()
- public String toString()
- public String toUpperCase()
- public String trim()
- StringBuffers are mutable – they can change without creating a new object
- StringBuffer methods act on the invoking object, but objects can change without an explicit assignment in the statement
- StringBuffer equals() is not overridden; it doesn’t compare values
- In all sections, remember that chained methods are evaluated from left to right
Important methods in the StringBuffer Class
- public synchronized StringBuffer append(String s)
- public synchronized StringBuffer insert(int offset, String s)
- public synchronized StringBuffer reverse()
- public String toString()
Using the java.lang.Math Class
- The abs() method is overloaded to take an int, a long, a float, or double arguments
- The abs() method can return a negative if the argument is the minimum int or long value equal to the value of Integer.MIN_VALUE or Long.MIN_VALUE respectively
- The max() method is overloaded to take int, long, float, or double arguments
- The min() method is overloaded to take int, long, float, or double arguments
- The random() method returns a double greater than or equal to 0.0 and less than 1.0
- The random() does not take any arguments
- The methods ceil(), floor(), and round() all return integer equivalent floating-point numbers, ceil() and floor() return doubles, round() returns a float if it was passed an int, or it returns a double if it was passed a long
- The round() method is overloaded to take a float or a double
- The methods sin(), cos(), and tan() take a double angle in radians
- The method sqrt() can return NaN if the argument is NaN or less than zero
- Floating-point numbers can be divided by 0.0 without error; the result is either positive or negative infinity
- NaN is not equal to anything, not even itself
Miscellaneous Math Class Facts
double d;
// The floating point classes have these three special fields
// They can be Float or Double
float p_i = Float.POSITIVE_INFINITY;
double n_i = Double.NEGATIVE_INFINITY;
double notanum = Double.NaN;
// ** Nan isn’t == to anything, not even itself!
// result is “NaNs not equal”
if (notanum != notanum)
System.out.println (“NaNs not equal”);
// Float and Double have isNan() methods to test for NaNs
// result is “got a NaN”
if (Double.isNaN(notanum))
System.out.println(“got a NaN”);
// square root of negative infinity?
d = Math.sqrt(n_i);
// result is “got sqrt NaN”
if (Double.isNaN(d))
System.out.println(“got sqrt NaN”);
// result is NaN
System.out.println(Math.sqrt(-16d);
// divide by zero only works for floating point numbers
// integers throw an ArithmeticException
// ** result is (positive) “Infinity"
System.out.println(16d / 0.0);
// ** result is (negative) “Infinity”
System.out.println(16d/-0.0);
// result is “abs(-0) = 0”
System.out.println(“abs(-0) = “ + Math.abs(-0));
Using Wrappers
- The wrapper classes correlate to the primitive types
- Wrappers have two main functions:
- To wrap primitives so that they can be handled like objects
- To provide utility methods for primitives (usually conversions)
- Other than Character and Integer, wrapper class names are the primitive’s name, capitalized
- Wrapper constructors can take a String or a primitive, except for Character, which can only take a char
- A Boolean object can’t be used like a boolean primitive
- The three most important method families are
- xxxValue() Takes no arguments, returns a primitive
- parseXxx() Takes a String, returns a primitive, is static, throws NumberFormatException
- valueOf() Takes a String, returns a wrapped object, is static, throws NumberFormatException
- Radix refers to bases (typically) other than 10; binary is radix 2, octal = 8, hex = 16
- Using equals()
- Use == to compare primitive variables
- Use == to determine if two reference variables refer to the same object
- == compares bit patterns, either primitive bits or reference bits
- Use equals() to determine if two objects are meaningfully equivalent
- The String and Wrapper classes override equals() to check for values
- The StringBuffer class equals() is not overridden; it uses == under the covers
- The compiler will not allow == if the classes are not in the same hierarchy
- Wrappers won’t pass equals() if they are in different classes
Chapter 7 – Objects and Collections
Overriding hashCode() and equals()
- The critical methods in class Object are equals(), finalize(), hashCode(), and toString()
- Equals(), hashCode(), and toString() are public(finalize() is protected)
- Fun facts about toString()
- Override toString() so that System.out.println() or other methods can see something useful
- Override toString() return the essence of your object’s state
- Use == to determine if two reference variables refer to the same object
- Use equals() to determine if two objects are meaningfully equivalent
- If you don’t override equals(), your objects won’t be useful hashtable/hashmap keys
- If you don’t override equals(), two different objects can’t be considered the same
- Strings and wrappers override equals() and make good hashtable/hashmap keys
- When overriding equals(), use the instanceof operator to be sure you’re evaluating
- an appropriate class
- When overriding equals(), use the instanceof operator to be sure you’re evaluating
- an appropriate class
- When overriding equals(), compare the object’ significant attributes
- Highlights of the equals contract:
- Reflexive: x.equals(x) is true
- Symmetric: If x.equals(y) is true, the y.equals(x) must be true
- Transitive: If x.equals(y) is true, then y.equals(z) is true, then z.equals(x) is true
- Consistent: Multiple calls to x.equals(y) will return the same result
- Null: If x is not null, then x.equals(null) is false
- If x.equals(y) is true, then x.hashCode() == y.hashCode() must be true
- If you override equals(), override hashCode()
- Classes HashMap, Hashtable, LinkedHashMap, and LinkedHashSet use hashing
- A legal hashCode() override compiles and runs
- An appropriate hashCode() override sticks to the contract
- An efficient hashCode() override distributes keys randomly across a wide range of buckets
- To reiterate: if two objects are equal, their hashcodes must be equal
- It’s legal for a hashCode() method to return the same value for all instances
- (although in practice it’s very inefficient)
- Highlights of the hashCode() contract
- Consistent: Multiple calls to x.hashCode() return the same integer
- If x.equals(y) is true, then x.hashCode() == y.hashCode() must be true
- If x.equals(y) is false, then x.hashCode() == y.hashCode() can be either
- true or false, but false will then to create better efficiency
- Transient variables aren’t appropriate for equals() and hashCode()
- Collections
- Common collection activities include adding objects, removing objects, verifying object inclusion, retrieving objects, and iterating
- Three meanings for “collection”:
- collection – Represents the data structure in which objects are stored
- Collection – java.util.Collection – Interface from which Set and List extend
- Collections – A class that holds static collection utility methods
- Three basic flavors of collections include: Lists, Sets, Maps
- Lists of things: Ordered, duplicates allowed, with an index
- Sets of things: May or may not be ordered and/or sorted, duplicates not allowed
- Maps of things with keys: may or may not be ordered and/or sorted, duplicate keys are not allowed
- Four basic subflavors of collections include: Sorted, Unsorted, Ordered, Unordered
- Ordered means iterating through a collection in a specific, nonrandom order
- Sorted means iterating through a collection in a natural sorted order
- Natural means alphabetic, numeric, or programmer-defined, whichever applies
- Key attributes of common collection classes:
- ArrayList: Fast iteration and fast random access
- Vector: Like a somewhat slower ArrayList, mainly due to its synchronized methods
- LinkedList: Good for adding elements to the ends, i.e., stack and queues
- HashSet: Assures no duplicates, provides no ordering
- LinkedHashSet: No duplicates; iterates by insertion order or last accessed
- TreeSet: No duplicates; iterates in natural sorted order
- HashMap: Fastest updates (key/value pairs); allows one null key, many null values
- Hashtable: Like a slower HashMap (as with Vector, due to its
- synchronized methods). No null values or null keys allowed
- LinkedHashMap: Faster iterations; iterates by insertion order or last
- accessed, allows one null key, many null values (new with 1.4)
- TreeMap: A sorted map, in natural order
- Basic Operations
- int size();
- boolean isEmpty();
- boolean contains(Object element);
- boolean add(Object element);
- boolean remove(Object element);
- Bulk Operations
- boolean containsAll(Collection c); // subset
- boolean addAll(Collection c); // union
- boolean removeAll(Collection c); // difference
- boolean retainAll(Collection c); // intersection
- void clear(); // empty set
- Array Operations
- Object[] toArray();
- Object[] toArray(Object a[]);
- Iterator
- boolean hasNext();
- Object next();
- void remove();
- Garbage Collection
- In Java, garbage collection provides some automated memory management
- All objects in Java live on the heap
- The heap is also known as the garbage collectible heap
- The purpose of garbage collecting is to find and delete objects that can’t be reached
- Only the JVM decides exactly when to run the garbage collector
- You (the programmer) can only recommend when to run the garbage collector
- You can’t know the garbage collector algorithm; maybe it uses mark and sweep, maybe it’s generational and/or iterative
- Objects must be considered eligible before they can be garbage collected.
- An object is eligible when no live thread can reach it
- To reach an object, a live thread must have a live, reachable reference variable to that object
- Java applications can run out of memory Islands of objects can be garbage collected, even though they have references
- To reiterate: garbage collection can’t be forced
- Request garbage collection with System.gc(); (recommended)
- Class Object has a finalize() method.
- The finalize() method is guaranteed to run once and only once before the garbage collector deletes an object
- Since the garbage collector makes no guarantees, finalize() may never run
- You can uneligibilize an object from within finalize()
Chapter 8 – Inner Classes
- Inner Classes
- A “regular” inner class is declared inside the curly braces of another class, but outside any method or other code block.
- An inner class is a full-fledged member of the enclosing (outer) class, so it can be marked with an access modifier as well as the abstract or final modifiers (but of course, never both abstract and final together – remember that abstract means it must be subclassed, whereas final means it cannot be subclassed).
- An inner class instance shares a special relationship with an instance of the enclosing class. This relationship gives the inner class access to all of the outer class’ members, including those marked private.
- To instantiate an inner class, you must have a reference to an instance of the outer class
- From code within the enclosing class, you can instantiate the inner class using only the name of the inner class, as follows: MyInner mi = new MyInner();
- From code outside the enclosing class’ instance methods, you can instantiate the inner class only by using both the inner and outer class names, and a reference to
- the outer class as follows: MyOuter mo= new MyOuter(); MyOuter.MyInner = mo.new MyInner();
- From code within the inner class, the keyword this holds a reference to the inner class instance. To reference the outer this (in other words, the instance of the out class that this inner instance is tied to) precede the keyword this with the outer class name as follows: MyOuter.this;
- Method-Local Inner Classes
- A method-local inner class is defined within a method of the enclosing class
- For the inner class to be used, you must instantiate it, and that instantiation must happen within the same method, but after the class definition code
- A method-local inner class cannot use variables declared within the method (including parameters) unless those variables are marked final
- The only modifiers you can apply to a method-local inner class are abstract and final. (Never both at the same time, though)
- Anonymous Inner Classes
- Anonymous inner classes have no name, and their type must be either a subclass of the named type or an implementer of the name interface
- An anonymous inner class is always created as part of a statement, so don’t forget to close the statement after the class definition, with a curly brace. This is one of the rare times you’ll see a curly brace followed by a semicolon in Java.
- Because of polymorphism, the only methods you can call on an anonymous inner class reference are those defined in the reference variable class (or interface), even though the anonymous class is really a subclass or implementer of the reference variable type.
- An anonymous inner class can extend one subclass, or implement one interface.
- Unlike non-anonymous classes (inner or otherwise), an anonymous inner class cannot do both. In other words, it cannot both extend a class and implement an interface, nor can it implement more than one interface.
- An argument-local inner class is declared, defined, and automatically instantiated as part of a method invocation. The key to remember is that the class is being defined within a method argument, so the syntax will end the class definition with a curly brace, followed by a closing parenthesis to end the method call, followed by a semicolon to the end the statement: });
- Static Nested Classes
- Static nested classes are inner classes marked with the static modifier
- Technically, a static nested class is not an inner class, but instead is considered a top-level nested class
- Because the nested class is static, it does not share any special relationship with an instance of the outer class. In fact, you don’t need an instance of the outer class to instantiate a static nested class
- Instantiating a static nested class requires using both the outer and nested class names as follows: BigOuter.Nested n = new BigOuter.Nested();
- A static nested class cannot access nonstatic members of the outer class, since it does not have an implicit reference to any outer instance (in other words, the nested class instance does not get an outer this reference).
Chapter 9 – Threads
- Creating, Instantiating, and Starting New Threads
- Threads can be created by extending Thread and overriding the public void run() method
- Thread objects can also be created by calling the Thread constructor that takes a Runnable argument. The Runnable object is said to be the target of the thread
- You can call start() on a Thread object only once. If start() is called more than once on a Thread object, it will throw a RuntimeException
- It is legal to create many Thread objects using the same Runnable object as the target
- When a Thread object is created, it does not become a thread of execution until its start() method is invoked. When a Thread object exists but hasn’t been started, it is in the new state and is not considered alive
- Thread Constructors
- Thread()
- Thread(Runnable target)
- Thread(Runnable target, String name)
- Thread(String name)
- Thread(ThreadGroup group, Runnable target)
- Thread(ThreadGroup group, Runnable target, String name)
- Thread(ThreadGroup group, String name)
- Transitioning Between Thread States
- Once a new thread is started, it will always enter the runnable state
- The thread scheduler can move a thread back and forth between the runnable state and the running state
- Only one thread can be running at a time, although many threads may be in the runnable state.
- There is no guarantee that the order in which threads were started determines the order in which they’ll run
- There’s no guarantee that threads will take turns in any fair way. It’s up to the thread scheduler, as determined by the particular virtual machine implementation.
- If you want a guarantee that you threads will take turns regardless of the underlying JVM, you should use the sleep() method. This prevents one thread from hogging the running process while another thread starves.
- A running thread may enter a blocked/waiting state by a wait(), sleep(), or join call
- A running thread may enter a blocked/waiting state because it can’t acquire the lock for a synchronized block of code
- When the sleep or wait is over, or an object’s lock becomes available, the thread can only reenter the runnable state. It will go directly from waiting to running (well, for all practical purposes anyway)
- A dead thread cannot be started again
- Sleep, Yield, and Join
- Sleeping is used to delay execution for a period of time, and no locks are released when a thread goes to sleep
- A sleeping thread is guaranteed to sleep for at least the time specified in the argument to the sleep method (unless it’s interrupted), but there is no guarantee as to when the newly awakened thread will actually return to running
- The sleep() method is a static method that sleeps the currently executing thread.
- One thread cannot tell another thread to sleep
- The setPriority() method is used on Thread objects to give threads a priority of between 1 (low) and 10 (high), although priorities are not guaranteed, and not all JVMs use a priority range of 1-10
- If not expliticitly set, a thread’s priority will be the same priority as the thread that created this thread (in other words, the thread executing the code that creates the new thread)
- The yield() method may cause a running thread to take back out if there are runnable threads of the same priority. There is no guarantee that this will happen, and there is no gurantee that when the thread backs out it will be different thread selected to run. A thread might yield and the immediately reenter the running state.
- The closest thing to a guarantee is that at any given time, when a thread is running it will usually not have a lower priority than any thread in the runnable state. If a low-priority thread is running when a high-priority thread enters runnable, the JVM will preempt the running low-priority thread and put the high priority thread in.
- When one thread calls the join() method of another thread, the currently running thread will wait until the thread it joins with has completed. Think of the join() method as saying,” Hey thread, I want to join on to the end of you. Let me know when you’re done, so I can enter the runnable state.”
- Concurrent Access Problems and Synchronized Threads
- Synchronized methods prevent more than one thread from accessing an object’s critical method code
- You can use the synchronized keyword as a method modifier, or to start a synchronized block of code
- To synchronize a block of code (in other word, a scope smaller than the whole method), you must specify an argument that is the object whose lock you want to synchronize on.
- While only one thread can be accessing synchronized code of a particular instance, multiple threads can still access the same object’s unsynchronized code
- When an object goes to sleep, it takes its locks with it
- Static methods can be synchronized, using the lock from the java.lang.Class instance representing that class
- Communicating with Objects by Waiting and Notifying
- The wait() method lets a thread say, “there’s nothing for me to do here, so put me in your waiting pool and notify me when something happens that I care about.” Basically, a wait() call means “wait me in your pool,” or “add me to your waiting list.”
- The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object’s waiting pool
- The method notifyAll() works in the same way as notify(), only it sends the signal to all of the threads waiting on the object
- All three methods- wait()/notify()/notifyAll() – must be called from within a synchronized context! A thread invokes wait()/notify() on a particular object, and the thread must currently hold the lock on that object
- Deadlocked Threads
- Deadlocking is when thread execution grinds to a halt because the code is waiting for locks to be removed from objects
- Deadlocking can occur when a locked object attempts to access another locked object that is trying to access the first locked object. In other words, both threads are waiting for each other’s locks to be released; therefore, the locks will never be released!
Java Development Kit 1.7
JDK Tools (1.7.0_09, jdk-7u9-windows-i586.exe)
49 File(s)