[关闭]
@TaoSama 2018-03-19T03:53:25.000000Z 字数 37688 阅读 944

Thinking in Java

Java


  1. Write above:
  2. I wrote the notes in the view of a CPP programmer,
  3. which is quick for catching the differences.
  4. Any error plz point out.

Introduction to Objects

The hidden implementation

The singly rooted hierarchy

Containers

Java, the library has different types of containers for different needs:

Parameterized types (generics)

One of the big changes in Java SE5 is the addition of parameterized types, called generics in Java

  1. ArrayList<Shape> shapes = new ArrayList<Shape>();

Exception handling: dealing with errors

Concurrent programming

Java’s concurrency is built into the language, and Java SE5 has added significant additional library support.

Java and the Internet

History

Client-side programming

Plug-ins and Scripting languages.

Serve-side programming

Analysis and design

Everything Is an Object

You manipulate objects with references

A safer practice, then, is always to initialize a reference when you create it:

  1. String s = "asdf";

You must create all the objects

Where storage lives

  1. Registers.
  2. The stack.
  3. The heap.
  4. Constant storage.
  5. Non-RAM storage.

Special case: primitive types

Primitive type Size Minimum Maximum Wrapper type
boolean Boolean
char 16 bits Unicode 0 Unicode 2^16- 1
byte 8 bits -128 +127 Byte
short 16 bits -2^15 +2^15-1 Short
int 32 bits -2^31 +2^31-1 Integer
long 64 bits -2^63 +2^63-1 Long
float 32 bits IEEE754 IEEE754 Float
double 64 bits IEEE754 IEEE754 Double
void Void
  1. // The “wrapper” classes allow you to make a non-primitive object on the heap
  2. // to represent a primitive type.
  3. Character ch = new Character(‘x’);
  4. // Java SE5 autoboxing will automatically convert from a primitive to a wrapper type:
  5. Character ch = x’;
  6. // and back:
  7. char c = ch;

High-precision numbers

BigInteger and BigDecimal

Arrays in Java

You never need to destroy an object

Scoping

In C, C++, and Java, scope is determined by the placement of curly braces {}

  1. int x = 12;
  2. // Only x available
  3. {
  4. int q = 96;
  5. // Both x & q available
  6. // You cannot do the following, even though it is legal in C and C++:
  7. int x = 96; // Illegal
  8. }
  9. // Only x available
  10. // q is "out of scope"
  11. }

Scope of objects

  1. {
  2. String s = new String("a string");
  3. } // End of scope

Creating new data types: class

Fields and methods

  1. class DataOnly {
  2. int i;
  3. double d;
  4. boolean b;
  5. }
  6. DataOnly data = new DataOnly();
  7. data.i = 47;
  8. data.d = 1.1;
  9. data.b = false;

Default values for primitive members

When a primitive data type is a member of a class, it is guaranteed to get a default value if you do not initialize it:

Primitive type Default
boolean false
char ‘\u0000’(null)
byte (byte)0
short (short)0
int 0
long 0L
float 0.0f
double 0.0d

This guarantee doesn’t apply to local variables those that are not fields of a class.

  1. int x;

Your first Java program

  1. // HelloDate.java
  2. import java.util.*;
  3. public class HelloDate {
  4. public static void main(String[] args) {
  5. System.out.println("Hello, it’s: ");
  6. System.out.println(new Date());
  7. }
  8. }

Compiling and running

  1. javac HelloDate.java
  2. java HelloDate

Comments and embedded documentation

  1. /* This is a comment
  2. * that continues
  3. * across lines
  4. */
  5. // Remember, however, that everything inside the /* and */ is ignored,
  6. // so there’s no difference in saying:
  7. /* This is a comment that
  8. continues across lines */
  9. // This is a one-line comment

Comment documentation

  1. //: object/Documentation1.java
  2. /** A class comment */
  3. public class Documentation1 {
  4. /** A field comment */
  5. public int i;
  6. /** A method comment */
  7. public void f() {}
  8. } ///:~
  9. //: object/Documentation2.java
  10. /**
  11. * <pre>
  12. * System.out.println(new Date());
  13. * </pre>
  14. */
  15. ///:~
  16. @see classname
  17. @see fully-qualified-classname
  18. @see fully-qualified-classname#method-name
  19. {@link package.class#member label}
  20. {@docRoot}
  21. {@inheritDoc}
  22. @version version-information
  23. @author author-information
  24. @since version-information
  25. @param parameter-name description
  26. @return description
  27. @throws fully-qualified-class-name description
  28. @deprecated

Coding style

  1. class AllTheColorsOfTheRainbow {
  2. int anIntegerRepresentingColors;
  3. void changeTheHueOfTheColor(int newHue) {
  4. // ...
  5. }
  6. // ...
  7. }

Operators

Precedence

Assignment

Aliasing during method calls

Mathematical operators

Unary minus and plus operators

Auto increment and decrement

Relational operators

Logical operators

Short-circuiting

Literals

Bitwise operators

Shift operators

Ternary if-else operator

String operator + and +=

Casting operators

Truncation and rounding

Promotion

Java has no “sizeof”

Controlling Execution

if-else

Iteration

Foreach syntax

return

break and continue

The infamous “goto”

  1. label1:
  2. outer-iteration {
  3. inner-iteration {
  4. //...
  5. break; // (1)
  6. //...
  7. continue; // (2)
  8. //...
  9. continue label1; // (3)
  10. //...
  11. break label1; // (4)
  12. }
  13. }
  1. A plain continue goes to the top of the innermost loop and continues.
  2. A labeled continue goes to the label and reenters the loop right after that label.
  3. A break “drops out of the bottom” of the loop.
  4. A labeled break drops out of the bottom of the end of the loop denoted by the label.

switch

  1. switch(integral-selector) {
  2. case integral-value1 : statement; break;
  3. case integral-value2 : statement; break;
  4. case integral-value3 : statement; break;
  5. case integral-value4 : statement; break;
  6. case integral-value5 : statement; break;
  7. // ...
  8. default: statement;
  9. }

Initialization & Cleanup

Guaranteed initialization with the constructor

Method overloading

Default constructors

The this keyword

The this keyword which can be used only inside a non-static method produces the reference to the object that the method has been called for.

Calling constructors from constructors

The meaning of static

Cleanup: finalization and garbage collection

You must perform cleanup

The termination condition

finalizie() can be used as the verification of the termination condition of an object.

How a garbage collector works

Adaptive generational stop-and-copy mark-and-sweep.

Member initialization

Specifying initialization

  1. public class InitialValues2 {
  2. boolean bool = true;
  3. char ch = x’;
  4. byte b = 47;
  5. short s = 0xff;
  6. int i = 999;
  7. long lng = 1;
  8. float f = 3.14f;
  9. double d = 3.14159;
  10. }

Constructor initialization

Order of initialization

static data initialization

To summarize the process of creating an object, consider a class called Dog:

  1. Even though it doesn’t explicitly use the static keyword, the constructor is actually a static method.
    So the first time an object of type Dog is created, or the first time a static method or static field of class Dog is accessed, the Java interpreter must locate Dog.class, which it does by searching through the classpath.
  2. As Dog.class is loaded (creating a Class object, which you’ll learn about later), all of its static initializers are run.
    Thus, static initialization takes place only once, as the Class object is loaded for the first time.
  3. When you create a new Dog(), the construction process for a Dog object first allocates enough storage for a Dog object on the heap.
  4. This storage is wiped to zero, automatically setting all the primitives in that Dog object to their default values (zero for numbers and the equivalent for boolean and char) and the references to null.
  5. Any initializations that occur at the point of field definition are executed.
  6. Constructors are executed.

Explicit static initialization

  1. public class Spoon {
  2. static int i;
  3. static {
  4. i = 47;
  5. }
  6. }

Non-static instance initialization

  1. public class Mugs {
  2. Mug mug1;
  3. Mug mug2;
  4. {
  5. mug1 = new Mug(1);
  6. mug2 = new Mug(2);
  7. print("mug1 & mug2 initialized");
  8. }
  9. }

Array initialization

  1. int[] a = { 1, 2, 3, 4, 5 };

Variable argument lists

In Java SE5, however, this long-requested feature was finally added, so you can now use
ellipses to define a variable argument list.

  1. public class NewVarArgs {
  2. static void printArray(Object... args) {
  3. for(Object obj : args)
  4. System.out.print(obj + " ");
  5. System.out.println();
  6. }
  7. }

Enumerated types

  1. public enum Spiciness {
  2. NOT, MILD, MEDIUM, HOT, FLAMING
  3. }
  4. public class EnumOrder {
  5. public static void main(String[] args) {
  6. for(Spiciness s : Spiciness.values())
  7. System.out.println(s + ", ordinal " + s.ordinal());
  8. }
  9. }
  10. /* Output:
  11. NOT, ordinal 0
  12. MILD, ordinal 1
  13. MEDIUM, ordinal 2
  14. HOT, ordinal 3
  15. FLAMING, ordinal 4
  16. */

Access Control

package: the library unit

Code organization

Creating unique package names

Using imports to change behavior

Java access specifiers

Interface and implementation

Reusing Classes

Composition syntax

  1. class WaterSource {
  2. private String s;
  3. WaterSource() {
  4. System.out.println("WaterSource()");
  5. s = "Constructed";
  6. }
  7. public String toString() { return s; }
  8. }

Inheritance syntax

  1. class Art {
  2. Art() { print("Art constructor"); }
  3. }
  4. class Drawing extends Art {
  5. Drawing() { print("Drawing constructor"); }
  6. }
  7. public class Cartoon extends Drawing {
  8. public Cartoon() { print("Cartoon constructor"); }
  9. public static void main(String[] args) {
  10. Cartoon x = new Cartoon();
  11. }
  12. }
  13. /* Output:
  14. Art constructor
  15. Drawing constructor
  16. Cartoon constructor
  17. */

Constructors with arguments

  1. class Game {
  2. Game(int i) {
  3. print("Game constructor");
  4. }
  5. }
  6. class BoardGame extends Game {
  7. BoardGame(int i) {
  8. super(i);
  9. print("BoardGame constructor");
  10. }
  11. }
  12. public class Chess extends BoardGame {
  13. Chess() {
  14. super(11);
  15. print("Chess constructor");
  16. }
  17. public static void main(String[] args) {
  18. Chess x = new Chess();
  19. }
  20. }
  21. /* Output:
  22. Game constructor
  23. BoardGame constructor
  24. Chess constructor
  25. */

Delegation

  1. public class SpaceShipDelegation {
  2. private String name;
  3. private SpaceShipControls controls = new SpaceShipControls();
  4. public SpaceShipDelegation(String name) {
  5. this.name = name;
  6. }
  7. // Delegated methods:
  8. public void back(int velocity) {
  9. controls.back(velocity);
  10. }
  11. public void down(int velocity) {
  12. controls.down(velocity);
  13. }
  14. public void forward(int velocity) {
  15. controls.forward(velocity);
  16. }
  17. public void left(int velocity) {
  18. controls.left(velocity);
  19. }
  20. public void right(int velocity) {
  21. controls.right(velocity);
  22. }
  23. public void turboBoost() {
  24. controls.turboBoost();
  25. }
  26. public void up(int velocity) {
  27. controls.up(velocity);
  28. }
  29. }

Guaranteeing proper cleanup

Name hiding

Choosing composition vs. inheritance

protected

It is the same as C++, but provide package access.

Upcasting

The final keyword

final data

  1. It can be a compile-time constant that won’t ever change.
  2. It can be a value initialized at run time that you don’t want changed.

final arguments

final methods

  1. To prevent any inheriting class from changing its meaning.
  2. To allow the compiler to turn any calls to that method into inline calls.
  3. With Java SE5/6, you should let the compiler and JVM handle efficiency issues and make a method final only if you want to explicitly prevent overriding.

final and private

final classes

Initialization and class loading

Polymorphism

Method-call binding

Pitfall: “overriding” private methods

Pitfall: fields and static methods

Behavior of polymorphic methods inside constructors

Covariant return types

Java SE5 adds covariant return types, which means that an overridden method in a derived class can return a type derived from the type returned by the base-class method.

Designing with inheritance

A general guideline is “Use inheritance to express differences in behavior, and fields to
express variations in state
.”

Substitution vs. extension

"is-a" vs "is-like-a"

Downcasting and runtime type information

Interfaces

Abstract classes and methods

  1. abstract class Instrument {
  2. // You can create an abstract class with no abstract methods
  3. }

Interfaces

  1. interface Instrument { // Automatically public
  2. // Compile-time constant:
  3. int VALUE = 5; // static & final
  4. // Cannot have method definitions:
  5. void play(Note n); // Automatically public
  6. void adjust();
  7. }
  8. class Wind implements Instrument {
  9. public void play(Note n) {} // Must be public
  10. public String toString() {}
  11. public void adjust() {}

Complete decoupling

  1. public interface Processor {
  2. String name();
  3. Object process(Object input);
  4. }
  5. // Strategy pattern
  6. public class Apply {
  7. public static void process(Processor p, Object s) {
  8. print("Using Processor " + p.name());
  9. print(p.process(s));
  10. }
  11. }
  12. // If you cannot modify the class, use Adapter pattern
  13. public class Filter {
  14. public String name() {
  15. return getClass().getSimpleName();
  16. }
  17. public Waveform process(Waveform input) { return input; }
  18. }
  19. class FilterAdapter implements Processor {
  20. Filter filter;
  21. public FilterAdapter(Filter filter) {
  22. this.filter = filter;
  23. }
  24. public String name() { return filter.name(); }
  25. public Waveform process(Object input) {
  26. return filter.process((Waveform)input); // Delegation
  27. }
  28. }
  29. public class FilterProcessor {
  30. public static void main(String[] args) {
  31. Waveform w = new Waveform();
  32. Apply.process(new FilterAdapter(new Filter(), w);
  33. }
  34. }

Extending an interface with inheritance

  1. interface Monster {
  2. void menace();
  3. }
  4. interface DangerousMonster extends Monster {
  5. void destroy();
  6. }
  7. class DragonZilla implements DangerousMonster {
  8. public void menace() {}
  9. public void destroy() {}
  10. }

Initializing fields in interfaces

  1. public interface RandVals {
  2. Random RAND = new Random(47);
  3. int RANDOM_INT = RAND.nextInt(10);
  4. long RANDOM_LONG = RAND.nextLong() * 10;
  5. float RANDOM_FLOAT = RAND.nextLong() * 10;
  6. double RANDOM_DOUBLE = RAND.nextDouble() * 10;
  7. }

Nesting interfaces

Interfaces and factories

Factory Method design pattern

  1. interface Game { boolean move(); }
  2. interface GameFactory { Game getGame(); }
  3. class Checkers implements Game {
  4. private int moves = 0;
  5. private static final int MOVES = 3;
  6. public boolean move() {
  7. print("Checkers move " + moves);
  8. return ++moves != MOVES;
  9. }
  10. }
  11. class CheckersFactory implements GameFactory {
  12. public Game getGame() { return new Checkers(); }
  13. }
  14. public class Games {
  15. public static void playGame(GameFactory factory) {
  16. Game s = factory.getGame();
  17. while(s.move());
  18. }

Summary

Inner Classes

Creating inner classes

  1. public class Sequence {
  2. private Object[] items;
  3. private int next = 0;
  4. public Sequence(int size) { items = new Object[size]; }
  5. public void add(Object x) {
  6. if(next < items.length)
  7. items[next++] = x;
  8. }
  9. private class SequenceSelector implements Selector {
  10. private int i = 0;
  11. public boolean end() { return i == items.length; }
  12. public Object current() { return items[i]; }
  13. public void next() { if(i < items.length) i++; }
  14. }
  15. public Selector selector() {
  16. return new SequenceSelector();
  17. }

Using .this and .new

  1. public class DotThis {
  2. public class Inner {
  3. public DotThis outer() {
  4. return DotThis.this;
  5. // A plain "this" would be Inner’s "this"
  6. }
  7. }
  8. public class DotNew {
  9. public class Inner {}
  10. public static void main(String[] args) {
  11. DotNew dn = new DotNew();
  12. DotNew.Inner dni = dn.new Inner();
  13. }
  14. }

Inner classes and upcasting

With interface, it can hide the implementation.

Inner classes in methods and scopes

Anonymous inner classes

  1. public class Wrapping {
  2. private int i;
  3. public Wrapping(int x) { i = x; }
  4. public int value() { return i; }
  5. }
  6. public class Parcel8 {
  7. public Wrapping wrapping(int x) {
  8. final int y = 47;
  9. // Base constructor call:
  10. return new Wrapping(x) { // Pass constructor argument.
  11. public int value() {
  12. return super.value() * y;
  13. }
  14. }
  15. }; // Semicolon required
  16. }

Factory Method revisited

  1. interface Game { boolean move(); }
  2. interface GameFactory { Game getGame(); }
  3. class Checkers implements Game {
  4. private int moves = 0;
  5. private static final int MOVES = 3;
  6. public boolean move() {
  7. print("Checkers move " + moves);
  8. return ++moves != MOVES;
  9. }
  10. private static GameFactory factory = new GameFactory() {
  11. public Game getGame() { return new Checkers(); }
  12. };
  13. public static GameFactory gameFactory() {
  14. return factory;
  15. }
  16. }
  17. public class Games {
  18. public static void playGame(GameFactory factory) {
  19. Game s = factory.getGame();
  20. while(s.move());
  21. }

Nested classes

  1. A static inner class is called a nested class
  2. You don’t need an outer-class object in order to create an object of a nested class.
  3. You can’t access a non-static outer-class object from an object of a nested class

Classes inside interfaces

Reaching outward from a multiply nested class

Why inner classes?

  1. The inner class can have multiple instances, each with its own state information that is independent of the information in the outer-class object.
  2. In a single outer class you can have several inner classes, each of which implements the same interface or inherits from the same class in a different way.
  3. The point of creation of the inner-class object is not tied to the creation of the outerclass object.
  4. There is no potentially confusing "is-a" relationship with the inner class; it’s a separate entity.

Closures & callbacks

  1. interface Incrementable {
  2. void increment();
  3. }
  4. // If your class must implement increment() in
  5. // some other way, you only can use an inner class:
  6. class Callee2 extends MyIncrement {
  7. private int i = 0;
  8. public void increment() {
  9. super.increment();
  10. i++;
  11. print(i);
  12. }
  13. private class Closure implements Incrementable {
  14. public void increment() {
  15. // Specify outer-class method, otherwise
  16. // you’d get an infinite recursion:
  17. Callee2.this.increment();
  18. }
  19. }
  20. Incrementable getCallbackReference() {
  21. return new Closure();
  22. }
  23. }
  24. class Caller {
  25. private Incrementable callbackReference;
  26. Caller(Incrementable cbh) { callbackReference = cbh; }
  27. void go() { callbackReference.increment(); }
  28. }

Inner classes & control frameworks

  1. public class GreenhouseControls extends Controller {
  2. private boolean light = false;
  3. public class LightOn extends Event {
  4. public LightOn(long delayTime) { super(delayTime); }
  5. public void action() {
  6. light = true;
  7. }
  8. public String toString() { return "Light is on"; }
  9. }
  10. public class LightOff extends Event {
  11. public LightOff(long delayTime) { super(delayTime); }
  12. public void action() {
  13. light = false;
  14. }
  15. public String toString() { return "Light is off"; }
  16. }

Inheriting from inner classes

  1. class WithInner {
  2. class Inner {}
  3. }
  4. public class InheritInner extends WithInner.Inner {
  5. //! InheritInner() {} // Won’t compile
  6. InheritInner(WithInner wi) {
  7. wi.super();
  8. }
  9. public static void main(String[] args) {
  10. WithInner wi = new WithInner();
  11. InheritInner ii = new InheritInner(wi);
  12. }
  13. }

Can inner classes be overridden?

  1. class Egg2 {
  2. protected class Yolk {
  3. public Yolk() { print("Egg2.Yolk()"); }
  4. public void f() { print("Egg2.Yolk.f()");}
  5. }
  6. private Yolk y = new Yolk();
  7. public Egg2() { print("New Egg2()"); }
  8. public void insertYolk(Yolk yy) { y = yy; }
  9. public void g() { y.f(); }
  10. }
  11. public class BigEgg2 extends Egg2 {
  12. public class Yolk extends Egg2.Yolk {
  13. public Yolk() { print("BigEgg2.Yolk()"); }
  14. public void f() { print("BigEgg2.Yolk.f()"); }
  15. }
  16. public BigEgg2() { insertYolk(new Yolk()); }
  17. public static void main(String[] args) {
  18. Egg2 e2 = new BigEgg2();
  19. e2.g();
  20. }
  21. }

Local inner classes

Inner-class identifiers

Holding Your Objects

Generics and type-safe containers

Adding groups of elements

List

Iterator

ListIterator

Stack

Set

  1. Set<Integer> intset = new HashSet<Integer>();
  2. SortedSet<Integer> intset = new TreeSet<Integer>();

Map

Queue

PriorityQueue

Collection vs. Iterator

Producing an Iterator is the least-coupled way of connecting a sequence to a method that consumes that sequence, and puts far fewer constraints on the sequence class than does implementing Collection.

  1. public class CollectionSequence
  2. extends AbstractCollection<Pet> {
  3. private Pet[] pets = Pets.createArray(8);
  4. public int size() { return pets.length; }
  5. public Iterator<Pet> iterator() {
  6. return new Iterator<Pet>() {
  7. private int index = 0;
  8. public boolean hasNext() {
  9. return index < pets.length;
  10. }
  11. public Pet next() { return pets[index++]; }
  12. public void remove() { // Not implemented
  13. throw new UnsupportedOperationException();
  14. }
  15. };
  16. }
  17. }
  1. class PetSequence {
  2. protected Pet[] pets = Pets.createArray(8);
  3. }
  4. public class NonCollectionSequence extends PetSequence {
  5. public Iterator<Pet> iterator() {
  6. return new Iterator<Pet>() {
  7. private int index = 0;
  8. public boolean hasNext() {
  9. return index < pets.length;
  10. }
  11. public Pet next() { return pets[index++]; }
  12. public void remove() { // Not implemented
  13. throw new UnsupportedOperationException();
  14. }
  15. };
  16. }
  17. }

Foreach and iterators

Java SE5 introduced a new interface called Iterable which contains an iterator() method to produce an Iterator, and the Iterable interface is what foreach uses to move through a sequence. So if you create any class that implements Iterable, you can use it in a foreach statement.

The Adapter Method idiom

  1. class ReversibleArrayList<T> extends ArrayList<T> {
  2. public ReversibleArrayList(Collection<T> c) { super(c); }
  3. public Iterable<T> reversed() {
  4. return new Iterable<T>() {
  5. public Iterator<T> iterator() {
  6. return new Iterator<T>() {
  7. int current = size() - 1;
  8. public boolean hasNext() { return current > -1; }
  9. public T next() { return get(current--); }
  10. public void remove() { // Not implemented
  11. throw new UnsupportedOperationException();
  12. }
  13. };
  14. }
  15. };
  16. }
  17. }
  18. ReversibleArrayList<String> ral =
  19. new ReversibleArrayList<String>(
  20. Arrays.asList("To be or not to be".split(" ")));
  21. for(String s : ral.reversed())
  22. System.out.print(s + " ");

Error Handling with Exceptions

Catching an exception

The try block and exception handler

  1. try {
  2. // Code that might generate exceptions
  3. } catch(Type1 id1)|{
  4. // Handle exceptions of Type1
  5. } catch(Type2 id2) {
  6. // Handle exceptions of Type2
  7. } catch(Type3 id3) {
  8. // Handle exceptions of Type3
  9. }

The stack trace

Maybe the best practice for logging stacktrace of log4j2 in some version.

  1. logger.info("{}", e.toString(), e);

Performing cleanup with finally

  1. try {
  2. // The guarded region: Dangerous activities
  3. // that might throw A, B, or C
  4. } catch(A a1) {
  5. // Handler for situation A
  6. } catch(B b1) {
  7. // Handler for situation B
  8. } catch(C c1) {
  9. // Handler for situation C
  10. } finally {
  11. // Activities that happen every time
  12. }

Constructors

Exception chaining and converting checked to unchecked exceptions

  1. try {
  2. // ... to do something useful
  3. } catch(IDontKnowWhatToDoWithThisCheckedException e) {
  4. throw new RuntimeException(e);
  5. }

You can also use e.getCause() to extract the originating exceptions.

Exception guidelines

  1. Handle problems at the appropriate level. (Avoid catching exceptions unless you know what to do with them.)
  2. Fix the problem and call the method that caused the exception again.
  3. Patch things up and continue without retrying the method.
  4. Calculate some alternative result instead of what the method was supposed to produce.

Strings

Immutable Strings

Overloading ‘+’ vs. StringBuilder

Unintended recursion

  1. public class InfiniteRecursion {
  2. public String toString() {
  3. return " InfiniteRecursion address: " + this + "\n";
  4. }
  5. }

Formatting output

  1. System.out.format("Row 1: [%d %f]\n", x, y);
  2. // A nostalgic way
  3. System.out.printf("Row 1: [%d %f]\n", x, y);
  4. Formatter formatter = new Formatter(System.out);
  5. formatter.format("%s The Turtle is at (%d,%d)\n", name, x, y);
  6. // It can come in handy when you only need to call format() once.
  7. String.format("%s The Turtle is at (%d,%d)\n", name, x, y);

Regular expressions

java.util.regex.*

Basics

Creating regular expressions

Quantifiers

Pattern and Matcher

Replace operations

Regular expressions and Java I/O

Scanning with regular expressions

StringTokenizer

Efficiency?

Type Information

The need for RTTI

The Class object

The Class object

  1. // Static method
  2. Class.forName(String)
  3. // Fully qualified name
  4. getName()
  5. // Fully qualified name (introduced in Java SE5)
  6. getCanonicalName()
  7. getSimpleName()
  8. getInterfaces()
  9. islnterface()
  10. getSuperClass()

Class literals

Generic class references

  1. Class intClass = int.class;
  2. Class<Integer> genericIntClass = int.class;
  3. genericIntClass = Integer.class; // Same thing
  4. Class<Number> genericNumberClass = int.class;
  5. // The wildcard symbol is ‘?’, and it indicates "anything."
  6. Class<?> intClass = int.class;
  7. Class<? extends Number> bounded = int.class;
  1. public class FilledList<T> {
  2. private Class<T> type;
  3. public FilledList(Class<T> type) { this.type = type; }
  4. public List<T> create(int nElements) {
  5. List<T> result = new ArrayList<T>();
  6. try {
  7. for(int i = 0; i < nElements; i++)
  8. result.add(type.newInstance());
  9. } catch(Exception e) {
  10. throw new RuntimeException(e);
  11. }
  12. return result;
  13. }
  14. public static void main(String[] args) {
  15. FilledList<CountedInteger> fl =
  16. new FilledList<CountedInteger>(CountedInteger.class);
  17. System.out.println(fl.create(15));
  18. }
  19. }

New cast syntax

  1. // Java SE5 introduces the two below.
  2. Class.cast()
  3. Class.asSubclass()

Checking before a cast

Using class literals

A dynamic instanceof

Class.isisInstance vs keyword instanceof

Registered factories

  1. class Part {
  2. public String toString() {
  3. return getClass().getSimpleName();
  4. }
  5. static List<Factory<? extends Part>> partFactories =
  6. new ArrayList<Factory<? extends Part>>();
  7. static {
  8. // Collections.addAll() gives an "unchecked generic
  9. // array creation ... for varargs parameter" warning.
  10. partFactories.add(new FuelFilter.Factory());
  11. // ...
  12. }
  13. private static Random rand = new Random(47);
  14. public static Part createRandom() {
  15. int n = rand.nextInt(partFactories.size());
  16. return partFactories.get(n).create();
  17. }
  18. }
  19. class Filter extends Part {}
  20. class FuelFilter extends Filter {
  21. // Create a Class Factory for each specific type:
  22. public static class Factory
  23. implements typeinfo.factory.Factory<FuelFilter> {
  24. public FuelFilter create() { return new FuelFilter(); }
  25. }
  26. }

instanceof vs. Class equivalence

Reflection: runtime class information

A class method extractor

Class.getMethods()

Dynamic proxies

  1. // Proxy Pattern
  2. class RealObject implements Interface {
  3. public void doSomething() { print("doSomething"); }
  4. public void somethingElse(String arg) {
  5. print("somethingElse " + arg);
  6. }
  7. }
  8. class SimpleProxy implements Interface {
  9. private Interface proxied;
  10. public SimpleProxy(Interface proxied) {
  11. this.proxied = proxied;
  12. }
  13. public void doSomething() {
  14. print("SimpleProxy doSomething");
  15. proxied.doSomething();
  16. }
  17. public void somethingElse(String arg) {
  18. print("SimpleProxy somethingElse " + arg);
  19. proxied.somethingElse(arg);
  20. }
  21. }
  22. class SimpleProxyDemo {
  23. public static void consumer(Interface iface) {
  24. iface.doSomething();
  25. iface.somethingElse("bonobo");
  26. }
  27. public static void main(String[] args) {
  28. consumer(new RealObject());
  29. consumer(new SimpleProxy(new RealObject()));
  30. }
  31. }
  1. class DynamicProxyHandler implements InvocationHandler {
  2. private Object proxied;
  3. public DynamicProxyHandler(Object proxied) {
  4. this.proxied = proxied;
  5. }
  6. public Object
  7. invoke(Object proxy, Method method, Object[] args)
  8. throws Throwable {
  9. System.out.println("**** proxy: " + proxy.getClass() +
  10. ", method: " + method + ", args: " + args);
  11. if(args != null)
  12. for(Object arg : args)
  13. System.out.println(" " + arg);
  14. return method.invoke(proxied, args);
  15. }
  16. }
  17. class SimpleDynamicProxy {
  18. public static void consumer(Interface iface) {
  19. iface.doSomething();
  20. iface.somethingElse("bonobo");
  21. }
  22. public static void main(String[] args) {
  23. RealObject real = new RealObject();
  24. consumer(real);
  25. // Insert a proxy and call again:
  26. Interface proxy = (Interface)Proxy.newProxyInstance(
  27. Interface.class.getClassLoader(),
  28. new Class[]{ Interface.class },
  29. new DynamicProxyHandler(real));
  30. consumer(proxy);
  31. }
  32. }

Null Objects

  1. public interface Null {}
  2. class Person {
  3. public final String first;
  4. public final String last;
  5. public final String address;
  6. // etc.
  7. public Person(String first, String last, String address){
  8. this.first = first;
  9. this.last = last;
  10. this.address = address;
  11. }
  12. public String toString() {
  13. return "Person: " + first + " " + last + " " + address;
  14. }
  15. public static class NullPerson
  16. extends Person implements Null {
  17. private NullPerson() { super("None", "None", "None"); }
  18. public String toString() { return "NullPerson"; }
  19. }
  20. public static final Person NULL = new NullPerson();
  21. }

Mock Objects & Stubs

A Stub is a sophisticated object that does lots of things.
You usually create lots of small, simple Mock Objects if you need to do many things.

Interfaces and type information

Summary

The intent of OOP is to use polymorphic method calls everywhere you can, and RTTI only when you must.

Generics

Arrays

Containers in Depth

I/O

Enumerated Types

Annotations

Concurrency

The many faces of concurrency

Faster execution

Improving code design

Some types of problems, such as gui, simulation, are difficult to solve without support for concurrency.

Basic threading

Using Executors

Executors are the preferred method for starting tasks in Java SE5/6.
Runnable ExecutorService.execute()

  1. // A CachedThreadPool will generally create as many threads as it needs,
  2. // then will stop creating new threads as it recycles the old ones,
  3. // so it’s a reasonable first choice as an Executor.
  4. Executors.newCachedThreadPool()
  5. // You limit the number of threads.
  6. Executors.newFixedThreadPool()
  7. // A SingleThreadExecutor is like a FixedThreadPool with a size of one thread.
  8. Executors.newSingleThreadExecutor()

Producing return values from tasks

Callable Future<> = ExecutorService.submit()

The overloaded Executors.callable() method takes a Runnable and produces a
Callable.
ExecutorService has some invoke methods that run collections of Callable objects.

Sleeping

  1. // Old-style:
  2. // Thread.sleep(100);
  3. // Java SE5/6-style:
  4. TimeUnit.MILLISECONDS.sleep(100);

yield() and sleep() allows the thread scheduler to switch to another thread.

Priority

Daemon threads

  1. public class DaemonThreadFactory implements ThreadFactory {
  2. public Thread newThread(Runnable r) {
  3. Thread t = new Thread(r);
  4. t.setDaemon(true);
  5. return t;
  6. }
  7. }
  8. ExecutorService exec = Executors.newCachedThreadPool(
  9. new DaemonThreadFactory());
  10. for(int i = 0; i < 10; i++)
  11. exec.execute(new DaemonFromFactory());

The Daemon thread is set to daemon mode and it then spawns a bunch of other threads—which
are implicitly set to daemon mode.

Terminology

To clarify these discussions, I shall attempt to use the term "task" when I am describing the work that is being done, and "thread" only when I am referring to the specific mechanism that’s driving the task.

Graphical User Interfaces

omitted

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注