[关闭]
@TangWill 2019-04-01T12:53:12.000000Z 字数 217693 阅读 830

Java学习笔记


SE


软件1705 唐麒 17301138



Chapter 1 Getting Start


1.1 About the Java Technology

Java programming language is unusual in that a program is both compiled and interpreted.
image_1ctvef6lc15a31o5cb61et3u6p5h.png-31.8kB

Java bytecodes help make "write once, run anywhere" possible
image_1ctveg1j41rsl2md1svv1mnnadf6b.png-89kB

The Java Platform
A platform is the hardware or software environment in which a program runs

The Java platform differs from most other platforms in that it's a software-only platform that runs on top of other hardware-based platforms. The Java platform has two components:

The Java Virtual Machine (Java VM)
The Java Application Programming Interface (Java API)

image_1ctvei0s6g6c1q1os2h1a5g7k75.png-25.2kB

The Java Virtual Machine
• Provides hardware platform specifications
• Reads compiled byte codes that are platform independent
• Is implemented in a Java technology development tool or a Web browser
• The majority of type checking is done when the code is compiled.

Garbage Collection
• Allocated memory that is no longer needed should be
Deallocated, In other languages, deallocation is the programmer’s Responsibility

• The Java programming language provides a systemlevel
thread to track memory allocation

• Garbage collection:

Checks for and frees memory no longer needed
Is done automatically

image_1ctvels8fvl24ffcc91gucfdm82.png-57.4kB


Chapter 2 Class and Object


2.1 What Is a Class and Object?

Definition:* A class is a blueprint, or prototype, that defines the variables and the methods common to all objects of a certain kind. *

In software, a class is a description of an object:

image_1ctvbmj3d1v24htgco71qlq3339.png-109.3kB


2.2 Constructor

All Java classes have constructors that are used to initialize a new object of that type.

  1. Basic syntax of a constructor:
  2. < modifier> <class_name> ([< argument_list>]) {
  3. [< statements>]
  4. }

Writing Our Own Explicit Constructors

The Default Constructor
• There is always at least one constructor in every class.
• If the writer does not supply any constructors, the default constructor is present automatically:

The default constructor takes no arguments
The default constructor has no body

• Enables you to create object instances with new Xxx() without having to write a constructor.

if we declare any of our own constructors for a class, with any argument signature, then the default parameterless constructor is not automatically provided.

Constructing and Initializing Objects
Calling new Xxx() to allocate space for the new object results in:


2.3 Object

Memory Allocation and Layout
• A declaration allocates storage only for a reference:

  1. MyDate my_birth

image_1ctvcakmg1es6qafkvn1eoq1nlj2i.png-1.7kB

Use the new operator to allocate space for MyDate:

  1. MyDate my_birth = new MyDate(22, 7, 1964);

image_1ctvccb439es1775m9utue1pog9.png-5.7kB


2.4 The Power of Encapsulation Plus Information Hiding

By restricting access to an object’s private attributes through public accessors, we derive three important benefits:


2.5 Packages

Definition: A package is a collection of related classes and interfaces providing access protection and namespace management.

programmers bundle groups of related classes and interfaces into packages.

  1. java.net
  2. java.io
  3. java.lang
  4. java.applet
  5. javax.swing

You should bundle these classes and the interface in a package for several reasons:

Using Package Members
To use a public package member from outside its package, you must do one or more of the following:

Refer to the member by its long (qualified) name
Import the package member
Import the members entire package

Using Package Members
1、Referring to a Package Member by Name

  1. graphics.Rectangle myRect = new graphics.Rectangle();

2、Importing a Package Member

  1. import graphics.Circle;
  2. Circle myCircle = new Circle();

3 . Importing an Entire Package

  1. import graphics.*;
  2. Circle myCircle = new Circle();
  3. Rectangle myRectangle = new Rectangle();

2.6 Access

image_1ctvd9s1ohqs1um3quo1shql8451.png-13.3kB


Chapter 3 Identifiers,Keywords and Types


3.1 Reference Types

Passing Information into a Method
primitive data types: such as doubles, floats and integers. the method cannot change its value

reference data types :such as objects and arrays. the method cannot change the object reference, but can invoke the object's methods and modify the accessible variables within the object.


3.2 This reference

You can use this in the method body to refer to members in the current object.
image_1ctvbb2nl1jhq1na4aj2fnrvho5.png-27.3kB
image_1ctvbbd971elo1ofu27f1dac1tsaoi.png-24kB
you can use this in the method body to refer to members in the current object.
Using the “this”Keyword to Facilitate Constructor Reuse.


Chapter 4 Expressions and Flow Control


4.1 Variables and Scope

The Java programming language defines the following kinds of variables:
Instance Variables (Non-Static Fields) Technically speaking, objects store their individual states in "non-static fields", that is, fields declared without the static keyword. Non-static fields are also known as instance variables because their values are unique to each instance of a class (to each object, in other words); the currentSpeed of one bicycle is independent from the currentSpeed of another.

Class Variables (Static Fields) A class variable is any field declared with the static modifier; this tells the compiler that there is exactly one copy of this variable in existence, regardless of how many times the class has been instantiated. A field defining the number of gears for a particular kind of bicycle could be marked as static since conceptually the same number of gears will apply to all instances. The code static int numGears = 6; would create such a static field. Additionally, the keyword final could be added to indicate that the number of gears will never change.

Local Variables Similar to how an object stores its state in fields, a method will often store its temporary state in local variables. The syntax for declaring a local variable is similar to declaring a field (for example, int count = 0;). There is no special keyword designating a variable as local; that determination comes entirely from the location in which the variable is declared — which is between the opening and closing braces of a method. As such, local variables are only visible to the methods in which they are declared; they are not accessible from the rest of the class.

Parameters You've already seen examples of parameters, both in the Bicycle class and in the main method of the "Hello World!" application. Recall that the signature for the main method is public static void main(String[] args). Here, the args variable is the parameter to this method. The important thing to remember is that parameters are always classified as "variables" not "fields". This applies to other parameter-accepting constructs as well (such as constructors and exception handlers) that you'll learn about later in the tutorial.

A variable's scope is the region of a program within which the variable can be referred to by its simple name.Scope also determines when the system creates and destroys memory for the variable.

Four categories:

89.gif-22.4kB

图片2.png-21.8kB

图片3.png-24.2kB

图片4.png-8.1kB

Naming
Every programming language has its own set of rules and conventions for the kinds of names that you're allowed to use, and the Java programming language is no different. The rules and conventions for naming your variables can be summarized as follows:


4.2 StringBuffer

java.long.String class provides for strings whose value will not change

  1. int length(). Obtains the number of characters in the String.
  2. char charAt(int index). Returns the character at the specified index.
  3. boolean equals(Object anObject). Returns true if the specified Object represents a String with the same sequence of characters.
  4. int indexOf(int ch). Returns the index of the first occurrence of the character.
  5. int indexOf(String str). Returns the index of the first occurrence of the String.
  6. boolean startsWith(String prefix). Checks if the String has the specified prefix.
  7. String substring(int beginIndex, int endIndex). Returns a substring.

The StringBuffer class provides for strings that will be modified typically use string buffers for constructing character data dynamically

Constructors:

  1. StringBuffer()
  2. StringBuffer(int capacity)
  3. StringBuffer(String initialString)

Modification operations: append, insert, reverse,setCharAt, and setLength.


Chapter 5 Array


5.1 Arrays

An array is a structure that holds multiple values of the same type.

An array can contain :
a set of primitives
a set of object references

An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created. After creation, its length is fixed. You have seen an example of arrays already, in the main method of the "Hello World!" application. This section discusses arrays in greater detail.

objects-tenElementArray.gif-6.7kB

Each item in an array is called an element, and each element is accessed by its numerical index. As shown in the preceding illustration, numbering begins with 0. The 9th element, for example, would therefore be accessed at index 8.


5.2 Declaring Arrays

Declare arrays of primitive or class types:

  1. char[] s;
  2. Point[] p;

the declaration for an array variable does not allocate any memory to contain the array elements.


5.3 Creating Arrays

Because Java arrays are objects, they must be instantiated using the new operator.

  1. int[] MyIntArray;
  2. MyIntArray =new int[10]
  3. Point[] myIntArray;
  4. myIntArray =new Point[10];

The first element in an array has an index of 0

For example, a primitive (char) array:

  1. public char[] createArray(){
  2. char[] s;
  3. s = new char[ 26];
  4. for ( int i= 0; i< 26; i++ ) {
  5. s[ i] = (char) (‘A’+ i);
  6. }
  7. return s;
  8. }

99.png-15.3kB

Another example, an object array:

  1. public Point[] createArray(){
  2. Point[] p;
  3. p = new Point[ 10];
  4. for ( int i= 0; i< 10; i++ ) {
  5. p[ i] = new Point( i, i+ 1);
  6. }
  7. return p;
  8. }

98.png-22.8kB


5.4 Initializing Arrays

That is, the following won’t compile:

  1. String[] names = new String[4];
  2. // This next line won't compile.
  3. names = {"Mike", "Cheryl", "Mickey", "Will" };

Initialize an array element
• Create an array with initial values:

  1. String names[];
  2. names = new String[3];
  3. names[0] = "Georgianna";
  4. names[1] = "Jen";
  5. names[2] = "Simon";
  6. String names[] = {
  7. "Georgianna",
  8. "Jen",
  9. "Simon"
  10. };

5.5 Manipulating Arrays

Arrays are typically traversed in sequential order using for-loops.
The for-each loop provides a simple way to iterate through the elements of an array

  1. String[] words = {"Arrays", " and ", "for-each"}
  2. String result = "";
  3. for (String element : words) {
  4. result += element;
  5. }
  6. System.out.println(result);

5.6 Array Resizing

• Cannot resize an array
• Can use the same reference variable to refer to an entirely new array:

  1. int myArray[] = new int[6];
  2. myArray = new int[10];

5.7 Coping Arrays

The System’s arraycopy method requires five arguments:

  1. public static void arraycopy(
  2. Object source, int srcIndex, Object dest, int destIndex, int length)

图片1.gif-4.1kB

92.png-6.4kB

91.png-24.2kB


5.8 Arrays of Arrays

• Arrays of arrays:

  1. int [][] twoDim = new int [4][];
  2. twoDim[0] = new int[5];
  3. twoDim[1] = new int[5];

• Non-rectangular arrays of arrays:

  1. twoDim[0] = new int[2];
  2. twoDim[1] = new int[4];
  3. twoDim[2] = new int[6];
  4. twoDim[3] = new int[8];

• Array of four arrays of five integers each:

  1. int [][] twoDim = new int[4][21];
  2. int [][] twoDim = new int [][22]; //illegal
  3. int [][] a = {{2,3}, {1,5}, {3,4}};

Chapter 6 Inheritence


6.1 Inheritence

Definition: A subclass is a class that extends another class. A subclass inherits state and behavior from all of its ancestors. The term "superclass" refers to a class's direct ancestor as well as to all of its ascendant classes。

  1. < modifier> class < name> [extends < superclass>] {< declarations>*}

Excepting Object, which has no superclass, every class has one and only one direct superclass (single inheritance). In the absence of any other explicit superclass, every class is implicitly a subclass of Object.
classes-object.gif-16kB

Classes can be derived from classes that are derived from classes that are derived from classes, and so on, and ultimately derived from the topmost class, Object. Such a class is said to be descended from all the classes in the inheritance chain stretching back to Object.

The idea of inheritance is simple but powerful: When you want to create a new class and there is already a class that includes some of the code that you want, you can derive your new class from the existing class. In doing this, you can reuse the fields and methods of the existing class without having to write (and debug!) them yourself.

A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

The Benefits of Inheritance
We dramatically reduce code redundancy,Subclasses are much more succinct than they would be without inheritance.

Through inheritance, we can reuse and extend code that has already been thoroughly tested without modifying it.

Best of all, we can derive a new class from an existing class even if we don’t own the source code for the latter!

Rules for Deriving Classes:
We may extend the superclass by adding features.
We also may specialize the way that a subclass performs one or more of the services inherited from its superclass.

What Members Does a Subclass Inherit?

Override
A subclass can modify behavior inherited from a parent class.

• A subclass can create a method with different functionality than the parent's method but with the same:

Name
Return type
Argument list

可以变宽不能变窄

Instance Methods
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method.

The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This subtype is called a covariant return type.

When overriding a method, you might want to use the @Override annotation that instructs the compiler that you intend to override a method in the superclass. If, for some reason, the compiler detects that the method does not exist in one of the superclasses, then it will generate an error. For more information on @Override, see Annotations.

Static Methods
If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.
The distinction between hiding a static method and overriding an instance method has important implications:

The version of the overridden instance method that gets invoked is the one in the subclass.
The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.

Consider an example that contains two classes. The first is Animal, which contains one instance method and one static method:

  1. public class Animal {
  2. public static void testClassMethod() {
  3. System.out.println("The static method in Animal");
  4. }
  5. public void testInstanceMethod() {
  6. System.out.println("The instance method in Animal");
  7. }
  8. }

The second class, a subclass of Animal, is called Cat:

  1. public class Cat extends Animal {
  2. public static void testClassMethod() {
  3. System.out.println("The static method in Cat");
  4. }
  5. public void testInstanceMethod() {
  6. System.out.println("The instance method in Cat");
  7. }
  8. public static void main(String[] args) {
  9. Cat myCat = new Cat();
  10. Animal myAnimal = myCat;
  11. Animal.testClassMethod();
  12. myAnimal.testInstanceMethod();
  13. }
  14. }

The Cat class overrides the instance method in Animal and hides the static method in Animal. The main method in this class creates an instance of Cat and invokes testClassMethod() on the class and testInstanceMethod() on the instance.

The output from this program is as follows:

The static method in Animal
The instance method in Cat

As promised, the version of the hidden static method that gets invoked is the one in the superclass, and the version of the overridden instance method that gets invoked is the one in the subclass.

Static methods in interfaces are never inherited.

Summary
The following table summarizes what happens when you define a method with the same signature as a method in a superclass.
Defining a Method with the Same Signature as a Superclass's Method

Superclass Instance Method Superclass Static Method
Subclass Instance Method Overrides Generates a compile-time error
Subclass Static Method Generates a compile-time error Hides

6.2 Super keyword

Reusing Superclass Behaviors: The “super”Keyword.
• super is used in a class to refer to its superclass.
• super is used to refer to the members of superclass,both data attributes and methods.

Accessing Superclass Members
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged). Consider this class, Superclass:

  1. public class Superclass {
  2. public void printMethod() {
  3. System.out.println("Printed in Superclass.");
  4. }
  5. }

Here is a subclass, called Subclass, that overrides printMethod():

  1. public class Subclass extends Superclass {
  2. // overrides printMethod in Superclass
  3. public void printMethod() {
  4. super.printMethod();
  5. System.out.println("Printed in Subclass");
  6. }
  7. public static void main(String[] args) {
  8. Subclass s = new Subclass();
  9. s.printMethod();
  10. }
  11. }

Within Subclass, the simple name printMethod() refers to the one declared in Subclass, which overrides the one in Superclass. So, to refer to printMethod() inherited from Superclass, Subclass must use a qualified name, using super as shown. Compiling and executing Subclass prints the following:

Printed in Superclass.
Printed in Subclass

Subclass Constructors
The following example illustrates how to use the super keyword to invoke a superclass's constructor. Recall from the Bicycle example that MountainBike is a subclass of Bicycle. Here is the MountainBike (subclass) constructor that calls the superclass constructor and then adds initialization code of its own:

  1. public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) {
  2. super(startCadence, startSpeed, startGear);
  3. seatHeight = startHeight;
  4. }

Invocation of a superclass constructor must be the first line in the subclass constructor.
The syntax for calling a superclass constructor is

  1. super();

or:

  1. super(parameter list);

With super(), the superclass no-argument constructor is called. With super(parameter list), the superclass constructor with a matching parameter list is called.

Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.

If a subclass constructor invokes a constructor of its superclass, either explicitly or implicitly, you might think that there will be a whole chain of constructors called, all the way back to the constructor of Object. In fact, this is the case. It is called constructor chaining, and you need to be aware of it when there is a long line of class descent.

Inheritance and Constructors
the super(...) syntax, the call must be the first statement in the subclass constructor.If we write a constructor without an explicit call to super(args),the parameterless constructor for the superclass is called automatically. If there no parameterless constructor in superclass ,then error occur


6.3 Multiple Inheritance

there are many complications inherent in multiple inheritance—so many, in fact, that the Java language designers chose not to support multiple inheritance.


6.4 Instanceof operator

test whether a given object reference belongs to a particular class is via the instanceof operator.

  1. object instanceof ClassX

For example:

  1. public class Employee extends Object
  2. public class Manager extends Employee
  3. public class Engineer extends Employee
  4. --------------------------------------- -
  5. public void doSomething( Employee e) {
  6. if (e instanceof Manager) {
  7. // Process a Manager
  8. } else if (e instanceof Engineer) {
  9. // Process an Engineer
  10. } else {
  11. // Process any other type of Employee
  12. }
  13. }

6.5 Casting Objects

Although it is always legal to cast a subclass reference to a superclass reference, the reverse is not always legal.

  1. Person person = new Employee("Joe Smith", "100 Main Ave", 3000.0);
  2. String name = person.getName(); // legal
  3. String address = person.getAddress(); // legal
  4. Employee employee = (Employee) person;
  5. double salary = employee.getSalary();
  6. // or
  7. double salary = ((Employee) person).getSalary();
  8. ---------------------------------------------------------------------------------
  9. Person person = new Person ("Joe Smith", "100 Main Ave");
  10. // illegal
  11. double salary = ((Employee) person).getSalary();

6.6 The Object Class

The Object class, in the java.lang package, sits at the top of the class hierarchy tree. Every class is a descendant, direct or indirect, of the Object class. Every class you use or write inherits the instance methods of Object. You need not use any of these methods, but, if you choose to do so, you may need to override them with code that is specific to your class. The methods inherited from Object that are discussed in this section are:

  1. protected Object clone() throws CloneNotSupportedException
  2. Creates and returns a copy of this object.
  3. public boolean equals(Object obj)
  4. Indicates whether some other object is "equal to" this one.
  5. protected void finalize() throws Throwable
  6. Called by the garbage collector on an object when garbage
  7. collection determines that there are no more references to the object
  8. public final Class getClass()
  9. Returns the runtime class of an object.
  10. public int hashCode()
  11. Returns a hash code value for the object.
  12. public String toString()
  13. Returns a string representation of the object.

The notify, notifyAll, and wait methods of Object all play a part in synchronizing the activities of independently running threads in a program, which is discussed in a later lessonand won't be covered here. There are five of these methods:

  1. public final void notify()
  2. public final void notifyAll()
  3. public final void wait()
  4. public final void wait(long timeout)
  5. public final void wait(long timeout, int nanos)

The equals() Method
The equals() method compares two objects for equality and returns true if they are equal. The equals() method provided in the Object class uses the identity operator (==) to determine whether two objects are equal. For primitive data types, this gives the correct result. For objects, however, it does not. The equals() method provided by Object tests whether the object references are equal—that is, if the objects compared are the exact same object.

To test whether two objects are equal in the sense of equivalency (containing the same information), you must override the equals() method.

You should always override the equals() method if the identity operator is not appropriate for your class.

Note: If you override equals(), you must override hashCode() as well.

The == operator determines if two references are identical to each other (that is, refer to the same object).

The equals method determines if objects are “equal” but not necessarily identical.

The Object implementation of the equals method uses the == operator.

User classes can override the equals method to implement a specific test for equality.

The getClass() Method

You cannot override getClass.
The getClass() method returns a Class object, which has methods you can use to get information about the class, such as its name (getSimpleName()), its superclass (getSuperclass()), and the interfaces it implements (getInterfaces()). For example, the following method gets and displays the class name of an object:

  1. void printClassName(Object obj) {
  2. System.out.println("The object's" + " class is " + obj.getClass().getSimpleName());
  3. }

The Class class, in the java.lang package, has a large number of methods (more than 50). For example, you can test to see if the class is an annotation (isAnnotation()), an interface (isInterface()), or an enumeration (isEnum()). You can see what the object's fields are (getFields()) or what its methods are (getMethods()), and so on.

One handy use of a Class object is to create a new instance of a class without knowing what the class is at compile time.

  1. Object createNewInstanceOf(Object obj) {
  2. return obj.getClass().newInstance();
  3. }

The toString() Method
You should always consider overriding the toString() method in your classes.
The Object's toString() method returns a String representation of the object, which is very useful for debugging. The String representation for an object depends entirely on the object, which is why you need to override toString() in your classes.

You can use toString() along with System.out.println() to display a text representation of an object.


6.7 Overloading Method

In some circumstances, you might want to write several methods in the same class that do basically the same job with different arguments
1.png-13.3kB


6.8 Wrapper Classes

The Java programming language provides wrapper classes to manipulate primitive data elements as objects.( in java.lang package)

2.png-35.3kB


6.9 Polymorphism

The dictionary definition of polymorphism refers to a principle in biology in which an organism or species can have many different forms or stages. This principle can also be applied to object-oriented programming and languages like the Java language. Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class.

The term polymorphism refers to the ability of two or more objects belonging to different classes to respond to exactly the same message (method call) in different class-specific ways.

  1. class A{
  2. void callme( ){
  3. System.out.println("Inside A's callme( ) method");
  4. }
  5. }
  6.  
  7. class B extends A{
  8. void callme( ){
  9. System.out.println("Inside B's callme( ) method");
  10. }
  11. }
  12.  
  13. public class Dispatch{
  14. public static void main( String args[ ] ){
  15. A a = new B( );
  16. a.callme( );
  17. }
  18. }

Outcome is: Inside B's callme( ) method

Polymorphism can be demonstrated with a minor modification to the Bicycle class. For example, a printDescription method could be added to the class that displays all the data currently stored in an instance.

  1. public void printDescription(){
  2. System.out.println("\nBike is " + "in gear " + this.gear + " with a cadence of " + this.cadence + " and travelling at a speed of " + this.speed + ". ");
  3. }

To demonstrate polymorphic features in the Java language, extend the Bicycle class with a MountainBike and a RoadBike class. For MountainBike, add a field for suspension, which is a String value that indicates if the bike has a front shock absorber, Front. Or, the bike has a front and back shock absorber, Dual.

Here is the updated class:

  1. public class MountainBike extends Bicycle {
  2. private String suspension;
  3. public MountainBike( int startCadence, int startSpeed, int startGear, String suspensionType){ super(startCadence, startSpeed, startGear);
  4. this.setSuspension(suspensionType);
  5. }
  6. public String getSuspension(){
  7. return this.suspension;
  8. }
  9. public void setSuspension(String suspensionType) {
  10. this.suspension = suspensionType;
  11. }
  12. public void printDescription() {
  13. super.printDescription();
  14. System.out.println("The " + "MountainBike has a" + getSuspension() + " suspension.");
  15. }
  16. }

Note the overridden printDescription method. In addition to the information provided before, additional data about the suspension is included to the output.

Next, create the RoadBike class. Because road or racing bikes have skinny tires, add an attribute to track the tire width. Here is the RoadBike class:

  1. public class RoadBike extends Bicycle{
  2. // In millimeters (mm)
  3. private int tireWidth;
  4. public RoadBike(int startCadence, int startSpeed, int startGear, int newTireWidth){
  5. super(startCadence, startSpeed, startGear);
  6. this.setTireWidth(newTireWidth);
  7. }
  8. public int getTireWidth(){
  9. return this.tireWidth;
  10. }
  11. public void setTireWidth(int newTireWidth){
  12. this.tireWidth = newTireWidth;
  13. }
  14. public void printDescription(){
  15. super.printDescription();
  16. System.out.println("The RoadBike" + " has " + getTireWidth() + " MM tires.");
  17. }
  18. }

Note that once again, the printDescription method has been overridden. This time, information about the tire width is displayed.

To summarize, there are three classes: Bicycle, MountainBike, and RoadBike. The two subclasses override the printDescription method and print unique information.

Here is a test program that creates three Bicycle variables. Each variable is assigned to one of the three bicycle classes. Each variable is then printed.

  1. public class TestBikes {
  2. public static void main(String[] args){
  3. Bicycle bike01, bike02, bike03;
  4. bike01 = new Bicycle(20, 10, 1);
  5. bike02 = new MountainBike(20, 10, 5, "Dual");
  6. bike03 = new RoadBike(40, 20, 8, 23);
  7. bike01.printDescription();
  8. bike02.printDescription();
  9. bike03.printDescription();
  10. }
  11. }

The following is the output from the test program:
Bike is in gear 1 with a cadence of 20 and travelling at a speed of 10.
Bike is in gear 5 with a cadence of 20 and travelling at a speed of 10.
The MountainBike has a Dual suspension.
Bike is in gear 8 with a cadence of 40 and travelling at a speed of 20.
The RoadBike has 23 MM tires.

捕获1.JPG-18.9kB

捕获2.JPG-79.2kB

捕获.JPG-81.9kB


Chapter 7 Advanced Class Features


7.1 Static

The static keyword is used as a modifier on variables,methods.
• The static keyword declares the attribute or method is associated with the class as a whole rather than any particular instance of that class.
• Thus static members are often called “class members,” such as “class attributes” or “class methods.”

Instance variable/method Class Variable/method
Whenever an instance of that class is created, memory is allocated for the instance variable; each instance of the class will have its own copy of the instance variable. Only one copy of a class variable will ever exist. That copy is shared by all instances of the class. Class variable can be accessed from outside the class if marked as public without an instance of the class.
instance method can access both instance and class variables. A class method is a method that can access only class variables.Since class variables and class methods are not associated with any particular object, they can be used even when no objects of the class exist!class methods can be invoked on the class, you don't need an instance to call a class method.

Class variables are often used with final to define constants; this is more memory efficient than final instance variables because constants can't change, so you really only need one copy

  1. protected static final String DISABLE = "disable";

Initializing Instance and Class Members
You can use static initializers and instance initializers to provide initial values for class and instance members when you declare them in a class:

  1. class BedAndBreakfast {
  2. static final int MAX_CAPACITY = 10; boolean full = false;
  3. }

This works well for members of primitive data type. Sometimes, it even works when creating arrays and objects. But this form of initialization has limitations, as follows:

To initialize an instance variable and cannot do it in the variable declaration for the reasons cited previously, then put the initialization in the constructor(s) for the class.

Using Static Initialization Blocks
A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:

  1. static { // whatever code is needed for initialization goes here}

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
• A class can contain code in a static block that does not exist within a method body.
• Static block code executes only once, when the class is loaded.
• A static block is usually used to initialize static (class) attributes


7.2 final

• You cannot subclass a final class.
• You cannot override a final method.
• A final variable is a constant.

Final variable
A final variable is a variable that can be assigned a value only once in a program; after that first assignment,
the variable’s value cannot be changed.

Public Static Final Variables and Interfaces
Interfaces are allowed to declare public static final variables to serve as global constants—that is, constant values that are in scope and hence accessible throughout an entire application.

Final class
You can declare that your class is final, that is, that your class cannot be subclassed. There are (at least) two reasons why you might want to do this:

Final Methods
You might wish to make a method final if it has an implementation that should not be changed and it is critical to the consistent state of the object

  1. final returnType finalMethod ( [paramlist] ){
  2. ……
  3. }

7.3 Abstract class

An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.

An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon), like this:

  1. abstract void moveTo(double deltaX, double deltaY);

If a class includes abstract methods, then the class itself must be declared abstract, as in:

  1. public abstract class GraphicObject {
  2. // declare fields
  3. // declare nonabstract methods
  4. abstract void draw();
  5. }

When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, then the subclass must also be declared abstract.

Note: Methods in an interface (see the Interfaces section) that are not declared as default or static are implicitly abstract, so the abstract modifier is not used with interface methods. (It can be used, but it is unnecessary.)

  1. Whenever a class contains one or more abstract methods, then we must declare the class abstract
  2. Note that it isn’t necessary for all of the methods in an abstract class to be abstract;
  3. An abstract class does not have to have abstract methods
  4. An abstract method must be declared in an abstract class
  5. No instance of an abstract class can be created.
  6. If a subclass of an abstract class does not implement all abstract methods inherited from its parent, the subclass must also be defined as abstract.
  7. An abstract class has one purpose: to act as the superclass of a class hierarchy.

7.4 Interface

In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces.

Defining an interface is similar to creating a new class:

  1. public interface OperateCar {
  2. // constant declarations, if any
  3. // method signatures
  4. // An enum with values RIGHT, LEFT
  5. int turn(Direction direction, double radius, double startSpeed, double endSpeed);
  6. int changeLanes(Direction direction, double startSpeed, double endSpeed);
  7. int signalTurn(Direction direction, boolean signalOn);
  8. int getRadarFront(double distanceToCar, double speedOfCar);
  9. int getRadarRear(double distanceToCar, double speedOfCar);
  10. ......
  11. // more method signatures
  12. }

Note that the method signatures have no braces and are terminated with a semicolon.

To use an interface, you write a class that implements the interface. When an instantiable class implements an interface, it provides a method body for each of the methods declared in the interface. For example,

  1. public class OperateBMW760i implements OperateCar {
  2. // the OperateCar method signatures, with implementation --
  3. // for example:
  4. int signalTurn(Direction direction, boolean signalOn) {
  5. // code to turn BMW's LEFT turn indicator lights on
  6. // code to turn BMW's LEFT turn indicator lights off
  7. // code to turn BMW's RIGHT turn indicator lights on
  8. // code to turn BMW's RIGHT turn indicator lights off
  9. }
  10. // other members, as needed -- for example, helper classes not
  11. // visible to clients of the interface
  12. }

In Java interfaces:
All methods in an interface are implicitly public and abstract. As a matter of style, the modifiers public and abstract are not used in an interface definition.

All data fields in an interface are implicitly public, static, and final. As a matter of style, the modifiers public, static, and final are not used in an interface definition.

An interface can extend another interface.

  1. public interface MyInterface extends InterfaceOne {
  2. void aMethod();
  3. }

class can only extend one class. In contrast, an interface can extend any number of interfaces:

  1. public interface MyInterface extends Interface1, Interface2 {
  2. void aMethod();
  3. }

If our intention is to declare a set of abstract method headers to a certain role within an application without imposing either data structure or concrete behavior on the subclasses, then the preferred way is interface.

An interface is more abstract than an abstract class.

Uses of Interfaces
• Simulating multiple inheritance by declaring a class that implements several interfaces
• Declaring methods that one or more classes are expected to implement
• Capturing similarities between unrelated classes without forcing a class relationship
• Determining an object’s programming interface without revealing the actual body of the class

Implementing Interfaces
When a class implements an interface, it agrees to implement all methods in the interface. If the class does not implement all the methods, the class must be defined as abstract.

Using an Interface as a Type
When you define a new interface, you are defining a new reference data type. You can use interface names anywhere you can use any other data type name.Only an instance of a class that implements the interface can be assigned to a reference variable whose type is an interface name.
Abstract Classes Compared to Interfaces
Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods. With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.

Which should you use, abstract classes or interfaces?
Consider using abstract classes if any of these statements apply to your situation:
You want to share code among several closely related classes.
You expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (such as protected and private).
You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong.
Consider using interfaces if any of these statements apply to your situation:
You expect that unrelated classes would implement your interface. For example, the interfacesComparable andCloneable are implemented by many unrelated classes.
You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.
You want to take advantage of multiple inheritance of type.
An example of an abstract class in the JDK isAbstractMap, which is part of the Collections Framework. Its subclasses (which include HashMap, TreeMap, and ConcurrentHashMap) share many methods (including get, put, isEmpty, containsKey, and containsValue) that AbstractMap defines.
An example of a class in the JDK that implements several interfaces is HashMap, which implements the interfaces Serializable, Cloneable, and Map. By reading this list of interfaces, you can infer that an instance of HashMap (regardless of the developer or company who implemented the class) can be cloned, is serializable (which means that it can be converted into a byte stream; see the sectionSerializable Objects), and has the functionality of a map. In addition, the Map interface has been enhanced with many default methods such as merge and forEach that older classes that have implemented this interface do not have to define.
Note that many software libraries use both abstract classes and interfaces; the HashMap class implements several interfaces and also extends the abstract class AbstractMap.

Comparing Abstract Classes and Interfaces

  • There are significant differences between abstract classes and interfaces:
  • An abstract class can define instance variables, whereas an interface cannot.
  • An abstract class can implement methods, whereas an interface cannot.
  • Interfaces do not contain constructors.
  • If a class extends an abstract class, it cannot extend another class; if a class implements an interface, it is free to extend another class and implement many other interfaces.
  • An abstract class should be used when some implementation details, like variables and method definitions, are common to all classes in a hierarchy. In such a case, the abstract class would be the root of the class hierarchy.
  • An interface should be used to define a behavior that must be implemented by classes in different hierarchies. Interfaces are the means by which unrelated classes tap the power of polymorphism because an interface—like a class—defines a type. This makes it possible for classes belonging to different hierarchies to be treated as instances of the same type.

7.5 Design Patterns

Design patterns describe practical solutions to common design problems that occur repeatedly in software development. A design pattern description consists of:

Design patterns document good design solutions that can be used for similar problems and form a shared vocabulary for problem-solving discussions.

Singleton Pattern

Description:

The singleton pattern ensures that only one instance of a class is created and provides a method to access that one instance.

Every object that uses an instance of a singleton class uses the same instance.
For example, an operating system should have only one system clock and a company should have only one accounting system.

Structure

In this pattern:

The static attribute instance contains the single instance of the class.

The constructor is defined as private so that other classes cannot create instances.

The static method getSingletonInstance returns the single instance of the class. The first time this method is called, it creates the single instance.

Consequences

The singleton pattern has the following benefits:

A singleton class can control how client code accesses the single instance. Client code does not have the freedom to use the new operator to create an instance of the singleton class. Instead, it must call a static method that returns a reference to the single instance.

A singleton class can be easily modified if requirements change and the application needs to limit the number of instances to a number other than one.

Strategy Pattern
In the strategy pattern,

each algorithm is encapsulated in its own class.

An interface that declares a method for executing an algorithm is created, and all the algorithm classes implement the interface.

Consequently, each algorithm class has its own version of the method.

When the need for a particular algorithm arises, the version of the method associated with that algorithm is invoked.


Chapter 8 Exception


8.1 What's an Exception?

*Definition: An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. *

When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.

After a method throws an exception, the runtime system attempts to find something to handle it. The set of possible "somethings" to handle the exception is the ordered list of methods that had been called to get to the method where the error occurred. The list of methods is known as the call stack (see the next figure).

exceptions-callstack.gif-14kB

The runtime system searches the call stack for a method that contains a block of code that can handle the exception. This block of code is called an exception handler. The search begins with the method in which the error occurred and proceeds through the call stack in the reverse order in which the methods were called. When an appropriate handler is found, the runtime system passes the exception to the handler. An exception handler is considered appropriate if the type of the exception object thrown matches the type that can be handled by the handler.

The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches all the methods on the call stack without finding an appropriate exception handler, as shown in the next figure, the runtime system (and, consequently, the program) terminates.

exceptions-errorOccurs.gif-16.8kB

Robust code handles failures gracefully: continuing execution despite the problem or terminating execution after displaying an error message.

Exception handling is a mechanism that allows failures to be handled outside the normal flow of the code. The resulting code is clear, easy to read, and easy to maintain.

exceptions-throwable.gif-11.9kB

Error Class
When a dynamic linking failure or other hard failure in the Java virtual machine occurs, the virtual machine throws an Error. Simple programs typically do not catch or throw Errors.

Exception Class
Most programs throw and catch objects that derive from the Exception class. An Exception indicates that a problem occurred, but it is not a serious system problem. Most programs you write will throw and catch Exceptions as opposed to Errors.

The Java platform defines the many descendants of the Exception class. These descendants indicate various types of exceptions that can occur. For example, IllegalAccessException signals that a particular method could not be found, and NegativeArraySizeException indicates that a program attempted to create an array with a negative size.

One Exception subclass, RuntimeException, is reserved for exceptions that indicate incorrect use of an API. An example of a runtime exception is NullPointerException, which occurs when a method tries to access a member of an object through a null reference. The section Unchecked Exceptions — The Controversy discusses why most applications shouldn't throw runtime exceptions or subclass RuntimeException.


8.2 How to handle Exception?

image_1ctt1issoarulqu1468h371dgmdh.png-42.7kB
image_1ctt1jobgr941j2ka4c1r2u15fodu.png-12.9kB


8.3 The Catch or Specify Requirement

Valid Java programming language code must honor the Catch or Specify Requirement. This means that code that might throw certain exceptions must be enclosed by either of the following:

A try statement that catches the exception. The try must provide a handler for the exception, as described in Catching and Handling Exceptions.
A method that specifies that it can throw the exception. The method must provide a throws clause that lists the exception, as described in Specifying the Exceptions Thrown by a Method.

Not all exceptions are subject to the Catch or Specify Requirement. To understand why, we need to look at the three basic categories of exceptions, only one of which is subject to the Requirement.

In Java, an exception is an object that describes an abnormal situation. An exception object contains the following information:

The kind of exception

A call stack which indicates where the exception occurred
A string with additional information about the exception

Exception objects are instances of classes that descend from class Throwable. Throwable has two subclasses: Error and Exception.

Exception objects are instances of classes that descend from class Throwable. Throwable has two subclasses: Error and Exception.

Java divides exceptions in two categories: checked exceptions and unchecked exceptions.

RuntimeException, Error and their subclasses are unchecked exceptions. All other exception classes are checked exceptions.

image_1ctt2henu1cc25ae1sm71ucp3jhh.png-50kB

The Three Kinds of Exceptions
The first kind of exception is the checked exception. These are exceptional conditions that a well-written application should anticipate and recover from. For example, suppose an application prompts a user for an input file name, then opens the file by passing the name to the constructor for java.io.FileReader. Normally, the user provides the name of an existing, readable file, so the construction of the FileReader object succeeds, and the execution of the application proceeds normally. But sometimes the user supplies the name of a nonexistent file, and the constructor throws java.io.FileNotFoundException. A well-written program will catch this exception and notify the user of the mistake, possibly prompting for a corrected file name.

Checked exceptions are subject to the Catch or Specify Requirement. All exceptions are checked exceptions, except for those indicated by Error, RuntimeException, and their subclasses.

The second kind of exception is the error. These are exceptional conditions that are external to the application, and that the application usually cannot anticipate or recover from. For example, suppose that an application successfully opens a file for input, but is unable to read the file because of a hardware or system malfunction. The unsuccessful read will throw java.io.IOError. An application might choose to catch this exception, in order to notify the user of the problem — but it also might make sense for the program to print a stack trace and exit.

Errors are not subject to the Catch or Specify Requirement. Errors are those exceptions indicated by Error and its subclasses.

The third kind of exception is the runtime exception. These are exceptional conditions that are internal to the application, and that the application usually cannot anticipate or recover from. These usually indicate programming bugs, such as logic errors or improper use of an API. For example, consider the application described previously that passes a file name to the constructor for FileReader. If a logic error causes a null to be passed to the constructor, the constructor will throw NullPointerException. The application can catch this exception, but it probably makes more sense to eliminate the bug that caused the exception to occur.

Runtime exceptions are not subject to the Catch or Specify Requirement. Runtime exceptions are those indicated by RuntimeException and its subclasses.

Errors and runtime exceptions are collectively known as unchecked exceptions.

Bypassing Catch or Specify
Some programmers consider the Catch or Specify Requirement a serious flaw in the exception mechanism and bypass it by using unchecked exceptions in place of checked exceptions. In general, this is not recommended. The section Unchecked Exceptions — The Controversy talks about when it is appropriate to use unchecked exceptions.


8.4 The try-catch-finally block

The try block
The first step in constructing an exception handler is to enclose the code that might throw an exception within a try block. In general, a try block looks like the following:

  1. try {
  2. code
  3. }
  4. catch and finally blocks . . .

The segment in the example labeled code contains one or more legal lines of code that could throw an exception. (The catch and finally blocks are explained in the next two subsections.)

If an exception occurs within the try block, that exception is handled by an exception handler associated with it. To associate an exception handler with a try block, you must put a catch block after it; the next section, The catch Blocks, shows you how.

The catch block
You associate exception handlers with a try block by providing one or more catch blocks directly after the try block. No code can be between the end of the try block and the beginning of the first catch block.

  1. try {
  2. } catch (ExceptionType name) {
  3. } catch (ExceptionType name) {
  4. }

Each catch block is an exception handler that handles the type of exception indicated by its argument. The argument type, ExceptionType, declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class. The handler can refer to the exception with name.

The catch block contains code that is executed if and when the exception handler is invoked. The runtime system invokes the exception handler when the handler is the first one in the call stack whose ExceptionType matches the type of the exception thrown. The system considers it a match if the thrown object can legally be assigned to the exception handler's argument.

Exception handlers can do more than just print error messages or halt the program. They can do error recovery, prompt the user to make a decision, or propagate the error up to a higher-level handler using chained exceptions, as described in the Chained Exceptions section.

Catching More Than One Type of Exception with One Exception Handler
In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.
In the catch clause, specify the types of exceptions that block can handle, and separate each exception type with a vertical bar (|):

  1. catch (IOException|SQLException ex) {
  2. logger.log(ex);
  3. throw ex;
  4. }

Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final. In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.

try block must be immediately followed by at least one catch or finally block.

As long as the code in the try block executes without error, all of the catch blocks are bypassed, and execution of our program continues after the end of the last catch block

图片51.png-32.8kB

If, on the other hand, an exception is thrown by the JVM while executing the try block, execution of the try block abruptly terminates as of the line on which the exception occurred.

图片61.png-48kB

The finally block
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.

The try block of the writeList method that you've been working with here opens a PrintWriter. The program should close that stream before exiting the writeList method. This poses a somewhat complicated problem because writeList's try block can exit in one of three ways.

Important: The finally block is a key tool for preventing resource leaks. When closing a file or otherwise recovering resources, place the code in a finally block to ensure that resource is always recovered.

Consider using the try-with-resources statement in these situations, which automatically releases system resources when no longer needed. The The try-with-resources Statement section has more information.

A try block may optionally have a finally block associated with it.

The code within a finally block is guaranteed to execute no matter what happens in the try/catch code that precedes :

The try block executes to completion without throwing any exceptions whatsoever.

The try block throws an exception that is handled by one of the catch blocks.

The try block throws an exception that is not handled by any of the catch blocks


8.5 The throws-clause

If a checked exception might occur in a method and the method does not have catch block to handle the checked exception, then the checked exception must be declared in the method header using a throws-clause,returnType methodName([paramlist]) throws exceptionList

Before you can catch an exception, some Java code somewhere must throw one.

图片71.png-224.8kB

Any Java code can throw an exception:

throw new ThrowableObject;

Example :

  1. public Object pop() throws EmptyStackException {
  2. Object obj;
  3. if (size == 0)
  4. throw new EmptyStackException();
  5. obj = objectAt(size - 1);
  6. setObjectAt(size - 1, null);
  7. size--;
  8. return obj;
  9. }

8.6 Method overriding and Exception

图片81.png-114.3kB

图片91.png-29.6kB


8.7 Creating your own Exception classes

When faced with choosing the type of exception to throw, you have two choices:
- Use one written by someone else. The Java development environment provides a lot of exception classes that you could use.
- Write one of your own.


8.8 Conclusion

By using exceptions to manage errors, Java programs have the following advantages over traditional error management techniques:


Chapter 9 Collections and Generics Framework


9.1 What is Collection?

A collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data.

Collections Organize References to Other Objects
The objects being organized by a collection live physically outside of the collection in the JVM’s memory; only their handles reside inside of the collection.

图片17.png-63.3kB

Collections Are Encapsulated
All collections provide, at a minimum, methods for

• Adding objects
• Removing objects
• Retrieving specific individual objects
• Iterating through the objects in some predetermined order
• Getting a count of the number of objects presently referenced by the collection
• Answering a true/false question as to whether a particular object’s reference is in the collection or not


9.2 What Is a Collections Framework?

A collections framework is a unified architecture for representing and manipulating collections. All collections frameworks contain the following:

Interfaces: These are abstract data types that represent collections. Interfaces allow collections to be manipulated independently of the details of their representation. In object-oriented languages, interfaces generally form a hierarchy.

Implementations: These are the concrete implementations of the collection interfaces. In essence, they are reusable data structures.

Algorithms: These are the methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. The algorithms are said to be polymorphic: that is, the same method can be used on many different implementations of the appropriate collection interface. In essence, algorithms are reusable functionality.

The core collections interfaces are shown below:

图片18.png-22.6kB colls-coreInterfaces.gif-13.3kB

A Set is a special kind of Collection, a SortedSet is a special kind of Set, and so forth.A Set is a Collection that cannot contain duplicate elements.Note also that the hierarchy consists of two distinct trees — a Map is not a true Collection.

Note that all the core collection interfaces are generic. For example, this is the declaration of the Collection interface.

public interface Collection...
The syntax tells you that the interface is generic. When you declare a Collection instance you can and should specify the type of object contained in the collection. Specifying the type allows the compiler to verify (at compile-time) that the type of object you put into the collection is correct, thus reducing errors at runtime. For information on generic types, see the Generics (Updated) lesson.

To keep the number of core collection interfaces manageable, the Java platform doesn't provide separate interfaces for each variant of each collection type. (Such variants might include immutable, fixed-size, and append-only.) Instead, the modification operations in each interface are designated optional — a given implementation may elect not to support all operations. If an unsupported operation is invoked, a collection throws an UnsupportedOperationException.

图片19.png-53.6kB

Implementations are responsible for documenting which of the optional operations they support. All of the Java platform's general-purpose implementations support all of the optional operations.

The following list describes the core collection interfaces:

Collection — the root of the collection hierarchy. A collection represents a group of objects known as its elements. The Collection interface is the least common denominator that all collections implement and is used to pass collections around and to manipulate them when maximum generality is desired. Some types of collections allow duplicate elements, and others do not. Some are ordered and others are unordered. The Java platform doesn't provide any direct implementations of this interface but provides implementations of more specific subinterfaces, such as Set and List.

SetAn unordered collection; no duplicates are permitted(a collection that cannot contain duplicate elements). This interface models the mathematical set abstraction and is used to represent sets, such as the cards comprising a poker hand, the courses making up a student's schedule, or the processes running on a machine.

Listan ordered collection (sometimes called a sequence). Lists can contain duplicate elements. The user of a List generally has precise control over where in the list each element is inserted and can access elements by their integer index (position). If you've used Vector, you're familiar with the general flavor of List. Also see The List Interface section.

Queue — a collection used to hold multiple elements prior to processing. Besides basic Collection operations, a Queue provides additional insertion, extraction, and inspection operations.

Queues typically, but do not necessarily, order elements in a FIFO (first-in, first-out) manner. Among the exceptions are priority queues, which order elements according to a supplied comparator or the elements' natural ordering. Whatever the ordering used, the head of the queue is the element that would be removed by a call to remove or poll. In a FIFO queue, all new elements are inserted at the tail of the queue. Other kinds of queues may use different placement rules. Every Queue implementation must specify its ordering properties.

Deque — a collection used to hold multiple elements prior to processing. Besides basic Collection operations, a Deque provides additional insertion, extraction, and inspection operations.

Deques can be used both as FIFO (first-in, first-out) and LIFO (last-in, first-out). In a deque all new elements can be inserted, retrieved and removed at both ends. Also see The Deque Interface section.

Map — an object that maps keys to values. A Map cannot contain duplicate keys; each key can map to at most one value. If you've used Hashtable, you're already familiar with the basics of Map. Also see The Map Interface section.

The last two core collection interfaces are merely sorted versions of Set and Map:
SortedSet — a Set that maintains its elements in ascending order. Several additional operations are provided to take advantage of the ordering. Sorted sets are used for naturally ordered sets, such as word lists and membership rolls. Also see The SortedSet Interface section.

SortedMap — a Map that maintains its mappings in ascending key order. This is the Map analog of SortedSet. Sorted maps are used for naturally ordered collections of key/value pairs, such as dictionaries and telephone directories. Also see The SortedMap Interface section.


9.3 The Collection Interface

The Collection interface contains methods that perform basic operations, such as int size(), boolean isEmpty(), boolean contains(Object element), boolean add(E element), boolean remove(Object element), and Iterator iterator().

It also contains methods that operate on entire collections, such as boolean containsAll(Collection c), boolean addAll(Collection c), boolean removeAll(Collection c), boolean retainAll(Collection c), and void clear().

Additional methods for array operations (such as Object[] toArray() and T[] toArray(T[] a) exist as well.

The Collection interface does about what you'd expect given that a Collection represents a group of objects. It has methods that tell you how many elements are in the collection (size, isEmpty), methods that check whether a given object is in the collection (contains), methods that add and remove an element from the collection (add, remove), and methods that provide an iterator over the collection (iterator).

The add method is defined generally enough so that it makes sense for collections that allow duplicates as well as those that don't. It guarantees that the Collection will contain the specified element after the call completes, and returns true if the Collection changes as a result of the call. Similarly, the remove method is designed to remove a single instance of the specified element from the Collection, assuming that it contains the element to start with, and to return true if the Collection was modified as a result.

Traversing Collections

There are three ways to traverse collections: (1) using aggregate operations (2) with the for-each construct and (3) by using Iterators.

Aggregate Operations
In JDK 8 and later, the preferred method of iterating over a collection is to obtain a stream and perform aggregate operations on it. Aggregate operations are often used in conjunction with lambda expressions to make programming more expressive, using less lines of code. The following code sequentially iterates through a collection of shapes and prints out the red objects:

  1. myShapesCollection.stream()
  2. .filter(e -> e.getColor() == Color.RED)
  3. .forEach(e -> System.out.println(e.getName()));

Likewise, you could easily request a parallel stream, which might make sense if the collection is large enough and your computer has enough cores:

  1. myShapesCollection.parallelStream()
  2. .filter(e -> e.getColor() == Color.RED)
  3. .forEach(e -> System.out.println(e.getName()));

There are many different ways to collect data with this API. For example, you might want to convert the elements of a Collection to String objects, then join them, separated by commas:

  1. String joined = elements.stream()
  2. .map(Object::toString)
  3. .collect(Collectors.joining(", "));

Or perhaps sum the salaries of all employees:

  1. int total = employees.stream()
  2. .collect(Collectors.summingInt(Employee::getSalary)));

These are but a few examples of what you can do with streams and aggregate operations.

The Collections framework has always provided a number of so-called "bulk operations" as part of its API. These include methods that operate on entire collections, such as containsAll, addAll, removeAll, etc. Do not confuse those methods with the aggregate operations that were introduced in JDK 8. The key difference between the new aggregate operations and the existing bulk operations (containsAll, addAll, etc.) is that the old versions are all mutative, meaning that they all modify the underlying collection. In contrast, the new aggregate operations do not modify the underlying collection. When using the new aggregate operations and lambda expressions, you must take care to avoid mutation so as not to introduce problems in the future, should your code be run later from a parallel stream.

for-each Construct
The for-each construct allows you to concisely traverse a collection or array using a for loop — see The for Statement. The following code uses the for-each construct to print out each element of a collection on a separate line.

  1. for (Object o : collection)
  2. System.out.println(o);

Iterators
An Iterator is an object that enables you to traverse through a collection and to remove elements from the collection selectively, if desired. You get an Iterator for a collection by calling its iterator method. The following is the Iterator interface.

  1. public interface Iterator<E> {
  2. boolean hasNext();
  3. E next();
  4. void remove(); //optional
  5. }

The hasNext method returns true if the iteration has more elements, and the next method returns the next element in the iteration. The remove method removes the last element that was returned by next from the underlying Collection. The remove method may be called only once per call to next and throws an exception if this rule is violated.

Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.

Use Iterator instead of the for-each construct when you need to:

The following method shows you how to use an Iterator to filter an arbitrary Collection — that is, traverse the collection removing specific elements.

  1. static void filter(Collection<?> c) {
  2. for (Iterator<?> it = c.iterator(); it.hasNext(); )
  3. if (!cond(it.next()))
  4. it.remove();
  5. }

This simple piece of code is polymorphic, which means that it works for any Collection regardless of implementation. This example demonstrates how easy it is to write a polymorphic algorithm using the Java Collections Framework.

Collection Interface Bulk Operations
Bulk(主体) operations perform an operation on an entire Collection. You could implement these shorthand operations using the basic operations, though in most cases such implementations would be less efficient. The following are the bulk operations:

The addAll, removeAll, and retainAll methods all return true if the target Collection was modified in the process of executing the operation.

As a simple example of the power of bulk operations, consider the following idiom to remove all instances of a specified element, e, from a Collection, c.

  1. c.removeAll(Collections.singleton(e));

More specifically, suppose you want to remove all of the null elements from a Collection.

  1. c.removeAll(Collections.singleton(null));

This idiom uses Collections.singleton, which is a static factory method that returns an immutable Set containing only the specified element.

Collection Interface Array Operations
The toArray methods are provided as a bridge between collections and older APIs that expect arrays on input. The array operations allow the contents of a Collection to be translated into an array. The simple form with no arguments creates a new array of Object. The more complex form allows the caller to provide an array or to choose the runtime type of the output array.

For example, suppose that c is a Collection. The following snippet dumps the contents of c into a newly allocated array of Object whose length is identical to the number of elements in c.

  1. Object[] a = c.toArray();

Suppose that c is known to contain only strings (perhaps because c is of type Collection). The following snippet dumps the contents of c into a newly allocated array of String whose length is identical to the number of elements in c.

  1. String[] a = c.toArray(new String[0]);

9.4 The Set Interface

A Set is a Collection that cannot contain duplicate elements. It models the mathematical set abstraction. The Set interface contains only methods inherited from Collection and adds the restriction that duplicate elements are prohibited. Set also adds a stronger contract on the behavior of the equals and hashCode operations, allowing Set instances to be compared meaningfully even if their implementation types differ. Two Set instances are equal if they contain the same elements.

The Java platform contains three general-purpose Set implementations: HashSet, TreeSet, and LinkedHashSet. HashSet, which stores its elements in a hash table, is the best-performing implementation; however it makes no guarantees concerning the order of iteration. TreeSet, which stores its elements in a red-black tree, orders its elements based on their values; it is substantially slower than HashSet. LinkedHashSet, which is implemented as a hash table with a linked list running through it, orders its elements based on the order in which they were inserted into the set (insertion-order). LinkedHashSet spares its clients from the unspecified, generally chaotic ordering provided by HashSet at a cost that is only slightly higher.


9.5 The List Interface

A List is an ordered Collection (sometimes called a sequence). Lists may contain duplicate elements. In addition to the operations inherited from Collection, the List interface includes operations for the following:

  • Positional access — manipulates elements based on their numerical position in the list. This includes methods such as get, set, add, addAll, and remove.
  • Search — searches for a specified object in the list and returns its numerical position. Search methods include indexOf and lastIndexOf.
  • Iteration — extends Iterator semantics to take advantage of the list's sequential nature. The listIterator methods provide this behavior.
  • Range-view — The sublist method performs arbitrary range operations on the list.

The Java platform contains two general-purpose List implementations. ArrayList, which is usually the better-performing implementation, and LinkedList which offers better performance under certain circumstances.

Iterators
As you'd expect, the Iterator returned by List's iterator operation returns the elements of the list in proper sequence. List also provides a richer iterator, called a ListIterator, which allows you to traverse the list in either direction, modify the list during iteration, and obtain the current position of the iterator.

The three methods that ListIterator inherits from Iterator (hasNext, next, and remove) do exactly the same thing in both interfaces. The hasPrevious and the previous operations are exact analogues of hasNext and next. The former operations refer to the element before the (implicit) cursor, whereas the latter refer to the element after the cursor. The previous operation moves the cursor backward, whereas next moves it forward.
Here's the standard idiom for iterating backward through a list.

  1. for (ListIterator<Type> it = list.listIterator(list.size()); it.hasPrevious(); ) {
  2. Type t = it.previous();
  3. ...
  4. }

Note the argument to listIterator in the preceding idiom. The List interface has two forms of the listIterator method. The form with no arguments returns a ListIterator positioned at the beginning of the list; the form with an int argument returns a ListIterator positioned at the specified index. The index refers to the element that would be returned by an initial call to next. An initial call to previous would return the element whose index was index-1. In a list of length n, there are n+1 valid values for index, from 0 to n, inclusive.
Intuitively speaking, the cursor is always between two elements — the one that would be returned by a call to previous and the one that would be returned by a call to next. The n+1 valid index values correspond to the n+1 gaps between elements, from the gap before the first element to the gap after the last one. The following figure shows the five possible cursor positions in a list containing four elements.
20.png-9.5kB

The five possible cursor positions.

Calls to next and previous can be intermixed, but you have to be a bit careful. The first call to previous returns the same element as the last call to next. Similarly, the first call to next after a sequence of calls to previous returns the same element as the last call to previous.

Scanner 实现了所有的Iterator接口


9.6 The Map Interface

A Map is an object that maps keys to values. A map cannot contain duplicate keys: Each key can map to at most one value.

图片23.png-45.5kB

It models the mathematical function abstraction. The Map interface includes methods for basic operations (such as put, get, remove, containsKey, containsValue, size, and empty), bulk operations (such as putAll and clear), and collection views (such as keySet, entrySet, and values).

图片21.png-29.1kB

图片26.png-12.3kB

The Java platform contains three general-purpose Map implementations: HashMap, TreeMap, and LinkedHashMap. Their behavior and performance are precisely analogous to HashSet, TreeSet, and LinkedHashSet, as described in The Set Interface section.

• TreeMaps are very similar to HashMaps,with one notable difference:
• TreeMap:objects are automatically retrieved from the collection in ascending key (sorted) order.
• HashMap:there’s no guarantee the order

图片22.png-65.9kB


9.7 Generics

Generics are described as follows:

图片24.png-15.7kB

图片25.png-119.2kB


9.8 The comparable and comparator interfaces

A List l may be sorted as follows.

  1. Collections.sort(l);

If the List consists of String elements, it will be sorted into alphabetical order. If it consists of Date elements, it will be sorted into chronological order. How does this happen? String and Date both implement the Comparable interface. Comparable implementations provide a natural ordering for a class, which allows objects of that class to be sorted automatically. The following table summarizes some of the more important Java platform classes that implement Comparable.

图片27.JPG-73.9kB

If you try to sort a list, the elements of which do not implement Comparable, Collections.sort(list) will throw a ClassCastException. Similarly, Collections.sort(list, comparator) will throw a ClassCastException if you try to sort a list whose elements cannot be compared to one another using the comparator. Elements that can be compared to one another are called mutually comparable. Although elements of different types may be mutually comparable, none of the classes listed here permit interclass comparison.

图片27.png-22.6kB

This is all you really need to know about the Comparable interface if you just want to sort lists of comparable elements or to create sorted collections of them. The next section will be of interest to you if you want to implement your own Comparable type.

The Comparable interface supports one method: compareTo.

图片28.png-10.9kB

method compares this object to the element parameter.
If this is a "less than" element, then a negative value is returned;
if this is a "greater than" element, then a positive value is returned;
otherwise zero is

00.JPG-53.9kB

图片29.png-26.2kB

图片30.png-14.3kB

Writing Your Own Comparable Types
The Comparable interface consists of the following method.

  1. public interface Comparable<T> {
  2. public int compareTo(T o);
  3. }

The compareTo method compares the receiving object with the specified object and returns a negative integer, 0, or a positive integer depending on whether the receiving object is less than, equal to, or greater than the specified object. If the specified object cannot be compared to the receiving object, the method throws a ClassCastException.
The following class representing a person's name implements Comparable.

  1. import java.util.*;
  2. public class Name implements Comparable<Name> {
  3. private final String firstName, lastName;
  4. public Name(String firstName, String lastName) {
  5. if (firstName == null || lastName == null)
  6. throw new NullPointerException();
  7. this.firstName = firstName;
  8. this.lastName = lastName;
  9. }
  10. public String firstName() { return firstName; }
  11. public String lastName() { return lastName; }
  12. public boolean equals(Object o) {
  13. if (!(o instanceof Name))
  14. return false;
  15. Name n = (Name) o;
  16. return n.firstName.equals(firstName) && n.lastName.equals(lastName);
  17. }
  18. public int hashCode() {
  19. return 31*firstName.hashCode() + lastName.hashCode();
  20. }
  21. public String toString() {
  22. return firstName + " " + lastName;
  23. }
  24. public int compareTo(Name n) {
  25. int lastCmp = lastName.compareTo(n.lastName);
  26. return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName));
  27. }
  28. }

Since this section is about element ordering, let's talk a bit more about Name's compareTo method. It implements the standard name-ordering algorithm, where last names take precedence over first names. This is exactly what you want in a natural ordering. It would be very confusing indeed if the natural ordering were unnatural!

Take a look at how compareTo is implemented, because it's quite typical. First, you compare the most significant part of the object (in this case, the last name). Often, you can just use the natural ordering of the part's type. In this case, the part is a String and the natural (lexicographic) ordering is exactly what's called for. If the comparison results in anything other than zero, which represents equality, you're done: You just return the result. If the most significant parts are equal, you go on to compare the next most-significant parts. In this case, there are only two parts — first name and last name. If there were more parts, you'd proceed in the obvious fashion, comparing parts until you found two that weren't equal or you were comparing the least-significant parts, at which point you'd return the result of the comparison.
Just to show that it all works, here's a program that builds a list of names and sorts them.

  1. import java.util.*;
  2. public class NameSort {
  3. public static void main(String[] args) {
  4. Name nameArray[] = {
  5. new Name("John", "Smith"),
  6. new Name("Karl", "Ng"),
  7. new Name("Jeff", "Smith"),
  8. new Name("Tom", "Rich")
  9. };
  10. List<Name> names = Arrays.asList(nameArray);
  11. Collections.sort(names);
  12. System.out.println(names);
  13. }
  14. }

If you run this program, here's what it prints.
[Karl Ng, Tom Rich, Jeff Smith, John Smith]

Comparators
What if you want to sort some objects in an order other than their natural ordering? Or what if you want to sort some objects that don't implement Comparable? To do either of these things, you'll need to provide a Comparator — an object that encapsulates an ordering. Like the Comparable interface, the Comparator interface consists of a single method.

图片31.png-22kB

  1. public interface Comparator<T> {
  2. int compare(T o1, T o2);
  3. }

The compare method compares its two arguments, returning a negative integer, 0, or a positive integer depending on whether the first argument is less than, equal to, or greater than the second. If either of the arguments has an inappropriate type for the Comparator, the compare method throws a ClassCastException.

Much of what was said about Comparable applies to Comparator as well. Writing a compare method is nearly identical to writing a compareTo method, except that the former gets both objects passed in as arguments. The compare method has to obey the same four technical restrictions as Comparable's compareTo method for the same reason — a Comparator must induce a total order on the objects it compares.

Suppose you have a class called Employee, as follows.

  1. public class Employee implements Comparable<Employee> {
  2. public Name name() { ... }
  3. public int number() { ... }
  4. public Date hireDate() { ... }
  5. ...
  6. }

Let's assume that the natural ordering of Employee instances is Name ordering (as defined in the previous example) on employee name. Unfortunately, the boss has asked for a list of employees in order of seniority. This means we have to do some work, but not much. The following program will produce the required list.

  1. import java.util.*;
  2. public class EmpSort {
  3. static final Comparator<Employee> SENIORITY_ORDER =
  4. new Comparator<Employee>() {
  5. public int compare(Employee e1, Employee e2) {
  6. return e2.hireDate().compareTo(e1.hireDate());
  7. }
  8. };
  9. // Employee database
  10. static final Collection<Employee> employees = ... ;
  11. public static void main(String[] args) {
  12. List<Employee> e = new ArrayList<Employee>(employees);
  13. Collections.sort(e, SENIORITY_ORDER);
  14. System.out.println(e);
  15. }
  16. }

The Comparator in the program is reasonably straightforward. It relies on the natural ordering of Date applied to the values returned by the hireDate accessor method. Note that the Comparator passes the hire date of its second argument to its first rather than vice versa. The reason is that the employee who was hired most recently is the least senior; sorting in the order of hire date would put the list in reverse seniority order. Another technique people sometimes use to achieve this effect is to maintain the argument order but to negate the result of the comparison.

  1. // Don't do this!!
  2. return -r1.hireDate().compareTo(r2.hireDate());

You should always use the former technique in favor of the latter because the latter is not guaranteed to work. The reason for this is that the compareTo method can return any negative int if its argument is less than the object on which it is invoked. There is one negative int that remains negative when negated, strange as it may seem.

-Integer.MIN_VALUE == Integer.MIN_VALUE
The Comparator in the preceding program works fine for sorting a List, but it does have one deficiency: It cannot be used to order a sorted collection, such as TreeSet, because it generates an ordering that is not compatible with equals. This means that this Comparator equates objects that the equals method does not. In particular, any two employees who were hired on the same date will compare as equal. When you're sorting a List, this doesn't matter; but when you're using the Comparator to order a sorted collection, it's fatal. If you use this Comparator to insert multiple employees hired on the same date into a TreeSet, only the first one will be added to the set; the second will be seen as a duplicate element and will be ignored.

To fix this problem, simply tweak the Comparator so that it produces an ordering that is compatible with equals. In other words, tweak it so that the only elements seen as equal when using compare are those that are also seen as equal when compared using equals. The way to do this is to perform a two-part comparison (as for Name), where the first part is the one we're interested in — in this case, the hire date — and the second part is an attribute that uniquely identifies the object. Here the employee number is the obvious attribute. This is the Comparator that results.

  1. static final Comparator<Employee> SENIORITY_ORDER =
  2. new Comparator<Employee>() {
  3. public int compare(Employee e1, Employee e2) {
  4. int dateCmp = e2.hireDate().compareTo(e1.hireDate());
  5. if (dateCmp != 0)
  6. return dateCmp;
  7. return (e1.number() < e2.number() ? -1 :
  8. (e1.number() == e2.number() ? 0 : 1));
  9. }
  10. };

One last note: You might be tempted to replace the final return statement in the Comparator with the simpler:
return e1.number() - e2.number();

Don't do it unless you're absolutely sure no one will ever have a negative employee number! This trick does not work in general because the signed integer type is not big enough to represent the difference of two arbitrary signed integers. If i is a large positive integer and j is a large negative integer, i - j will overflow and will return a negative integer. The resulting comparator violates one of the four technical restrictions we keep talking about (transitivity) and produces horrible, subtle bugs. This is not a purely theoretical concern; people get burned by it.


Chapter 10 I/O:Reading and Writing


10.1 Overview of I/O Streams

To bring in information, a program opens a stream on an information source (a file, memory, a socket) and reads the information sequentially, as shown here:
图片1.png-7.1kB

Similarly, a program can send information to an external destination by opening a stream to a destination and writing the information out sequentially, like this:
![图片2.png-7.2kB]

No matter where the data is coming from or going to and no matter what its type, the algorithms for sequentially reading and writing data are basically the same:
图片3.png-12kB

The java.io package contains a collection of stream classes that support these algorithms for reading and writing.

The stream classes are divided into two class hierarchies, based on the data type (either characters or bytes) on which they operate.
图片4.png-10.5kB

Reader and Writer are the abstract superclasses for 16-bit character streams in java.io.

InputStream and OutputStream are the abstract superclasses for 8-bit byte streams in java.io.

These streams are typically used to read and write binary data such as images and sounds

图片5.png-18.4kB


10.2 Understanding the I/O Superclasses

Reader and InputStream define similar APIs but for different data types.
Reader contains these methods for reading characters and arrays of characters:
图片6.png-4.1kB
InputStream defines the same methods but for reading bytes and arrays of bytes:
图片7.png-2.8kB

图片8.png-8.8kB


10.3 Node streams and Process streams

Types of Node Streams
图片9.png-19.4kB

图片10.png-42.5kB
A processing stream performs some sort of conversion on another
stream. Processing streams are also known as filter streams.

This allows you to convert the raw data into a more usable form for your application.


10.4 File Stream I/O

  1. BufferedReader fileIn =
  2. new BufferedReader(new FileReader(filename));
  3. PrintWriter fileOut =
  4. new PrintWriter(new FileWriter(filename));

10.5 Scanner Class

图片11.png-40.4kB


10.6 RandomAccessFile

RandomAccessFile is used for both reading and writing files and it doesn't inherit from the InputStream or OutputStream.

RandomAccessFile supports the notion of a file pointer. The file pointer indicates the current location in the file. When the file is first created, the file pointer is set to 0, indicating the beginning of the file.Calls to the read and write methods adjust the file pointer by the number of bytes read or written.

Create a randomaccessfile
myRAFile = new RandomAccessFile(String name, String mode);
myRAFile = new RandomAccessFile(File file, String mode);

example:

  1. new RandomAccessFile("farrago.txt", "r");
  2. new RandomAccessFile("farrago.txt", "rw");

int skipBytes(int)--Moves the file pointer forward the specified number of bytes
void seek(long)--Positions the file pointer just before the specified byte
long getFilePointer()--Returns the current byte location of the file pointer


10.7 Serialization

图片12.png-26.9kB

图片13.png-123.7kB

图片14.png-63.2kB


Chapter 11 Swing


11.1 Top-Level Containers

Swing provides three generally useful top-level container classes: JFrame, JDialog, and JApplet.

When using these classes, you should keep these facts in mind:
To appear onscreen, every GUI component must be part of a containment hierarchy(层次结构). A containment hierarchy is a tree of components that has a top-level container as its root. We'll show you one in a bit.

Each GUI component can be contained only once. If a component is already in a container and you try to add it to another container, the component will be removed from the first container and then added to the second.

Each top-level container has a content pane that, generally speaking, contains (directly or indirectly) the visible components in that top-level container's GUI.

You can optionally add a menu bar to a top-level container. The menu bar is by convention positioned within the top-level container, but outside the content pane. Some look and feels, such as the Mac OS look and feel, give you the option of placing the menu bar in another place more appropriate for the look and feel, such as at the top of the screen.

TopLevelDemoMetal.png-6.6kB ConceptualPane.jpg-3.2kB

图片15.png-8.8kB

Top-Level Containers and Containment Hierarchies
Each program that uses Swing components has at least one top-level container. This top-level container is the root of a containment hierarchy — the hierarchy that contains all of the Swing components that appear inside the top-level container.
As a rule, a standalone application with a Swing-based GUI has at least one containment hierarchy with a JFrame as its root. For example, if an application has one main window and two dialogs, then the application has three containment hierarchies, and thus three top-level containers. One containment hierarchy has a JFrame as its root, and each of the other two has a JDialog object as its root.

Adding Components to the Content Pane
Here's the code that the preceding example uses to get a frame's content pane and add the yellow label to it:

  1. frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);

As the code shows, you find the content pane of a top-level container by calling the getContentPane method. The default content pane is a simple intermediate(中间) container that inherits from JComponent, and that uses a BorderLayout as its layout manager.

It's easy to customize(自定义)the content pane — setting the layout manager or adding a border, for example. However, there is one tiny gotcha(疑难杂症). The getContentPane method returns a Container object, not a JComponent object. This means that if you want to take advantage of the content pane's JComponent features, you need to either typecast the return value or create your own component to be the content pane. Our examples generally take the second approach, since it's a little cleaner. Another approach we sometimes take is to simply add a customized component to the content pane, covering the content pane completely.

Note that the default layout manager for JPanel is FlowLayout; you'll probably want to change it.

Adding a Menu Bar
To add a menu bar to a top-level container, create a JMenuBar object, populate it with menus, and then call setJMenuBar. The TopLevelDemo adds a menu bar to its frame with this code:

  1. frame.setJMenuBar(greenMenuBar);

A menu provides a space-saving way to let the user choose one of several options. Other components with which the user can make a one-of-many choice include combo boxes, lists, radio buttons, spinners, and tool bars. If any of your menu items performs an action that is duplicated by another menu item or by a tool-bar button.

Menus are unique in that, by convention, they aren't placed with the other components in the UI. Instead, a menu usually appears either in a menu bar or as a popup menu. A menu bar contains one or more menus and has a customary, platform-dependent location — usually along the top of a window. A popup menu is a menu that is invisible until the user makes a platform-specific mouse action, such as pressing the right mouse button, over a popup-enabled component. The popup menu then appears under the cursor.

The following figure shows many menu-related components: a menu bar, menus, menu items, radio button menu items, check box menu items, and separators. As you can see, a menu item can have either an image or text, or both. You can also specify other properties, such as font and color.
MenuLookDemo.bmp-399.2kB

The Menu Component Hierarchy
Here is a picture of the inheritance hierarchy for the menu-related classes:
object.bmp-310.9kB
As the figure shows, menu items (including menus) are simply buttons.

The following code creates the menus shown near the beginning of this menu section.

  1. //Where the GUI is created:
  2. JMenuBar menuBar;
  3. JMenu menu, submenu;
  4. JMenuItem menuItem;
  5. JRadioButtonMenuItem rbMenuItem;
  6. JCheckBoxMenuItem cbMenuItem;
  7. //Create the menu bar.
  8. menuBar = new JMenuBar();
  9. //Build the first menu.
  10. menu = new JMenu("A Menu");
  11. menu.setMnemonic(KeyEvent.VK_A);//设置热键
  12. menu.getAccessibleContext().setAccessibleDescription(
  13. "The only menu in this program that has menu items");
  14. menuBar.add(menu);
  15. //a group of JMenuItems
  16. menuItem = new JMenuItem("A text-only menu item",
  17. KeyEvent.VK_T);
  18. menuItem.setAccelerator(KeyStroke.getKeyStroke(
  19. KeyEvent.VK_1, ActionEvent.ALT_MASK));
  20. menuItem.getAccessibleContext().setAccessibleDescription(
  21. "This doesn't really do anything");
  22. menu.add(menuItem);
  23. menuItem = new JMenuItem("Both text and icon",
  24. new ImageIcon("images/middle.gif"));
  25. menuItem.setMnemonic(KeyEvent.VK_B);
  26. menu.add(menuItem);
  27. menuItem = new JMenuItem(new ImageIcon("images/middle.gif"));
  28. menuItem.setMnemonic(KeyEvent.VK_D);
  29. menu.add(menuItem);
  30. //a group of radio button menu items
  31. 单选框要添加到group
  32. group是一个抽象集合
  33. 要单独添加到jMenu
  34. menu.addSeparator();
  35. ButtonGroup group = new ButtonGroup();
  36. rbMenuItem = new JRadioButtonMenuItem("A radio button menu item");
  37. rbMenuItem.setSelected(true);
  38. rbMenuItem.setMnemonic(KeyEvent.VK_R);
  39. group.add(rbMenuItem);
  40. menu.add(rbMenuItem);
  41. rbMenuItem = new JRadioButtonMenuItem("Another one");
  42. rbMenuItem.setMnemonic(KeyEvent.VK_O);
  43. group.add(rbMenuItem);
  44. menu.add(rbMenuItem);
  45. //a group of check box menu items
  46. menu.addSeparator();
  47. cbMenuItem = new JCheckBoxMenuItem("A check box menu item");
  48. cbMenuItem.setMnemonic(KeyEvent.VK_C);
  49. menu.add(cbMenuItem);
  50. cbMenuItem = new JCheckBoxMenuItem("Another one");
  51. cbMenuItem.setMnemonic(KeyEvent.VK_H);
  52. menu.add(cbMenuItem);
  53. //a submenu
  54. menu.addSeparator();
  55. submenu = new JMenu("A submenu");
  56. submenu.setMnemonic(KeyEvent.VK_S);
  57. menuItem = new JMenuItem("An item in the submenu");
  58. menuItem.setAccelerator(KeyStroke.getKeyStroke(
  59. KeyEvent.VK_2, ActionEvent.ALT_MASK));
  60. submenu.add(menuItem);
  61. menuItem = new JMenuItem("Another item");
  62. submenu.add(menuItem);
  63. menu.add(submenu);
  64. //Build second menu in the menu bar.
  65. menu = new JMenu("Another Menu");
  66. menu.setMnemonic(KeyEvent.VK_N);
  67. menu.getAccessibleContext().setAccessibleDescription(
  68. "This menu does nothing");
  69. menuBar.add(menu);
  70. ...
  71. frame.setJMenuBar(theJMenuBar);

As the code shows, to set the menu bar for a JFrame, you use the setJMenuBar method. To add a JMenu to a JMenuBar, you use the add(JMenu) method. To add menu items and submenus to a JMenu, you use the add(JMenuItem) method.

  1. Create a JMenuBar object, and set it into a menu container, such as a JFrame.
  2. Create one or more JMenu objects, and add them to the menu bar object.
  3. Create one or more JMenuItem objects, and add them to the menu object.

The Root Pane
Each top-level container relies on a reclusive intermediate container called the root pane. The root pane manages the content pane and the menu bar, along with a couple of other containers. You generally don't need to know about root panes to use Swing components. However, if you ever need to intercept mouse clicks or paint over multiple components, you should get acquainted with root panes.

ui-rootPane.bmp-313.9kB

We've already told you about the content pane and the optional menu bar. The two other components that a root pane adds are a layered pane and a glass pane. The layered pane contains the menu bar and content pane, and enables Z-ordering of other components. The glass pane is often used to intercept input events occuring over the top-level container, and can also be used to paint over multiple components.


11.2 The JComponent Class

With the exception of top-level containers, all Swing components whose names begin with "J" descend from the JComponent class. For example, JPanel, JScrollPane, JButton, and JTable all inherit from JComponent. However, JFrame and JDialog don't because they implement top-level containers.

The JComponent class extends the Container class, which itself extends Component. The Component class includes everything from providing layout hints to supporting painting and events. The Container class has support for adding components to the container and laying them out. This section's API tables summarize the most often used methods of Component and Container, as well as of JComponent.
捕获.PNG-174.8kB


11.3 Component


1、JPanel


Constructor Summary

Constructor Description
JPanel() Creates a new JPanel with a double buffer and a flow layout.
JPanel​(boolean isDoubleBuffered) Creates a new JPanel with FlowLayout and the specified buffering strategy.
JPanel​(LayoutManager layout) Create a new buffered JPanel with the specified layout manager
JPanel​(LayoutManager layout, boolean isDoubleBuffered) Creates a new JPanel with the specified layout manager and buffering strategy.

2、JButton


Constructor Summary

Constructor Description
JButton() Creates a button with no set text or icon.
JButton​(String text) Creates a button with text.
JButton​(String text, Icon icon) Creates a button with initial text and an icon.
JButton​(Action a) Creates a button where properties are taken from the Action supplied.
JButton​(Icon icon) Creates a button with an icon.

3、JTextArea


A JTextArea is a multi-line area that displays plain text. Alternative multi-line text classes with more capabilities are JTextPane and JEditorPane.

The java.awt.TextArea internally handles scrolling. JTextArea is different in that it doesn't manage scrolling, but implements the swing Scrollable interface. This allows it to be placed inside a JScrollPane if scrolling behavior is desired, and used directly if scrolling is not desired.

Constructor Summary

Constructor Description
JTextArea() Constructs a new TextArea.
JTextArea​(int rows, int columns) Constructs a new empty TextArea with the specified number of rows and columns.
JTextArea​(String text) Constructs a new TextArea with the specified text displayed.
JTextArea​(String text, int rows, int columns) Constructs a new TextArea with the specified text and number of rows and columns.
JTextArea​(Document doc) Constructs a new JTextArea with the given document model, and defaults for all of the other arguments (null, 0, 0).
JTextArea​(Document doc, String text, int rows, int columns) Constructs a new JTextArea with the specified number of rows and columns, and the given model.

4、JTextField

JTextField is a lightweight component that allows the editing of a single line of text.

The horizontal alignment of JTextField can be set to be left justified, leading justified, centered, right justified or trailing justified. Right/trailing justification is useful if the required size of the field text is smaller than the size allocated to it. This is determined by the setHorizontalAlignment and getHorizontalAlignment methods. The default is to be leading justified.

Constructor Summary

Constructor Description
JTextField() Constructs a new TextField.
JTextField​(int columns) Constructs a new empty TextField with the specified number of columns.
JTextField​(String text) Constructs a new TextField initialized with the specified text.
JTextField​(String text, int columns) Constructs a new TextField initialized with the specified text and columns.
JTextField​(Document doc, String text, int columns) Constructs a new JTextField that uses the given text storage model and the given number of columns.

5、JScrollPanel

Provides a scrollable view of a lightweight component. A JScrollPane manages a viewport, optional vertical and horizontal scroll bars, and optional row and column heading viewports.

Constructor Summary

Constructor Description
JScrollPane() Creates an empty (no viewport view) JScrollPane where both horizontal and vertical scrollbars appear when needed.
JScrollPane​(int vsbPolicy, int hsbPolicy) Creates an empty (no viewport view) JScrollPane with specified scrollbar policies.
JScrollPane​(Component view) Creates a JScrollPane that displays the contents of the specified component, where both horizontal and vertical scrollbars appear whenever the component's contents are larger than the view.
JScrollPane​(Component view, int vsbPolicy, int hsbPolicy) Creates a JScrollPane that displays the view component in a viewport whose view position can be controlled with a pair of scrollbars.

Fields declared in interface javax.swing.ScrollPaneConstants

  • HORIZONTAL_SCROLLBAR
    HORIZONTAL_SCROLLBAR_ALWAYS
    HORIZONTAL_SCROLLBAR_AS_NEEDED
    HORIZONTAL_SCROLLBAR_NEVER
  • VERTICAL_SCROLLBAR
    VERTICAL_SCROLLBAR_ALWAYS
    VERTICAL_SCROLLBAR_AS_NEEDED
    VERTICAL_SCROLLBAR_NEVER

6、 Radio Buttons

Radio buttons are groups of buttons in which, by convention, only one button at a time can be selected. The Swing release supports radio buttons with the JRadioButton and ButtonGroup classes. To put a radio button in a menu, use the JRadioButtonMenuItem class. Other ways of displaying one-of-many choices are combo boxes and lists. Radio buttons look similar to check boxes, but, by convention, check boxes place no limits on how many items can be selected at a time.

Because JRadioButton inherits from AbstractButton, Swing radio buttons have all the usual button characteristics, as discussed earlier in this section. For example, you can specify the image displayed in a radio button.

Here is a picture of an application that uses five radio buttons to let you choose which kind of pet is displayed:

RadioButtonDemoMetal.png-22kB

Each time the user clicks a radio button (even if it was already selected), the button fires an action event. One or two item events also occur — one from the button that was just selected, and another from the button that lost the selection (if any). Usually, you handle radio button clicks using an action listener.
Below is the code from RadioButtonDemo.java that creates the radio buttons in the previous example and reacts to clicks.

  1. //In initialization code:
  2. //Create the radio buttons.
  3. JRadioButton birdButton = new JRadioButton(birdString);
  4. birdButton.setMnemonic(KeyEvent.VK_B);
  5. birdButton.setActionCommand(birdString);
  6. birdButton.setSelected(true);
  7. JRadioButton catButton = new JRadioButton(catString);
  8. catButton.setMnemonic(KeyEvent.VK_C);
  9. catButton.setActionCommand(catString);
  10. JRadioButton dogButton = new JRadioButton(dogString);
  11. dogButton.setMnemonic(KeyEvent.VK_D);
  12. dogButton.setActionCommand(dogString);
  13. JRadioButton rabbitButton = new JRadioButton(rabbitString);
  14. rabbitButton.setMnemonic(KeyEvent.VK_R);
  15. rabbitButton.setActionCommand(rabbitString);
  16. JRadioButton pigButton = new JRadioButton(pigString);
  17. pigButton.setMnemonic(KeyEvent.VK_P);
  18. pigButton.setActionCommand(pigString);
  19. //Group the radio buttons.
  20. ButtonGroup group = new ButtonGroup();
  21. group.add(birdButton);
  22. group.add(catButton);
  23. group.add(dogButton);
  24. group.add(rabbitButton);
  25. group.add(pigButton);
  26. //Register a listener for the radio buttons.
  27. birdButton.addActionListener(this);
  28. catButton.addActionListener(this);
  29. dogButton.addActionListener(this);
  30. rabbitButton.addActionListener(this);
  31. pigButton.addActionListener(this);
  32. ...
  33. public void actionPerformed(ActionEvent e) {
  34. picture.setIcon(new ImageIcon("images/"
  35. + e.getActionCommand()
  36. + ".gif"));
  37. }

For each group of radio buttons, you need to create a ButtonGroup instance and add each radio button to it. The ButtonGroup takes care of unselecting the previously selected button when the user selects another button in the group.

You should generally initialize a group of radio buttons so that one is selected. However, the API doesn't enforce this rule — a group of radio buttons can have no initial selection. Once the user has made a selection, exactly one button is selected from then on.


7、Check Boxes

The JCheckBox class provides support for check box buttons. You can also put check boxes in menus, using the JCheckBoxMenuItem class. Because JCheckBox and JCheckBoxMenuItem inherit from AbstractButton, Swing check boxes have all the usual button characteristics, as discussed earlier in this section. For example, you can specify images to be used in check boxes.

Check boxes are similar to radio buttons but their selection model is different, by convention. Any number of check boxes in a group — none, some, or all — can be selected. A group of radio buttons, on the other hand, can have only one button selected.

Here is a picture of an application that uses four check boxes to customize a cartoon:

CheckBoxDemoMetal.png-15.6kB

A check box generates one item event and one action event per click. Usually, you listen only for item events, since they let you determine whether the click selected or deselected the check box. Below is the code from CheckBoxDemo.java that creates the check boxes in the previous example and reacts to clicks.

  1. //In initialization code:
  2. chinButton = new JCheckBox("Chin");
  3. chinButton.setMnemonic(KeyEvent.VK_C);
  4. chinButton.setSelected(true);
  5. glassesButton = new JCheckBox("Glasses");
  6. glassesButton.setMnemonic(KeyEvent.VK_G);
  7. glassesButton.setSelected(true);
  8. hairButton = new JCheckBox("Hair");
  9. hairButton.setMnemonic(KeyEvent.VK_H);
  10. hairButton.setSelected(true);
  11. teethButton = new JCheckBox("Teeth");
  12. teethButton.setMnemonic(KeyEvent.VK_T);
  13. teethButton.setSelected(true);
  14. //Register a listener for the check boxes.
  15. chinButton.addItemListener(this);
  16. glassesButton.addItemListener(this);
  17. hairButton.addItemListener(this);
  18. teethButton.addItemListener(this);
  19. ...
  20. public void itemStateChanged(ItemEvent e) {
  21. ...
  22. Object source = e.getItemSelectable();
  23. if (source == chinButton) {
  24. //...make a note of it...
  25. } else if (source == glassesButton) {
  26. //...make a note of it...
  27. } else if (source == hairButton) {
  28. //...make a note of it...
  29. } else if (source == teethButton) {
  30. //...make a note of it...
  31. }
  32. if (e.getStateChange() == ItemEvent.DESELECTED)
  33. //...make a note of it...
  34. ...
  35. updatePicture();
  36. }

8、Combo Boxes

A JComboBox, which lets the user choose one of several choices, can have two very different forms. The default form is the uneditable combo box, which features a button and a drop-down list of values. The second form, called the editable combo box, features a text field with a small button abutting it. The user can type a value in the text field or click the button to display a drop-down list. Here's what the two forms of combo boxes look like in the Java look and feel:

16.PNG-33.6kB

Combo boxes require little screen space, and their editable (text field) form is useful for letting the user quickly choose a value without limiting the user to the displayed values. Other components that can display one-of-many choices are groups of radio buttons and lists. Groups of radio buttons are generally the easiest for users to understand, but combo boxes can be more appropriate when space is limited or more than a few choices are available. Lists are not terribly attractive, but they're more appropriate than combo boxes when the number of items is large (say, over 20) or when selecting multiple items might be valid.

ComboBoxDemoMetal.png-21.6kB

The following code, taken from ComboBoxDemo.java, creates an uneditable combo box and sets it up:

  1. String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" };
  2. //Create the combo box, select item at index 4.
  3. //Indices start at 0, so 4 specifies the pig.
  4. JComboBox petList = new JComboBox(petStrings);
  5. petList.setSelectedIndex(4);
  6. petList.addActionListener(this);

This combo box contains an array of strings, but you could just as easily use icons instead. To put anything else into a combo box or to customize how the items in a combo box look, you need to write a custom renderer. An editable combo box would also need a custom editor. Refer to Providing a Custom Renderer for information and an example.
The preceding code registers an action listener on the combo box. To see the action listener implementation and learn about other types of listeners supported by combo box, refer to Handling Events on a Combo Box.
No matter which constructor you use, a combo box uses a combo box model to contain and manage the items in its menu. When you initialize a combo box with an array or a vector, the combo box creates a default model object for you. As with other Swing components, you can customize a combo box in part by implementing a custom model — an object that implements the ComboBoxModel interface.


11.4 Layout


1、BoxLayout

A layout manager that allows multiple components to be laid out either vertically or horizontally. The components will not wrap so, for example, a vertical arrangement of components will stay vertically arranged when the frame is resized.
Example:
BoxLayout-1.gif-1.7kB

The BoxLayout manager is constructed with an axis parameter that specifies the type of layout that will be done.

X_AXIS- Components are laid out horizontally from left to right.
Y_AXIS - Components are laid out vertically from top to bottom.g
默认左对齐

For all directions, components are arranged in the same order as they were added to the container.

Instead of using BoxLayout directly, many programs use the Box class. The Box class is a lightweight container that uses a BoxLayout. It also provides handy methods to help you use BoxLayout well. Adding components to multiple nested boxes is a powerful way to get the arrangement you want.

Constructor Summary

Constructor Description
BoxLayout​(Container target, int axis) Creates a layout manager that will lay out components along the given axis.

Method Summary

Modifier and Type Method Description
int getAxis() Returns the axis that was used to lay out components.
float getLayoutAlignmentX​(Container target) Returns the alignment along the X axis for the container.
float getLayoutAlignmentY​(Container target) Returns the alignment along the Y axis for the container.
Container getTarget() Returns the container that uses this layout manager.
void invalidateLayout​(Container target) Indicates that a child has changed its layout related information, and thus any cached calculations should be flushed.
void layoutContainer​(Container target) Called by the AWT when the specified container needs to be laid out.
Dimension maximumLayoutSize​(Container target) Returns the maximum dimensions the target container can use to lay out the components it contains.
Dimension minimumLayoutSize​(Container target) Returns the minimum dimensions needed to lay out the components contained in the specified target container.
Dimension preferredLayoutSize​(Container target) Returns the preferred dimensions for this layout, given the components in the specified target container.

Box

A lightweight container that uses a BoxLayout object as its layout manager. Box provides several class methods that are useful for containers using BoxLayout -- even non-Box containers.

The Box class can create several kinds of invisible components that affect layout: glue, struts, and rigid areas. If all the components your Box contains have a fixed size, you might want to use a glue component (returned by createGlue) to control the components' positions. If you need a fixed amount of space between two components, try using a strut (createHorizontalStrut or createVerticalStrut). If you need an invisible component that always takes up the same amount of space, get it by invoking createRigidArea.

Constructor Summary

Constructor Description
Box​(int axis) Creates a Box that displays its components along the specified axis.

Method Summary

Modifier and Type Method Description
static Component createGlue() Creates an invisible "glue" component that can be useful in a Box whose visible components have a maximum width (for a horizontal box) or height (for a vertical box).
static Box createHorizontalBox() Creates a Box that displays its components from left to right.
static Component createHorizontalGlue() Creates a horizontal glue component.
static Component createHorizontalStrut​(int width) Creates an invisible, fixed-width component.
static Component createRigidArea​(Dimension d) Creates an invisible component that's always the specified size.
static Box createVerticalBox() Creates a Box that displays its components from top to bottom.
static Component createVerticalGlue() Creates a vertical glue component.
static Component createVerticalStrut​(int height) Creates an invisible, fixed-height component.
AccessibleContext getAccessibleContext() Gets the AccessibleContext associated with this Box.
protected void paintComponent​(Graphics g) Paints this Box.
void setLayout​(LayoutManager l) Throws an AWTError, since a Box can use only a BoxLayout.

2、FlowLayout

A flow layout arranges components in a directional flow, much like lines of text in a paragraph. The flow direction is determined by the container's componentOrientation property and may be one of two values:
ComponentOrientation.LEFT_TO_RIGHT
ComponentOrientation.RIGHT_TO_LEFT
Flow layouts are typically used to arrange buttons in a panel. It arranges buttons horizontally until no more buttons fit on the same line. The line alignment is determined by the align property. The possible values are:

For example, the following picture shows an applet using the flow layout manager (its default layout manager) to position three buttons:
FlowLayout-1.gif-1.9kB

Here is the code for this applet:

  1. import java.awt.*;
  2. import java.applet.Applet;
  3. public class myButtons extends Applet {
  4. Button button1, button2, button3;
  5. public void init() {
  6. button1 = new Button("Ok");
  7. button2 = new Button("Open");
  8. button3 = new Button("Close");
  9. add(button1);
  10. add(button2);
  11. add(button3);
  12. }
  13. }

A flow layout lets each component assume its natural (preferred) size.

Constructor Summary

Constructor Description
FlowLayout() Constructs a new FlowLayout with a centered alignment and a default 5-unit horizontal and vertical gap.
FlowLayout​(int align) Constructs a new FlowLayout with the specified alignment and a default 5-unit horizontal and vertical gap.
FlowLayout​(int align, int hgap, int vgap) Creates a new flow layout manager with the indicated alignment and the indicated horizontal and vertical gaps.

Method Summary

Modifier and Type Method Description
void addLayoutComponent​(String name, Component comp) Adds the specified component to the layout.
int getAlignment() Gets the alignment for this layout.
boolean getAlignOnBaseline() Returns true if components are to be vertically aligned along their baseline.
int getHgap() Gets the horizontal gap between components and between the components and the borders of the Container
int getVgap() Gets the vertical gap between components and between the components and the borders of the Container.
void layoutContainer​(Container target) Lays out the container.
Dimension minimumLayoutSize​(Container target) Returns the minimum dimensions needed to layout the visible components contained in the specified target container.
Dimension preferredLayoutSize​(Container target) Returns the preferred dimensions for this layout given the visible components in the specified target container.
void removeLayoutComponent​(Component comp) Removes the specified component from the layout.
void setAlignment​(int align) Sets the alignment for this layout.
void setAlignOnBaseline​(boolean alignOnBaseline) Sets whether or not components should be vertically aligned along their baseline.
void setHgap​(int hgap) Sets the horizontal gap between components and between the components and the borders of the Container.
void setVgap​(int vgap) Sets the vertical gap between components and between the components and the borders of the Container.

Field Detail


LEFT

This value indicates that each row of components should be left-justified.


CENTER

This value indicates that each row of components should be centered.


RIGHT

This value indicates that each row of components should be right-justified.


LEADING

This value indicates that each row of components should be justified to the leading edge of the container's orientation, for example, to the left in left-to-right orientations.


TRAILING

This value indicates that each row of components should be justified to the trailing edge of the container's orientation, for example, to the right in left-to-right orientations.


Constructor Detail


  1. public FlowLayout()

Constructs a new FlowLayout with a centered alignment and a default 5-unit horizontal and vertical gap.


  1. public FlowLayout​(int align)

Constructs a new FlowLayout with the specified alignment and a default 5-unit horizontal and vertical gap. The value of the alignment argument must be one of FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER, FlowLayout.LEADING, or FlowLayout.TRAILING.
Parameters:
align - the alignment value


  1. public FlowLayout​(int align,int hgap,int vgap)

Creates a new flow layout manager with the indicated alignment and the indicated horizontal and vertical gaps.
The value of the alignment argument must be one of FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER, FlowLayout.LEADING, or FlowLayout.TRAILING.
Parameters:
align - the alignment value
hgap - the horizontal gap between components and between the components and the borders of the Container
vgap - the vertical gap between components and between the components and the borders of the Container


3、GridLayout

The GridLayout class is a layout manager that lays out a container's components in a rectangular grid. The container is divided into equal-sized rectangles, and one component is placed in each rectangle. For example, the following is an applet that lays out six buttons into three rows and two columns:

  1. import java.awt.*;
  2. import java.applet.Applet;
  3. public class ButtonGrid extends Applet {
  4. public void init() {
  5. setLayout(new GridLayout(3,2));
  6. add(new Button("1"));
  7. add(new Button("2"));
  8. add(new Button("3"));
  9. add(new Button("4"));
  10. add(new Button("5"));
  11. add(new Button("6"));
  12. }
  13. }

If the container's ComponentOrientation property is horizontal and left-to-right, the above example produces the output shown in Figure 1. If the container's ComponentOrientation property is horizontal and right-to-left, the example produces the output shown in Figure 2.
GridLayout-1.gif-1.7kB GridLayout-2.gif-1.7kB


When both the number of rows and the number of columns have been set to non-zero values, either by a constructor or by the setRows and setColumns methods, the number of columns specified is ignored. Instead, the number of columns is determined from the specified number of rows and the total number of components in the layout. So, for example, if three rows and two columns have been specified and nine components are added to the layout, they will be displayed as three rows of three columns. Specifying the number of columns affects the layout only when the number of rows is set to zero.

Constructor Summary

Constructor Description
GridLayout() Creates a grid layout with a default of one column per component, in a single row.
GridLayout​(int rows, int cols) Creates a grid layout with the specified number of rows and columns.
GridLayout​(int rows, int cols, int hgap, int vgap) Creates a grid layout with the specified number of rows and columns.

Method Summary

Modifier and Type Method Description
void addLayoutComponent​(String name, Component comp) Adds the specified component with the specified name to the layout.
int getColumns() Gets the number of columns in this layout.
int getHgap() Gets the horizontal gap between components.
int getRows() Gets the number of rows in this layout.
int getVgap() Gets the vertical gap between components.
void layoutContainer​(Container parent) Lays out the specified container using this layout.
Dimension minimumLayoutSize​(Container parent) Determines the minimum size of the container argument using this grid layout.
Dimension preferredLayoutSize​(Container parent) Determines the preferred size of the container argument using this grid layout.
void removeLayoutComponent​(Component comp) Removes the specified component from the layout
void setColumns​(int cols) Sets the number of columns in this layout to the specified value.
void setHgap​(int hgap) Sets the horizontal gap between components to the specified value.
void setRows​(int rows) Sets the number of rows in this layout to the specified value.
void setVgap​(int vgap) Sets the vertical gap between components to the specified value.
String toString() Returns the string representation of this grid layout's values.

Constructor Detail


  1. public GridLayout()

Creates a grid layout with a default of one column per component, in a single row.


  1. public GridLayout​(int rows,int cols)

Creates a grid layout with the specified number of rows and columns. All components in the layout are given equal size.
One, but not both, of rows and cols can be zero, which means that any number of objects can be placed in a row or in a column.
Parameters:
rows - the rows, with the value zero meaning any number of rows.
cols - the columns, with the value zero meaning any number of columns.


  1. public GridLayout​(int rows,int cols,int hgap,int vgap)

Creates a grid layout with the specified number of rows and columns. All components in the layout are given equal size.
In addition, the horizontal and vertical gaps are set to the specified values. Horizontal gaps are placed between each of the columns. Vertical gaps are placed between each of the rows.
One, but not both, of rows and cols can be zero, which means that any number of objects can be placed in a row or in a column.
All GridLayout constructors defer to this one.
Parameters:
rows - the rows, with the value zero meaning any number of rows
cols - the columns, with the value zero meaning any number of columns
hgap - the horizontal gap
vgap - the vertical gap
Throws:
IllegalArgumentException - if the value of both rows and cols is set to zero



Chapter 12 Threads


12.1 What Is a Thread?

A thread is an object.Sometimes it is called an execution context or a lightweight process--is a single sequential flow of control within a program.

执行上下文(Excute Context);
一个线程是一个程序内部的顺序控制流。

  1. 进程:每个进程都有独立的代码和数据空间(进程上下文) ,进程切换的开销大。
  2. 线程:轻量的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,线程切换的开销小。
  3. 多进程:在操作系统中,能同时运行多个任务程序。
  4. 多线程:在同一应用程序中,有多个顺序流同时执行。

A program always has at least one thread: the one created when the program begins execution.


12.2 Sigle thread and Multiple thread

There are two ways to create a new thread of execution. One is to declare a class to be a subclass of Thread. This subclass should override the run method of class Thread. An instance of the subclass can then be allocated and started. For example, a thread that computes primes larger than a stated value could be written as follows:

  1. class PrimeThread extends Thread {
  2. long minPrime;
  3. PrimeThread(long minPrime) {
  4. this.minPrime = minPrime;
  5. }
  6. public void run() {
  7. // compute primes larger than minPrime
  8. . . .
  9. }
  10. }

The following code would then create a thread and start it running:

  1. PrimeThread p = new PrimeThread(143);
  2. p.start();

The other way to create a thread is to declare a class that implements the Runnable interface. That class then implements the run method. An instance of the class can then be allocated, passed as an argument when creating Thread, and started. The same example in this other style looks like the following:

  1. class PrimeRun implements Runnable {
  2. long minPrime;
  3. PrimeRun(long minPrime) {
  4. this.minPrime = minPrime;
  5. }
  6. public void run() {
  7. // compute primes larger than minPrime
  8. . . .
  9. }
  10. }

The following code would then create a thread and start it running:

  1. PrimeRun p = new PrimeRun(143);
  2. new Thread(p).start();
  3. /*Thread t = new Thread(p);
  4. p.start();
  5. */

12.3 The Life Cycle of a Thread

图片3.PNG-66.1kB

1、 New
When a thread is a New Thread, it is merely an empty Thread object; no system resources have
been allocated for it yet. you can only start the thread. Calling any method besides start when a
thread is in this state makes no sense and causes an IllegalThreadStateException.

2、 Runnable
The start method creates the system resources necessary to run the thread, schedules the thread
to run, and calls the thread's run method .The code that executes in a new thread is always a
method called run(), which is public, accepts no arguments, and doesn’t return a value. thread that has been started is actually in the Runnable state.The Java runtime system must implement a scheduling scheme that shares the processor between all "running" threads.
Once a thread starts running, it can be interrupted to give other threads a chance to run. The operating system gives each runnable thread a time slice to perform tasks. When the time slice runs out, the operating system will deny the thread the right to run and give another thread a chance to run ( considering the priority of the thread ).

A thread becomes Not Runnable when one of these events occurs:

3、 Terminate
A thread arranges for its own death by having a run method that terminates naturally
Accidental death due to an abnormal termination of the run method without inactivity

4、 Blocked and Waiting
When a thread attempts to acquire an internal object lock and the lock is held by other threads, the thread enters a blocking state, and when all other threads release the lock and the thread scheduler allows the thread to hold it, the thread becomes a non-blocking state.
When a thread waits for another thread to notify the scheduler of a condition, it enters the waiting state itself.


12.4 Thread Priority

The Java runtime supports a very simple, deterministic scheduling algorithm known as fixed priority scheduling.
When a Java thread is created, it inherits its priority from the thread that created it.
You can also modify a thread's priority at any time after its creation using the setPriority method. Thread priorities are integers ranging between MIN_PRIORITY and MAX_PRIORITY( 1-10 ). The higher the integer, the higher the priority.

1 - MIN_PRIORITY
10 – MAX_PRIORITY
5- NORM_PRIORITY

when multiple threads are ready to be executed,the runtime system chooses the runnable thread with the highest priority for execution.Only when that thread stops, yields, or becomes not runnable for some reason will a lower priority thread start executing. If two threads of the same priority are waiting for the CPU, the scheduler chooses one of them to run in a round-robin fashion.
The chosen thread will run until one of the following conditions is true:

At any given time, the highest priority thread is running. However, this is not guaranteed. The thread scheduler may choose to run a lower priority thread to avoid starvation. For this reason, use priority only to affect scheduling policy for efficiency purposes. Do not rely on thread priority for algorithm correctness.


12.5 Basic Control of Thread

Constructor Summary

Constructor Description
Thread() Allocates a new Thread object.This constructor has the same effect as Thread (null, null, gname), where gname is a newly generated name.
Thread​(Runnable target) Allocates a new Thread object.
Thread​(Runnable target, String name) Allocates a new Thread object.
Thread​(String name) Allocates a new Thread object.
Thread​(ThreadGroup group, Runnable target) Allocates a new Thread object.
Thread​(ThreadGroup group, Runnable target, String name) Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group.
Thread​(ThreadGroup group, Runnable target, String name, long stackSize) Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group, and has the specified stack size.
Thread​(ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals) Allocates a new Thread object so that it has target as its run object, has the specified name as its name, belongs to the thread group referred to by group, has the specified stackSize, and inherits initial values for inheritable thread-local variables if inheritThreadLocals is true.
Thread​(ThreadGroup group, String name) Allocates a new Thread object.

Method Summary

Modifier and Type Method Description
int getPriority() Returns this thread's priority.
void interrupt() Interrupts this thread.
static boolean interrupted() Tests whether the current thread has been interrupted.
boolean isAlive() Tests if this thread is alive.
boolean isInterrupted() Tests whether this thread has been interrupted.
void join() Waits for this thread to die.
void join​(long millis) Waits at most millis milliseconds for this thread to die.
void run() If this thread was constructed using a separate Runnable run object, then that Runnable object's run method is called; otherwise, this method does nothing and returns.
void setPriority​(int newPriority) Changes the priority of this thread.
static void sleep​(long millis) Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.
void start() Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
static void yield() A hint to the scheduler that the current thread is willing to yield its current use of a processor.

Note

  1. Thread.sleep() // static method
    Thread.yield()
  2. void join()
    等待该线程终止。
    void join(long millis)
    等待该线程终止的时间最长为 millis 毫秒。
    void join(long millis, int nanos)
    等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。
  3. sleep():end any priority thread
    yeild():end the same priority thread

12.6 Synchronizing Threads

Multithreaded programming has these characteristics:
• Multiple threads are from one Runnable instance.
• Threads share the same data and code.

The code segments within a program that access the same object from separate, concurrent threads are called critical sections. A critical section can be a block or a method and are identified with the synchronized keyword. The Java platform then associates a lock with every object that has synchronized code.

To ensure that when several threads want access to a single resource,only one thread can access it at any given time.
❑ You can manage code at the method level—synchronizing methods.
❑ You can manage code at the block level— synchronizing blocks.

Every object has a flag that is a type of lock flag.The synchronized enables interaction with the lock flag.

To make a method synchronized, simply add the synchronized keyword to its declaration:

  1. public class SynchronizedCounter {
  2. private int c = 0;
  3. //method-level locked
  4. public synchronized void increment() {
  5. c++;
  6. }
  7. public synchronized void decrement() {
  8. c--;
  9. }
  10. public synchronized int value() {
  11. return c;
  12. }
  13. }

If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
Note that constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed.

Warning: When constructing an object that will be shared between threads, be very careful that a reference to the object does not "leak" prematurely. For example, suppose you want to maintain a List called instances containing every instance of class. You might be tempted to add the following line to your constructor:

  1. instances.add(this);

But then other threads can use instances to access the object before construction of the object is complete.

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed)

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquisition of the same lock.

Locks In Synchronized Methods
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.

Synchronized Statements
Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:

  1. public void addName(String name) {
  2. synchronized(this) {
  3. lastName = name;
  4. nameCount++;
  5. }
  6. nameList.add(name);
  7. }

Synchronized statements are also useful for improving concurrency with fine-grained synchronization. Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.

  1. public class MsLunch {
  2. private long c1 = 0;
  3. private long c2 = 0;
  4. private Object lock1 = new Object();
  5. private Object lock2 = new Object();
  6. public void inc1() {
  7. synchronized(lock1) {
  8. c1++;
  9. }
  10. }
  11. public void inc2() {
  12. synchronized(lock2) {
  13. c2++;
  14. }
  15. }
  16. }

Use this idiom with extreme care. You must be absolutely sure that it really is safe to interleave access of the affected fields.

To avoid polling, Java includes an elegant interprocess communication mechanism via the wait( ),
notify( ), and notifyAll( ) methods

– All three methods can be called only from within a synchronized context

  • wait( ) tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
  • notify() wakes up the first thread that called wait() on the same object.
  • notifyAll() wakes up all the threads that called wait( ) on

图片5.PNG-257.3kB

Releasing the Lock Flag:
The lock flag is released in the following events:
• Released when the thread passes the end of the synchronized code block
• Released automatically when a break, return, or exception is thrown by the synchronized code block


12.7 Deadlock

Deadlock occurs when two or more threads are waiting on a condition that cannot be satisfied.
Deadlock most often occurs when two (or more) threads are each waiting for the other(s) to do something.
A deadlock has the following characteristics:


12.8 Grouping Treads

Every Java thread is a member of a thread group.Thread groups provide a mechanism for collecting multiple threads into a single object and manipulating those threads all at once, rather than individually.
The runtime system puts a thread into a thread group during thread construction. When create a thread, you can either allow the runtime system to put the new thread in some reasonable default group or you can explicitly set the new thread's group.The thread is a permanent member of whatever thread group it joins upon its creation--you cannot move a thread to a new group after the thread has been created.
If you create a new Thread without specifying its group in the constructor, the runtime system automatically places the new thread in the same group as the thread that created it
When a Java application first starts up, the Java runtime system creates a ThreadGroup named main.
When you operate a group,you will operate the whole thread in the group.

图片7.PNG-372.8kB


Chapter 13 Network


Question:
1、something about the new port created by server when the acceptance is well ?
2、printwriter and printstream?


13.1 Networking Basics

Computers running on the Internet communicate to each other using either the Transmission Control Protocol (TCP) or the User Datagram Protocol(UDP)
图8.PNG-8.7kB

TCP & UDP


13.2 Networking With Java Technology

• Java programs ‐ at the application layer– can use the classes in the java.net package.
When you write Java programs that communicate over the network, you are programming at the application layer.

To address the connection, include the following:
• The address or name of remote machine
• A port(端口) number to identify the purpose at the server
• Port numbers range from 0–65535

Through the classes in java.net, Java programs can use TCP or UDP to communicate over the Internet.
The URL, URLConnection, Socket, and ServerSocket classes all use TCP to communicate over the network.
The DatagramPacket, DatagramSocket, and MulticastSocket classes are for use with UDP.


13.3 Port

The TCP and UDP protocols use ports to map incoming data to a particular process running on a computer.
In connection-based communication such as TCP, a server application binds a socket to a specific port number.
This has the effect of registering the server with the system to receive all data destined for that port. A client can then rendezvous(约会) with the server at the server's port, as illustrated here:
图片9.png-2kB
Generally speaking, a computer has a single physical connection to the network. All data destined for a particular computer arrives through that connection. However, the data may be intended for different applications running on the computer. So how does the computer know to which application to forward the data? Through the use of ports.
Data transmitted over the Internet is accompanied by addressing information that identifies the computer and the port for which it is destined. The computer is identified by its 32-bit IP address, which IP uses to deliver data to the right computer on the network. Ports are identified by a 16-bit number, which TCP and UDP use to deliver the data to the right application.
In connection-based communication such as TCP, a server application binds a socket to a specific port number. This has the effect of registering the server with the system to receive all data destined for that port.
In datagram-based communication such as UDP, the datagram packet contains the port number of its destination and UDP routes the packet to the appropriate application.
图片10.png-11.7kB
Port numbers range from 0 to 65,535 because ports are represented by 16-bit numbers. The port numbers ranging from 0 - 1023 are restricted; they are reserved for use by well-known services such as HTTP and FTP and other system services. These ports are called well-known ports. Your applications should not attempt to bind to them.


13.4 Socket

A socket is one end-point of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to.

Normally, a server runs on a specific computer and has a socket that is bound to a specific port number. The server just waits, listening to the socket for a client to make a connection request.
On the client-side:The client knows the hostname of the machine on which the server is running and the port number to which the server is connected. To make a connection request, the client tries to rendezvous with the server on the server's machine and port.
图片11.png-2.9kB
If everything goes well, the server accepts the connection. Upon acceptance, the server gets a new socket bound to a different port.
图片12.png-1.8kB
On the client side, if the connection is accepted, a socket is successfully created and the client can use the socket to communicate with the server.The client and server can now communicate by writing to or reading from their sockets.

The java.net package provides two classes--Socket and ServerSocket--that implement the client side of the connection and the server side of the connection, respectively.

Sockets hold two streams: an input streamand an output stream.Each end of the socket has a pair of streams.Set up of a network connection is similar to a telephone system: One end must dial the other end, which must be listening.


13.5 Reading from and Writing to a Socket

Let's look at a simple example that illustrates how a program can establish a connection to a server program using the Socket class and then, how the client can send data to and receive data from the server through the socket.

  1. String hostName = args[0];
  2. int portNumber = Integer.parseInt(args[1]);
  3. try (
  4. Socket echoSocket = new Socket(hostName, portNumber);
  5. PrintWriter out =
  6. new PrintWriter(echoSocket.getOutputStream(), true);
  7. BufferedReader in =
  8. new BufferedReader(
  9. new InputStreamReader(echoSocket.getInputStream()));
  10. BufferedReader stdIn =
  11. new BufferedReader(
  12. new InputStreamReader(System.in))
  13. )

The example program implements a client, EchoClient, that connects to an echo server. The echo server receives data from its client and echoes it back. The example EchoServer implements an echo server. (Alternatively, the client can connect to any host that supports the Echo Protocol.)

The EchoClient example creates a socket, thereby getting a connection to the echo server. It reads input from the user on the standard input stream, and then forwards that text to the echo server by writing the text to the socket. The server echoes the input back through the socket to the client. The client program reads and displays the data passed back to it from the server.

Note that the EchoClient example both writes to and reads from its socket, thereby sending data to and receiving data from the echo server.

  1. /**
  2. *server
  3. */
  4. import java.io.*;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. import java.util.Scanner;
  8. public class EchoServer {
  9. public static void main(String[] args) {
  10. File file = new File("multiLines.txt");
  11. System.out.println("Wait for client request");
  12. try {
  13. ServerSocket serverSocket = new ServerSocket(27015);
  14. Socket socket = serverSocket.accept();
  15. Scanner scanner = new Scanner(socket.getInputStream());
  16. PrintStream printStream = new PrintStream(socket.getOutputStream());
  17. BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
  18. while (true) {
  19. String message = "";
  20. int num = scanner.nextInt();
  21. for (int i = 1; i <= num; i++) {
  22. String messageTemp = bufferedReader.readLine();
  23. if(messageTemp != null && !messageTemp.equals("")){
  24. String messageCur = message;
  25. message = messageTemp + "##";
  26. message = messageCur + message;
  27. }
  28. else{
  29. message=message+"No more sentences##";
  30. break;
  31. }
  32. }
  33. printStream.println(message);
  34. }
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. }
  1. /**
  2. *client
  3. */
  4. import javax.swing.*;
  5. import java.awt.*;
  6. import java.awt.event.ActionEvent;
  7. import java.awt.event.ActionListener;
  8. import java.io.*;
  9. import java.net.Socket;
  10. import java.util.Scanner;
  11. public class EchoClient {
  12. private JFrame frame;
  13. private JLabel label;
  14. private JButton button;
  15. private JTextField textField;
  16. private JTextArea textArea;
  17. private Socket socket;
  18. private Scanner in;
  19. private PrintStream out;
  20. public EchoClient() {
  21. frame = new JFrame("Product System");
  22. label = new JLabel("Please input the number of the string lines to get from server:");
  23. button = new JButton("send to server");
  24. textArea = new JTextArea();
  25. textField = new JTextField();
  26. try {
  27. socket = new Socket("127.0.0.1", 27015);
  28. out = new PrintStream(socket.getOutputStream());
  29. in = new Scanner(socket.getInputStream());
  30. ButtonActionListener r = new ButtonActionListener();
  31. Thread t = new Thread(r);
  32. t.start();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. public void lunchFrame() {
  38. frame.setLayout(new BorderLayout());
  39. Dimension frameDimension = new Dimension(600, 300);
  40. frame.setPreferredSize(frameDimension);
  41. JPanel panel = new JPanel(new BorderLayout());
  42. Dimension panelDimension = new Dimension(600, 40);
  43. panel.setPreferredSize(panelDimension);
  44. JPanel panelEast = new JPanel();
  45. panelEast.setLayout(new FlowLayout());
  46. Dimension textDimension = new Dimension(100, 20);
  47. textField.setPreferredSize(textDimension);
  48. panelEast.add(textField);
  49. panelEast.add(button);
  50. button.addActionListener(new ButtonActionListener());
  51. panel.add(label, BorderLayout.CENTER);
  52. panel.add(panelEast, BorderLayout.EAST);
  53. textArea.setEditable(false);
  54. textArea.setSize(100, 50);
  55. frame.add(panel, BorderLayout.NORTH);
  56. frame.add(textArea, BorderLayout.CENTER);
  57. frame.pack();
  58. frame.setLocationRelativeTo(null);
  59. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  60. frame.setVisible(true);
  61. }
  62. private class ButtonActionListener implements ActionListener, Runnable {
  63. @Override
  64. public void actionPerformed(ActionEvent e) {
  65. int number = 0;
  66. String num = textField.getText();
  67. if (!num.equals("")) {
  68. number = Integer.parseInt(num);
  69. }
  70. textField.setText("");
  71. textArea.append("get " + number + " lines from server\n");
  72. out.println(number);
  73. }
  74. @Override
  75. public void run() {
  76. while (true) {
  77. String message = in.nextLine();
  78. String subMessage = "No more sentences";
  79. if (!message.equals("")) {
  80. if (message.indexOf(subMessage) != -1) {
  81. textArea.append(message + "\n");
  82. textArea.append("can not take sentences anymore\n");
  83. } else {
  84. textArea.append(message + "\n");
  85. }
  86. }
  87. }
  88. }
  89. }
  90. public static void main(String[] args){
  91. javax.swing.SwingUtilities.invokeLater(new Runnable() {
  92. @Override
  93. public void run() {
  94. EchoClient echoClient =new EchoClient();
  95. echoClient.lunchFrame();
  96. }
  97. });
  98. }
  99. }

The while loop then terminates, and the Java runtime automatically closes the readers and writers connected to the socket and to the standard input stream, and it closes the socket connection to the server. The Java runtime closes these resources automatically because they were created in the try-with-resources statement. The Java runtime closes these resources in reverse order that they were created. (This is good because streams connected to a socket should be closed before the socket itself is closed.)

The basics are much the same as they are in this program:
1. Open a socket.
2. Open an input stream and output stream to the socket.
3. Read from and write to the stream according to the server's protocol.
4. Close the streams.
5. Close the socket.
6.
Only step 3 differs from client to client, depending on the server. The other steps remain largely the same.
图片13.PNG-32.7kB


13.6 Supporting Multiple Clients

multiple client requests can come into the same port and, consequently, into the same ServerSocket. Client connection requests are queued at the port, so the server must accept the connections sequentially. However, the server can service them simultaneously through the use of threads - one thread per each client connection.

  1. while (true) {
  2. accept a connection ;
  3. create a thread to deal with the client ;
  4. }

13.7 Datagram

A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed.
Clients and servers that communicate via a reliable channel, such as a TCP socket, have a dedicated point-to-point channel between themselves, or at least the illusion(错误的观念) of one. To communicate, they establish a connection, transmit the data, and then close the connection. All data sent over the channel is received in the same order in which it was sent. This is guaranteed by the channel.

In contrast, applications that communicate via datagrams send and receive completely independent packets of information. These clients and servers do not have and do not need a dedicated point-to-point channel. The delivery of datagrams to their destinations is not guaranteed. Nor is the order of their arrival.

The java.net package contains three classes to help you write Java programs that use datagrams to send and receive packets over the network: DatagramSocket, DatagramPacket, and MulticastSocketAn application can send and receive DatagramPackets through a DatagramSocket. In addition, DatagramPackets can be broadcast to multiple recipients all listening to a MulticastSocket.
图片14.png-54.3kB

DatagramSocket
用于UDP通信的套接字,发送端不指定端口;接受端需要指定端口。
DatagramSocket使用send(packet)发送数据、使用receive(packet)接收数据
DatagramPacket
发送:在构造发送的数据报文包时指定接受者的端口和IP地址
接收:接受到的DatagramPacket对象可以使用getAddress()和getPort()获取发送者的IP和端口,从而可以构造发送包交互通信


13.8 Writing a Datagram Client and Server

The example featured in this section consists of two applications: a client and a server. The server continuously receives datagram packets over a datagram socket. Each datagram packet received by the server indicates a client request for a quotation. When the server receives a datagram, it replies by sending a datagram packet that contains a one-line "quote of the moment" back to the client.

The client application in this example is fairly simple. It sends a single datagram packet to the server indicating that the client would like to receive a quote of the moment. The client then waits for the server to send a datagram packet in response.

Two classes implement the server application: QuoteServer and QuoteServerThread. A single class implements the client application: QuoteClient.

Let's investigate these classes, starting with the class that contains the main method for the server application. Working With a Server-Side Application contains an applet version of the QuoteClient class.

The QuoteServer Class
The QuoteServer class, shown here in its entirety, contains a single method: the main method for the quote server application. The main method simply creates a new QuoteServerThread object and starts it:

  1. import java.io.*;
  2. public class QuoteServer {
  3. public static void main(String[] args) throws IOException {
  4. new QuoteServerThread().start();
  5. }
  6. }

The QuoteServerThread class implements the main logic of the quote server.

The QuoteServerThread Class
When created, the QuoteServerThread creates a DatagramSocket on port 4445 (arbitrarily chosen). This is the DatagramSocket through which the server communicates with all of its clients.

  1. public QuoteServerThread() throws IOException {
  2. this("QuoteServer");
  3. }
  4. public QuoteServerThread(String name) throws IOException {
  5. super(name);
  6. socket = new DatagramSocket(4445);
  7. try {
  8. in = new BufferedReader(new FileReader("one-liners.txt"));
  9. }
  10. catch (FileNotFoundException e){
  11. System.err.println("Couldn't open quote file. Serving time instead.");
  12. }
  13. }

Remember that certain ports are dedicated to well-known services and you cannot use them. If you specify a port that is in use, the creation of the DatagramSocket will fail.

The constructor also opens a BufferedReader on a file named one-liners.txt which contains a list of quotes. Each quote in the file is on a line by itself.

Now for the interesting part of the QuoteServerThread: its run method. The run method overrides run in the Thread class and provides the implementation for the thread. For information about threads, see Defining and Starting a Thread.

The run method contains a while loop that continues as long as there are more quotes in the file. During each iteration of the loop, the thread waits for a DatagramPacket to arrive over the DatagramSocket. The packet indicates a request from a client. In response to the client's request, the QuoteServerThread gets a quote from the file, puts it in a DatagramPacket and sends it over the DatagramSocket to the client that asked for it.

Let's look first at the section that receives the requests from clients:

  1. byte[] buf = new byte[256];
  2. DatagramPacket packet = new DatagramPacket(buf, buf.length);
  3. socket.receive(packet);

The first statement creates an array of bytes which is then used to create a DatagramPacket. The DatagramPacket will be used to receive a datagram from the socket because of the constructor used to create it. This constructor requires only two arguments: a byte array that contains client-specific data and the length of the byte array. When constructing a DatagramPacket to send over the DatagramSocket, you also must supply the Internet address and port number of the packet's destination. You'll see this later when we discuss how the server responds to a client request.

The last statement in the previous code snippet receives a datagram from the socket (the information received from the client gets copied into the packet). The receive method waits forever until a packet is received. If no packet is received, the server makes no further progress and just waits.

Now assume that, the server has received a request from a client for a quote. Now the server must respond. This section of code in the run method constructs the response:

  1. String dString = null;
  2. if (in == null)
  3. dString = new Date().toString();
  4. else
  5. dString = getNextQuote();
  6. buf = dString.getBytes();

If the quote file did not get opened for some reason, then in equals null. If this is the case, the quote server serves up the time of day instead. Otherwise, the quote server gets the next quote from the already opened file. Finally, the code converts the string to an array of bytes.
Now, the run method sends the response to the client over the DatagramSocket with this code:

  1. InetAddress address = packet.getAddress();
  2. int port = packet.getPort();
  3. packet = new DatagramPacket(buf, buf.length, address, port);
  4. socket.send(packet);

The first two statements in this code segment get the Internet address and the port number, respectively, from the datagram packet received from the client. The Internet address and port number indicate where the datagram packet came from. This is where the server must send its response. In this example, the byte array of the datagram packet contains no relevant information. The arrival of the packet itself indicates a request from a client that can be found at the Internet address and port number indicated in the datagram packet.

The third statement creates a new DatagramPacket object intended for sending a datagram message over the datagram socket. You can tell that the new DatagramPacket is intended to send data over the socket because of the constructor used to create it. This constructor requires four arguments. The first two arguments are the same required by the constructor used to create receiving datagrams: a byte array containing the message from the sender to the receiver and the length of this array. The next two arguments are different: an Internet address and a port number. These two arguments are the complete address of the destination of the datagram packet and must be supplied by the sender of the datagram. The last line of code sends the DatagramPacket on its way.

When the server has read all the quotes from the quote file, the while loop terminates and the run method cleans up:

  1. socket.close();

The QuoteClient Class
The QuoteClient class implements a client application for the QuoteServer. This application sends a request to the QuoteServer, waits for the response, and, when the response is received, displays it to the standard output. Let's look at the code in detail.

The QuoteClient class contains one method, the main method for the client application. The top of the main method declares several local variables for its use:

  1. int port;
  2. InetAddress address;
  3. DatagramSocket socket = null;
  4. DatagramPacket packet;
  5. byte[] sendBuf = new byte[256];

First, the main method processes the command-line arguments used to invoke the QuoteClient application:

  1. if (args.length != 1) {
  2. System.out.println("Usage: java QuoteClient <hostname>");
  3. return;
  4. }

The QuoteClient application requires one command-line arguments: the name of the machine on which the QuoteServer is running.

Next, the main method creates a DatagramSocket:

  1. DatagramSocket socket = new DatagramSocket();

The client uses a constructor that does not require a port number. This constructor just binds the DatagramSocket to any available local port. It doesn't matter what port the client is bound to because the DatagramPackets contain the addressing information. The server gets the port number from the DatagramPackets and send its response to that port.

Next, the QuoteClient program sends a request to the server:

  1. byte[] buf = new byte[256];
  2. InetAddress address = InetAddress.getByName(args[0]);
  3. DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445);
  4. socket.send(packet);

The code segment gets the Internet address for the host named on the command line (presumably the name of the machine on which the server is running). This InetAddress and the port number 4445 (the port number that the server used to create its DatagramSocket) are then used to create DatagramPacket destined for that Internet address and port number. Therefore the DatagramPacket will be delivered to the quote server.

Note that the code creates a DatagramPacket with an empty byte array. The byte array is empty because this datagram packet is simply a request to the server for information. All the server needs to know to send a response--the address and port number to which reply--is automatically part of the packet.

Next, the client gets a response from the server and displays it:

  1. packet = new DatagramPacket(buf, buf.length);
  2. socket.receive(packet);
  3. String received = new String(packet.getData(), 0, packet.getLength());
  4. System.out.println("Quote of the Moment: " + received);

To get a response from the server, the client creates a "receive" packet and uses the DatagramSocket receive method to receive the reply from the server. The receive method waits until a datagram packet destined for the client comes through the socket. Note that if the server's reply is somehow lost, the client will wait forever because of the no-guarantee policy of the datagram model. Normally, a client sets a timer so that it doesn't wait forever for a reply; if no reply arrives, the timer goes off and the client retransmits.

When the client receives a reply from the server, the client uses the getData method to retrieve that data from the packet. The client then converts the data to a string and displays it.
Running the Server and Client

After you've successfully compiled the server and the client programs, you run them. You have to run the server program first. Just use the Java interpreter and specify the QuoteServer class name.

Once the server has started, you can run the client program. Remember to run the client program with one command-line argument: the name of the host on which the QuoteServer is running.

After the client sends a request and receives a response from the server, you should see output similar to this:

Quote of the Moment:
Good programming is 99% sweat and 1% coffee.
The whole code is as following:

  1. /*
  2. *QuoteClient
  3. */
  4. import java.io.*;
  5. import java.net.*;
  6. import java.util.*;
  7. import java.io.*;
  8. public class QuoteClient {
  9. public static void main(String[] args) throws IOException {
  10. if (args.length != 1) {
  11. System.out.println("Usage: java QuoteClient <hostname>");
  12. return;
  13. }
  14. // get a datagram socket
  15. DatagramSocket socket = new DatagramSocket();
  16. // send request
  17. byte[] buf = new byte[256];
  18. InetAddress address = InetAddress.getByName(args[0]);
  19. for (int i = 0; i < 5; i++) {
  20. DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445);
  21. socket.send(packet);
  22. // get response
  23. packet = new DatagramPacket(buf, buf.length);
  24. socket.receive(packet);
  25. // display response
  26. String received = new String(packet.getData());
  27. System.out.println("Quote of the Moment: " + received);
  28. }
  29. socket.close();
  30. }
  31. }
  1. /*
  2. *QuoteServer
  3. */
  4. import java.io.*;
  5. import java.net.*;
  6. import java.util.*;
  7. public class QuoteServerThread extends Thread {
  8. protected DatagramSocket socket = null;
  9. protected BufferedReader in = null;
  10. protected boolean moreQuotes = true;
  11. public QuoteServerThread() throws IOException {
  12. this("QuoteServerThread");
  13. }
  14. public QuoteServerThread(String name) throws IOException {
  15. super(name);
  16. socket = new DatagramSocket(4445);
  17. try {
  18. in = new BufferedReader(new FileReader("one-liners.txt"));
  19. } catch (FileNotFoundException e) {
  20. System.err.println("Could not open quote file. Serving time instead.");
  21. }
  22. }
  23. public void run() {
  24. while (moreQuotes) {
  25. try {
  26. byte[] buf = new byte[256];
  27. // receive request
  28. DatagramPacket packet = new DatagramPacket(buf, buf.length);
  29. socket.receive(packet);
  30. // figure out response
  31. String dString = null;
  32. if (in == null)
  33. dString = new Date().toString();
  34. else
  35. dString = getNextQuote();
  36. buf = dString.getBytes();
  37. // send the response to the client at "address" and "port"
  38. InetAddress address = packet.getAddress();
  39. int port = packet.getPort();
  40. packet = new DatagramPacket(buf, buf.length, address, port);
  41. socket.send(packet);
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. moreQuotes = false;
  45. }
  46. }
  47. socket.close();
  48. }
  49. protected String getNextQuote() {
  50. String returnValue = null;
  51. try {
  52. if ((returnValue = in.readLine()) == null) {
  53. in.close();
  54. moreQuotes = false;
  55. returnValue = "No more quotes. Goodbye.";
  56. }
  57. } catch (IOException e) {
  58. returnValue = "IOException occurred in server.";
  59. }
  60. return returnValue;
  61. }
  62. }
  63. import java.io.*;
  64. public class QuoteServer {
  65. public static void main(String[] args) throws IOException {
  66. new QuoteServerThread().start();
  67. }
  68. }

13.9 Broadcasting to Multiple Recipients

In addition to DatagramSocket, which lets programs send packets to one another, java.net includes a class called MulticastSocket. This kind of socket is used on the client-side to listen for packets that the server broadcasts to multiple clients.The InetAddress and port used to construct the DatagramPacket.

Let's rewrite the quote server so that it broadcasts DatagramPackets to multiple recipients.

Instead of sending quotes to a specific client that makes a request, the new server now needs to broadcast quotes at a regular interval. The client needs to be modified so that it passively listens for quotes and does so on a MulticastSocket.

This example is comprised of three classes which are modifications of the three classes from the previous example: MulticastServer, MulticastServerThread, and MulticastClient. This discussion highlights the interesting parts of these classes.

Here is the new version of the server's main program. The differences between this code and the previous version, QuoteServer, are shown in bold:

  1. import java.io.*;
  2. public class MulticastServer {
  3. public static void main(String[] args) throws IOException {
  4. new MulticastServerThread().start();
  5. }
  6. }

Basically, the server got a new name and creates a MulticastServerThread instead of a QuoteServerThread. Now let's look at the MulticastServerThread which contains the heart of the server. Here's its class declaration:

  1. public class MulticastServerThread extends QuoteServerThread {
  2. // ...
  3. }

We've made this class a subclass of QuoteServerThread so that it can use the constructor, and inherit some member variable and the getNextQuote method. Recall that QuoteServerThread creates a DatagramSocket bound to port 4445 and opens the quote file. The DatagramSocket's port number doesn't actually matter in this example because the client never send anything to the server.
The only method explicitly implemented in MulticastServerThread is its run method. The differences between this run method and the one in QuoteServerThread are shown in bold:

  1. public void run() {
  2. while (moreQuotes) {
  3. try {
  4. byte[] buf = new byte[256];
  5. // don't wait for request...just send a quote
  6. String dString = null;
  7. if (in == null)
  8. dString = new Date().toString();
  9. else
  10. dString = getNextQuote();
  11. buf = dString.getBytes();
  12. InetAddress group = InetAddress.getByName("203.0.113.0");
  13. DatagramPacket packet;
  14. packet = new DatagramPacket(buf, buf.length, group, 4446);
  15. socket.send(packet);
  16. try {
  17. sleep((long)Math.random() * FIVE_SECONDS);
  18. }
  19. catch (InterruptedException e) { }
  20. }
  21. catch (IOException e) {
  22. e.printStackTrace();
  23. moreQuotes = false;
  24. }
  25. }
  26. socket.close();
  27. }

The interesting change is how the DatagramPacket is constructed, in particular, the InetAddress and port used to construct the DatagramPacket. Recall that the previous example retrieved the InetAddress and port number from the packet sent to the server from the client. This was because the server needed to reply directly to the client. Now, the server needs to address multiple clients. So this time both the InetAddress and the port number are hard-coded.

The hard-coded port number is 4446 (the client must have a MulticastSocket bound to this port). The hard-coded InetAddress of the DatagramPacket is "203.0.113.0" and is a group identifier (rather than the Internet address of the machine on which a single client is running). This particular address was arbitrarily chosen from the reserved for this purpose.

Created in this way, the DatagramPacket is destined for all clients listening to port number 4446 who are member of the "203.0.113.0" group.

To listen to port number 4446, the new client program just created its MulticastSocket with that port number. To become a member of the "203.0.113.0" group, the client calls the MulticastSocket's joinGroup method with the InetAddress that identifies the group. Now, the client is set up to receive DatagramPackets destined for the port and group specified. Here's the relevant code from the new client program (which was also rewritten to passively receive quotes rather than actively request them). The bold statements are the ones that interact with the MulticastSocket:

  1. MulticastSocket socket = new MulticastSocket(4446);
  2. InetAddress group = InetAddress.getByName("203.0.113.0");
  3. socket.joinGroup(group);
  4. DatagramPacket packet;
  5. for (int i = 0; i < 5; i++) {
  6. byte[] buf = new byte[256];
  7. packet = new DatagramPacket(buf, buf.length);
  8. socket.receive(packet);
  9. String received = new String(packet.getData());
  10. System.out.println("Quote of the Moment: " + received);
  11. }
  12. socket.leaveGroup(group);
  13. socket.close();

Notice that the server uses a DatagramSocket to broadcast packet received by the client over a MulticastSocket. Alternatively, it could have used a MulticastSocket. The socket used by the server to send the DatagramPacket is not important. What's important when broadcasting packets is the addressing information contained in the DatagramPacket, and the socket used by the client to listen for it

The whole code is as following:

  1. import java.io.*;
  2. import java.net.*;
  3. import java.util.*;
  4. public class MulticastClient {
  5. public static void main(String[] args) throws IOException {
  6. MulticastSocket socket = new MulticastSocket(2020);
  7. InetAddress group = InetAddress.getByName("230.0.0.1");
  8. //socket.setTimeToLive(100);
  9. socket.joinGroup(group);
  10. DatagramPacket packet;
  11. for (int i = 0; i < 5; i++) {
  12. //接收多播数据
  13. byte[] buf = new byte[256];
  14. packet = new DatagramPacket(buf, buf.length);
  15. socket.receive(packet);
  16. //显示接收结果
  17. String received = new String(packet.getData(), 0, packet.getLength());
  18. System.out.println("接收: " + received);
  19. }
  20. //离开多播组,关闭套接字
  21. socket.leaveGroup(group);
  22. socket.close();
  23. }
  24. }
  1. import java.io.*;
  2. import java.net.*;
  3. import java.util.*;
  4. import java.text.DateFormat;
  5. public class MulticastServer1 extends Thread{
  6. protected MulticastSocket socket = null;
  7. private InetAddress group;
  8. static int count = 0;
  9. int port = 2020;
  10. String groupIP ="230.0.0.1";
  11. public MulticastServer1() throws IOException {
  12. //创建绑定到指定地址的多播套接字对象
  13. //InetSocketAddress ina = new InetSocketAddress("localhost", port);
  14. //socket = new MulticastSocket(ina);
  15. socket = new MulticastSocket(port);
  16. //创建组播组地址
  17. group = InetAddress.getByName(groupIP);
  18. }
  19. public void run() {
  20. byte[] buf = new byte[256];
  21. System.out.println("多播服务器启动... ");
  22. while (true){
  23. count++;
  24. String str = "Hello " + ":" + count;
  25. System.out.println("广播信息: " + str);
  26. buf = str.getBytes();
  27. try {
  28. //使用多播套接字发送多播数据包
  29. DatagramPacket packet = new DatagramPacket(buf, buf.length,
  30. group, port);
  31. socket.send(packet);
  32. //间隔3秒
  33. Thread.sleep(3000);
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. //socket.close();
  39. }
  40. public static void main(String[] args) throws Exception {
  41. new MulticastServer().start();
  42. }
  43. }

13.10 URL

URL is an acronym for Uniform Resource Locator and is a reference (an address) to a resource on the Internet.
As in the previous diagram, a URL has two main components:
Protocol identifier : HTTP,FTP,Gopher,File and News
Resource name :Host Name , Filename , Port Number , Reference

  1. URLConnection yc = yahoo.openConnection();
  2. BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));

Appendix


ATM src:

  1. package admin;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.*;
  5. import java.io.*;
  6. public class AdminLogIn {
  7. private JFrame frame;
  8. private JPanel northPanel;
  9. private JLabel titleLabel;
  10. private JPanel centerPanel;
  11. private JPanel leftPanel;
  12. private JPanel rightPanel;
  13. private JLabel nameLabel;
  14. private JLabel passwordLabel;
  15. private JTextField accountTextField;
  16. private JPasswordField passwordTextField;
  17. private JPanel buttonPanel;
  18. private JButton logInButton;
  19. private JButton signUpButton;
  20. private JPanel mainPanel;
  21. private AdminLogIn() {
  22. frame = new JFrame("ATM Server");
  23. northPanel = new JPanel();
  24. titleLabel = new JLabel("Welcome to ATM server");
  25. centerPanel = new JPanel();
  26. leftPanel = new JPanel(new GridLayout(2, 1, 10, 10));
  27. rightPanel = new JPanel(new GridLayout(2, 1, 10, 10));
  28. nameLabel = new JLabel("Name:");
  29. passwordLabel = new JLabel("Password:");
  30. accountTextField = new JTextField();
  31. passwordTextField = new JPasswordField();
  32. buttonPanel = new JPanel();
  33. logInButton = new JButton("Log In");
  34. signUpButton = new JButton("Sign Up");
  35. mainPanel = new JPanel();
  36. }
  37. private void lunchFrame() {
  38. frame.setPreferredSize(new Dimension(700, 400));
  39. mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
  40. northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS));
  41. northPanel.add(titleLabel);
  42. titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
  43. mainPanel.add(northPanel);
  44. leftPanel.setPreferredSize(new Dimension(20, 70));
  45. leftPanel.add(nameLabel);
  46. leftPanel.add(passwordLabel);
  47. rightPanel.setPreferredSize(new Dimension(200, 70));
  48. rightPanel.add(accountTextField);
  49. rightPanel.add(passwordTextField);
  50. centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
  51. centerPanel.add(Box.createHorizontalGlue());
  52. centerPanel.add(leftPanel);
  53. centerPanel.add(rightPanel);
  54. centerPanel.add(Box.createHorizontalGlue());
  55. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
  56. JLabel unLabel = new JLabel();
  57. unLabel.setPreferredSize(new Dimension(80,30));
  58. buttonPanel.add(unLabel);
  59. buttonPanel.add(Box.createRigidArea(new Dimension(100,30)));
  60. buttonPanel.add(logInButton);
  61. logInButton.addActionListener(new LogInAction());
  62. buttonPanel.add(Box.createRigidArea(new Dimension(200,30)));
  63. buttonPanel.add(signUpButton);
  64. signUpButton.addActionListener(new SignUpAction());
  65. buttonPanel.add(Box.createHorizontalGlue());
  66. buttonPanel.add(Box.createHorizontalGlue());
  67. mainPanel.add(Box.createRigidArea(new Dimension(700, 50)));
  68. mainPanel.add(centerPanel);
  69. mainPanel.add(Box.createRigidArea(new Dimension(700, 50)));
  70. mainPanel.add(buttonPanel);
  71. mainPanel.add(Box.createRigidArea(new Dimension(700, 200)));
  72. frame.add(mainPanel);
  73. frame.pack();
  74. frame.setLocationRelativeTo(null);
  75. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  76. frame.setVisible(true);
  77. }
  78. private class LogInAction implements ActionListener {
  79. JDialog logInDialog;
  80. JTextField nameTextField;
  81. JPasswordField firstPasswordField;
  82. JPasswordField secondPasswordField;
  83. @Override
  84. public void actionPerformed(ActionEvent e) {
  85. logInDialog = new JDialog(frame, "Log In", false);
  86. logInDialog.setPreferredSize(new Dimension(700, 400));
  87. logInDialog.setLayout(new BorderLayout());
  88. JPanel dialogPanel = new JPanel();
  89. dialogPanel.setLayout(new BorderLayout());
  90. JPanel northPanel = new JPanel();
  91. northPanel.setPreferredSize(new Dimension(700, 100));
  92. JPanel southPanel = new JPanel();
  93. southPanel.setPreferredSize(new Dimension(700, 100));
  94. JPanel westPanel = new JPanel();
  95. westPanel.setPreferredSize(new Dimension(30, 400));
  96. JPanel eastPanel = new JPanel();
  97. eastPanel.setPreferredSize(new Dimension(30, 400));
  98. JPanel diaLeftPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  99. JPanel diaRightPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  100. JLabel nameLabel = new JLabel("Name");
  101. JLabel dialogPasswordLabel = new JLabel("Password");
  102. JLabel againLabel = new JLabel("Again");
  103. JLabel nullLabel = new JLabel();
  104. diaLeftPanel.add(nameLabel);
  105. diaLeftPanel.add(dialogPasswordLabel);
  106. diaLeftPanel.add(againLabel);
  107. diaLeftPanel.add(nullLabel);
  108. nameTextField = new JTextField();
  109. firstPasswordField = new JPasswordField();
  110. secondPasswordField = new JPasswordField();
  111. JLabel noneLabel = new JLabel();
  112. diaRightPanel.add(nameTextField);
  113. diaRightPanel.add(firstPasswordField);
  114. diaRightPanel.add(secondPasswordField);
  115. diaRightPanel.add(noneLabel);
  116. dialogPanel.add(diaLeftPanel, BorderLayout.WEST);
  117. dialogPanel.add(diaRightPanel, BorderLayout.CENTER);
  118. JButton OKButton = new JButton("OK");
  119. OKButton.addActionListener(new PassErrorAction());
  120. JPanel buttonPanel = new JPanel();
  121. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
  122. OKButton.setAlignmentX(Component.CENTER_ALIGNMENT);
  123. buttonPanel.add(OKButton);
  124. dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
  125. logInDialog.add(dialogPanel, BorderLayout.CENTER);
  126. logInDialog.add(northPanel, BorderLayout.NORTH);
  127. logInDialog.add(southPanel, BorderLayout.SOUTH);
  128. logInDialog.add(westPanel, BorderLayout.WEST);
  129. logInDialog.add(eastPanel, BorderLayout.EAST);
  130. logInDialog.pack();
  131. logInDialog.setLocationRelativeTo(null);
  132. logInDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  133. logInDialog.setVisible(true);
  134. }
  135. private class PassErrorAction implements ActionListener {
  136. @Override
  137. public void actionPerformed(ActionEvent e) {
  138. String name = nameTextField.getText();
  139. String firstPassword = String.valueOf(firstPasswordField.getPassword());
  140. String secondPassword = String.valueOf(secondPasswordField.getPassword());
  141. int result = 0;
  142. if (firstPassword.length() != secondPassword.length()) {
  143. result = 2;
  144. }
  145. if (!firstPassword.equals(secondPassword)) {
  146. result = 1;
  147. }
  148. switch (result) {
  149. case 0:
  150. String logInMessage = "0" + "-" + 0 + "-" + name + "-" + firstPassword;
  151. AdminNet net = AdminNet.getAdminNet();
  152. PrintWriter out = net.getPrintWriter();
  153. out.println(logInMessage);
  154. logInDialog.setVisible(false);
  155. break;
  156. case 1:
  157. LogInError error1 = new LogInError();
  158. error1.lunch();
  159. break;
  160. case 2:
  161. LogInError error2 = new LogInError();
  162. error2.lunch();
  163. break;
  164. }
  165. }
  166. }
  167. }
  168. private class LogInError {
  169. void lunch() {
  170. JDialog error = new JDialog(frame, "ERROR", false);
  171. error.setPreferredSize(new Dimension(300, 150));
  172. JLabel errorMessage = new JLabel("The Passwords are different.", JLabel.CENTER);
  173. error.add(errorMessage);
  174. error.pack();
  175. error.setLocationRelativeTo(null);
  176. error.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  177. error.setVisible(true);
  178. }
  179. }
  180. private class SignUpAction implements ActionListener {
  181. @Override
  182. public void actionPerformed(ActionEvent e) {
  183. boolean mark = false;
  184. String account = accountTextField.getText();
  185. String password = String.valueOf(passwordTextField.getPassword());
  186. AdminNet adminNet = AdminNet.getAdminNet();
  187. BufferedReader inBufferedReader = adminNet.getBufferedReader();
  188. PrintWriter outPrintWriter = adminNet.getPrintWriter();
  189. String result = "0";
  190. try {
  191. outPrintWriter.println("0" + "-" + 1 + "-" + account + "-" + password);
  192. result = inBufferedReader.readLine();
  193. } catch (IOException e1) {
  194. e1.printStackTrace();
  195. }
  196. JDialog errorDialog = new JDialog(frame, "Error", false);
  197. JLabel labelError = new JLabel("", JLabel.CENTER);
  198. switch (result) {
  199. case "0":
  200. labelError.setText("The Account Doesn't Exist.");
  201. errorDialog.add(labelError);
  202. break;
  203. case "1":
  204. labelError.setText("Account Is Empty.");
  205. errorDialog.add(labelError);
  206. break;
  207. case "2":
  208. labelError.setText("Password Is Empty.");
  209. errorDialog.add(labelError);
  210. break;
  211. case "3":
  212. mark = true;
  213. frame.setVisible(false);
  214. AdminMainWindow mainWindow = new AdminMainWindow();
  215. mainWindow.lunchFrame();
  216. break;
  217. case "4":
  218. labelError.setText("Password Is Wrong.");
  219. errorDialog.add(labelError);
  220. break;
  221. }
  222. if (!mark) {
  223. errorDialog.setPreferredSize(new Dimension(300, 150));
  224. errorDialog.setLocationRelativeTo(null);
  225. errorDialog.pack();
  226. errorDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  227. errorDialog.setVisible(true);
  228. }
  229. }
  230. }
  231. public static void main(String[] args) {
  232. javax.swing.SwingUtilities.invokeLater(() -> {
  233. new AdminLogIn().lunchFrame();
  234. });
  235. }
  236. }
  1. package admin;
  2. import bank.*;
  3. import javax.swing.*;
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.io.*;
  7. import java.util.StringTokenizer;
  8. public class AdminMainWindow {
  9. /* Stander error stream */
  10. static private PrintWriter stdErr = new PrintWriter(System.err, true);
  11. private JFrame frame;
  12. private JButton addModifyButton;
  13. private JButton removeButton;
  14. private JLabel noLabel;
  15. private JButton displayButton;
  16. private JTextArea statusTextArea;
  17. private JPanel centerPanel;
  18. private JButton searchButton;
  19. private JTextField searchTextField;
  20. private JPanel searchPanel;
  21. private JPanel northPanel;
  22. private JPanel westPanel;
  23. private JPanel eastPanel;
  24. private JPanel southPanel;
  25. private JPanel southNorthPanel;
  26. private JPanel southEastPanel;
  27. private JPanel southSouthPanel;
  28. private JPanel southCenterPanel;
  29. private JPanel centerCenterPanel;
  30. private JScrollPane textPane;
  31. private JPanel leftPanel;
  32. private JPanel rightPanel;
  33. private JLabel label1;
  34. private JLabel label2;
  35. private JLabel label3;
  36. private JLabel label4;
  37. private JTextField textField1;
  38. private JTextField textField2;
  39. private JTextField textField3;
  40. private JTextField textField4;
  41. private JLabel noneLabel;
  42. private JPanel buttonGroup;
  43. //TODO what this?
  44. private boolean logIn = false;
  45. AdminMainWindow() {
  46. frame = new JFrame("ATM Server");
  47. addModifyButton = new JButton("Add");
  48. removeButton = new JButton("Remove");
  49. noLabel = new JLabel();
  50. displayButton = new JButton("Exit");
  51. statusTextArea = new JTextArea();
  52. centerPanel = new JPanel(new BorderLayout());
  53. searchButton = new JButton("Search");
  54. searchTextField = new JTextField();
  55. searchPanel = new JPanel();
  56. northPanel = new JPanel();
  57. westPanel = new JPanel();
  58. eastPanel = new JPanel();
  59. southPanel = new JPanel(new BorderLayout());
  60. southNorthPanel = new JPanel();
  61. southEastPanel = new JPanel();
  62. southSouthPanel = new JPanel();
  63. southCenterPanel = new JPanel();
  64. centerCenterPanel = new JPanel(new BorderLayout());
  65. buttonGroup = new JPanel(new GridLayout(4, 1, 10, 10));
  66. textPane = new JScrollPane(statusTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  67. leftPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  68. rightPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  69. label1 = new JLabel("Name");
  70. label2 = new JLabel("Card ID");
  71. label3 = new JLabel("Telephone");
  72. label4 = new JLabel("Balance");
  73. textField1 = new JTextField();
  74. textField2 = new JTextField();
  75. textField3 = new JTextField();
  76. textField4 = new JTextField();
  77. noneLabel = new JLabel();
  78. AdminNet adminNet = AdminNet.getAdminNet();
  79. }
  80. void lunchFrame() {
  81. frame.setLayout(new BorderLayout());
  82. searchPanel.setLayout(new BoxLayout(searchPanel, BoxLayout.X_AXIS));
  83. searchPanel.add(Box.createHorizontalGlue());
  84. searchTextField.setPreferredSize(new Dimension(50, 20));
  85. searchPanel.add(searchTextField);
  86. searchPanel.add(Box.createRigidArea(new Dimension(50, 20)));
  87. searchPanel.add(searchButton);
  88. searchButton.addActionListener(new SearchAction());
  89. searchPanel.add(Box.createHorizontalGlue());
  90. statusTextArea.setEditable(false);
  91. buttonGroup.add(noneLabel);
  92. buttonGroup.add(addModifyButton);
  93. addModifyButton.addActionListener(new AddAction());
  94. buttonGroup.add(removeButton);
  95. removeButton.addActionListener(new RemoveAction());
  96. buttonGroup.add(noLabel);
  97. centerCenterPanel.add(buttonGroup, BorderLayout.EAST);
  98. JPanel centerWestPanel = new JPanel();
  99. centerWestPanel.setPreferredSize(new Dimension(30, 100));
  100. JPanel centerNorthPanel = new JPanel();
  101. centerNorthPanel.setPreferredSize(new Dimension(700, 10));
  102. JPanel centerSouthPanel = new JPanel();
  103. centerSouthPanel.setPreferredSize(new Dimension(700, 10));
  104. centerCenterPanel.add(centerNorthPanel, BorderLayout.NORTH);
  105. centerCenterPanel.add(centerSouthPanel, BorderLayout.SOUTH);
  106. textField2.setEditable(false);
  107. textField4.setEditable(false);
  108. leftPanel.add(label1);
  109. leftPanel.add(label2);
  110. leftPanel.add(label3);
  111. leftPanel.add(label4);
  112. rightPanel.add(textField1);
  113. rightPanel.add(textField2);
  114. rightPanel.add(textField3);
  115. rightPanel.add(textField4);
  116. centerCenterPanel.add(leftPanel, BorderLayout.WEST);
  117. centerCenterPanel.add(rightPanel, BorderLayout.CENTER);
  118. textPane.setPreferredSize(new Dimension(500, 200));
  119. centerPanel.add(searchPanel, BorderLayout.NORTH);
  120. centerPanel.add(textPane, BorderLayout.SOUTH);
  121. centerPanel.add(centerCenterPanel, BorderLayout.CENTER);
  122. southCenterPanel.setLayout(new BoxLayout(southCenterPanel, BoxLayout.Y_AXIS));
  123. displayButton.setAlignmentX(Component.RIGHT_ALIGNMENT);
  124. southCenterPanel.add(displayButton);
  125. displayButton.addActionListener(new ExitAction());
  126. southSouthPanel.setPreferredSize(new Dimension(700, 10));
  127. southNorthPanel.setPreferredSize(new Dimension(700, 10));
  128. southEastPanel.setPreferredSize(new Dimension(10, 30));
  129. southPanel.add(southNorthPanel, BorderLayout.NORTH);
  130. southPanel.add(southSouthPanel, BorderLayout.SOUTH);
  131. southPanel.add(southCenterPanel, BorderLayout.CENTER);
  132. southPanel.add(southEastPanel, BorderLayout.EAST);
  133. frame.add(northPanel, BorderLayout.NORTH);
  134. frame.add(centerPanel, BorderLayout.CENTER);
  135. frame.add(eastPanel, BorderLayout.EAST);
  136. frame.add(westPanel, BorderLayout.WEST);
  137. frame.add(southPanel, BorderLayout.SOUTH);
  138. frame.pack();
  139. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  140. /* Window width in pixels */
  141. int WIDTH = 620;
  142. /* Window height in pixels */
  143. int HEIGHT = 530;
  144. frame.setSize(WIDTH, HEIGHT);
  145. frame.setLocationRelativeTo(null);
  146. frame.setResizable(true);
  147. frame.setVisible(true);
  148. }
  149. private class AddAction implements ActionListener {
  150. @Override
  151. public void actionPerformed(ActionEvent e) {
  152. AdminNet adminNet = AdminNet.getAdminNet();
  153. PrintWriter adminWriter = adminNet.getPrintWriter();
  154. String name = textField1.getText();
  155. String telephone = textField3.getText();
  156. String addInfo = "1" + "-" + 0 + "-" + name + "-" + "00000000-" + telephone;
  157. adminWriter.println(addInfo);
  158. BufferedReader logInRead = adminNet.getBufferedReader();
  159. String id = "";
  160. try {
  161. id = logInRead.readLine();
  162. } catch (IOException e1) {
  163. e1.printStackTrace();
  164. }
  165. textField2.setText(id);
  166. textField4.setText("0.0");
  167. }
  168. }
  169. private class RemoveAction implements ActionListener {
  170. @Override
  171. public void actionPerformed(ActionEvent e) {
  172. String id = searchTextField.getText();
  173. String cardInfo = "1-7-YCL-" + id + "-123456";
  174. AdminNet adminNet = AdminNet.getAdminNet();
  175. PrintWriter adminPrint = adminNet.getPrintWriter();
  176. adminPrint.println(cardInfo);
  177. statusTextArea.setText("The card" + id + " has been removed");
  178. }
  179. }
  180. private class ExitAction implements ActionListener {
  181. @Override
  182. public void actionPerformed(ActionEvent e) {
  183. System.exit(0);
  184. }
  185. }
  186. private class SearchAction implements ActionListener {
  187. @Override
  188. public void actionPerformed(ActionEvent e) {
  189. String id = searchTextField.getText();
  190. String cardInfo = "1-6-YCL-" + id + "-123456";
  191. AdminNet adminNet = AdminNet.getAdminNet();
  192. PrintWriter adminPrint = adminNet.getPrintWriter();
  193. BufferedReader adminBuffered = adminNet.getBufferedReader();
  194. adminPrint.println(cardInfo);
  195. String cardInformation = "";
  196. try {
  197. cardInformation = adminBuffered.readLine();
  198. } catch (IOException e1) {
  199. e1.printStackTrace();
  200. }
  201. if (cardInformation.equals("error")) {
  202. statusTextArea.setText("The ID doesn't exist");
  203. } else {
  204. StringTokenizer info = new StringTokenizer(cardInformation, "-", false);
  205. String side = info.nextToken();
  206. String name = info.nextToken();
  207. String telephone = info.nextToken();
  208. String balance = info.nextToken();
  209. textField1.setText(name);
  210. textField2.setText(id);
  211. textField3.setText(telephone);
  212. textField4.setText(balance);
  213. }
  214. }
  215. }
  216. }
  1. package admin;
  2. import java.io.*;
  3. import java.net.Socket;
  4. public class AdminNet {
  5. private BufferedReader bufferedReader;
  6. private PrintWriter printWriter;
  7. private static AdminNet adminNet;
  8. private AdminNet() {
  9. try {
  10. //TODO why only local net?
  11. Socket socket = new Socket("127.0.0.1", 4448);
  12. bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  13. printWriter = new PrintWriter(socket.getOutputStream(), true);
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. static AdminNet getAdminNet() {
  19. if (adminNet == null) {
  20. adminNet = new AdminNet();
  21. }
  22. return adminNet;
  23. }
  24. BufferedReader getBufferedReader() {
  25. return bufferedReader;
  26. }
  27. PrintWriter getPrintWriter() {
  28. return printWriter;
  29. }
  30. //TODO NEVER USE
  31. public void operation() {
  32. try {
  33. bufferedReader.readLine();
  34. } catch (IOException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  1. package admin;
  2. import java.io.*;
  3. import java.util.StringTokenizer;
  4. public class AdminAccountManage {
  5. private BufferedReader in;
  6. private PrintWriter out;
  7. public AdminAccountManage() {
  8. File accountRecord = new File("Admin.txt");
  9. try {
  10. in = new BufferedReader(new FileReader(accountRecord));
  11. out = new PrintWriter(new FileWriter(accountRecord, true), true);
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. public int accountManage(String account, String password, String operation) {
  17. switch (operation) {
  18. case "0":
  19. String newAdmin = account + "-" + password;
  20. out.println(newAdmin);
  21. break;
  22. case "1":
  23. if (account == null || account.equals("")) {
  24. return 1;
  25. }
  26. if (password == null || password.equals("")) {
  27. return 2;
  28. }
  29. try {
  30. String message = in.readLine();
  31. while (message != null && !message.equals("")) {
  32. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  33. String name = stringTokenizer.nextToken();
  34. String pass = stringTokenizer.nextToken();
  35. if (name.equals(account)) {
  36. if (pass.equals(password)) {
  37. return 3;
  38. } else {
  39. return 4;
  40. }
  41. }
  42. message = in.readLine();
  43. }
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. break;
  48. }
  49. return 0;
  50. }
  51. }
  1. package client;
  2. import bank.ATMBank;
  3. import bank.Card;
  4. import bank.Customer;
  5. import javax.swing.*;
  6. import javax.swing.plaf.basic.DefaultMenuLayout;
  7. import java.awt.*;
  8. import java.awt.event.ActionEvent;
  9. import java.awt.event.ActionListener;
  10. import java.io.BufferedReader;
  11. import java.io.IOException;
  12. import java.io.PrintWriter;
  13. import java.util.StringTokenizer;
  14. public class ATMLogIn {
  15. private JFrame frame;
  16. private JPanel northPanel;
  17. private JLabel titleLabel;
  18. private JPanel centerPanel;
  19. private JPanel leftPanel;
  20. private JPanel rightPanel;
  21. private JLabel nameLabel;
  22. private JLabel passwordLabel;
  23. private JTextField accountTextField;
  24. private JPasswordField passwordTextField;
  25. private JPanel buttonPanel;
  26. private JButton logInButton;
  27. private JButton signUpButton;
  28. private JButton findPasswordButton;
  29. private JPanel mainPanel;
  30. public ATMLogIn() {
  31. frame = new JFrame("ATM");
  32. northPanel = new JPanel();
  33. titleLabel = new JLabel("Welcome to ATM");
  34. centerPanel = new JPanel();
  35. leftPanel = new JPanel(new GridLayout(2, 1, 10, 10));
  36. rightPanel = new JPanel(new GridLayout(2, 1, 10, 10));
  37. nameLabel = new JLabel("Card ID:");
  38. passwordLabel = new JLabel("Password:");
  39. accountTextField = new JTextField();
  40. passwordTextField = new JPasswordField();
  41. buttonPanel = new JPanel();
  42. logInButton = new JButton("Log In");
  43. signUpButton = new JButton("Sign Up");
  44. findPasswordButton = new JButton("Forget password");
  45. mainPanel = new JPanel();
  46. }
  47. public void lunchFrame() {
  48. frame.setPreferredSize(new Dimension(700, 400));
  49. mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
  50. northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS));
  51. northPanel.add(titleLabel);
  52. titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
  53. mainPanel.add(northPanel);
  54. leftPanel.setPreferredSize(new Dimension(20, 70));
  55. leftPanel.add(nameLabel);
  56. leftPanel.add(passwordLabel);
  57. rightPanel.setPreferredSize(new Dimension(200, 70));
  58. rightPanel.add(accountTextField);
  59. rightPanel.add(passwordTextField);
  60. centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
  61. centerPanel.add(Box.createHorizontalGlue());
  62. centerPanel.add(leftPanel);
  63. centerPanel.add(rightPanel);
  64. centerPanel.add(Box.createHorizontalGlue());
  65. // frame.add(centerPanel,BorderLayout.CENTER);
  66. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
  67. buttonPanel.add(Box.createHorizontalGlue());
  68. buttonPanel.add(logInButton);
  69. logInButton.addActionListener(new LogInAction());
  70. buttonPanel.add(Box.createHorizontalGlue());
  71. buttonPanel.add(signUpButton);
  72. signUpButton.addActionListener(new SignUpAction());
  73. buttonPanel.add(Box.createHorizontalGlue());
  74. buttonPanel.add(findPasswordButton);
  75. findPasswordButton.addActionListener(new FindPasswordAction());
  76. buttonPanel.add(Box.createHorizontalGlue());
  77. //frame.add(new JPanel(),BorderLayout.SOUTH);
  78. mainPanel.add(Box.createRigidArea(new Dimension(700, 50)));
  79. mainPanel.add(centerPanel);
  80. mainPanel.add(Box.createRigidArea(new Dimension(700, 50)));
  81. mainPanel.add(buttonPanel);
  82. mainPanel.add(Box.createRigidArea(new Dimension(700, 200)));
  83. frame.add(mainPanel);
  84. frame.setResizable(false);
  85. frame.pack();
  86. frame.setLocationRelativeTo(null);
  87. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  88. frame.setVisible(true);
  89. }
  90. private class LogInAction implements ActionListener {
  91. JDialog logInDialog;
  92. JTextField nameTextField;
  93. JPasswordField firstPasswordField;
  94. JPasswordField secondPasswordField;
  95. @Override
  96. public void actionPerformed(ActionEvent e) {
  97. logInDialog = new JDialog(frame, "Log In", false);
  98. logInDialog.setPreferredSize(new Dimension(700, 400));
  99. logInDialog.setLayout(new BorderLayout());
  100. JPanel dialogPanel = new JPanel();
  101. dialogPanel.setLayout(new BorderLayout());
  102. JPanel northPanel = new JPanel();
  103. northPanel.setPreferredSize(new Dimension(700, 100));
  104. JPanel southPanel = new JPanel();
  105. southPanel.setPreferredSize(new Dimension(700, 100));
  106. JPanel westPanel = new JPanel();
  107. westPanel.setPreferredSize(new Dimension(30, 400));
  108. JPanel eastPanel = new JPanel();
  109. eastPanel.setPreferredSize(new Dimension(30, 400));
  110. JPanel diaLeftPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  111. JPanel diaRightPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  112. JLabel nameLabel = new JLabel("Name");
  113. JLabel dialogPasswordLabel = new JLabel("Telephone");
  114. JLabel againLabel = new JLabel("Again");
  115. JLabel nullLabel = new JLabel();
  116. diaLeftPanel.add(nameLabel);
  117. diaLeftPanel.add(dialogPasswordLabel);
  118. diaLeftPanel.add(againLabel);
  119. diaLeftPanel.add(nullLabel);
  120. nameTextField = new JTextField();
  121. firstPasswordField = new JPasswordField();
  122. secondPasswordField = new JPasswordField();
  123. JLabel noneLabel = new JLabel();
  124. diaRightPanel.add(nameTextField);
  125. diaRightPanel.add(firstPasswordField);
  126. diaRightPanel.add(secondPasswordField);
  127. diaRightPanel.add(noneLabel);
  128. dialogPanel.add(diaLeftPanel, BorderLayout.WEST);
  129. dialogPanel.add(diaRightPanel, BorderLayout.CENTER);
  130. JButton OKButton = new JButton("OK");
  131. JButton finishButton = new JButton("Finish");
  132. OKButton.addActionListener(new PassErrorAction());
  133. finishButton.addActionListener(new FinishAction());
  134. JPanel buttonPanel = new JPanel();
  135. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
  136. JLabel unUseLabel = new JLabel();
  137. unUseLabel.setPreferredSize(new Dimension(150, 30));
  138. buttonPanel.add(unUseLabel);
  139. buttonPanel.add(Box.createRigidArea(new Dimension(220, 30)));
  140. buttonPanel.add(OKButton);
  141. buttonPanel.add(Box.createRigidArea(new Dimension(100, 30)));
  142. buttonPanel.add(finishButton);
  143. dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
  144. logInDialog.add(dialogPanel, BorderLayout.CENTER);
  145. logInDialog.add(northPanel, BorderLayout.NORTH);
  146. logInDialog.add(southPanel, BorderLayout.SOUTH);
  147. logInDialog.add(westPanel, BorderLayout.WEST);
  148. logInDialog.add(eastPanel, BorderLayout.EAST);
  149. logInDialog.pack();
  150. logInDialog.setLocationRelativeTo(null);
  151. logInDialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
  152. logInDialog.setVisible(true);
  153. }
  154. private class FinishAction implements ActionListener {
  155. @Override
  156. public void actionPerformed(ActionEvent e) {
  157. logInDialog.setVisible(false);
  158. }
  159. }
  160. private class PassErrorAction implements ActionListener {
  161. @Override
  162. public void actionPerformed(ActionEvent e) {
  163. String name = nameTextField.getText();
  164. char[] firstTelephone = firstPasswordField.getPassword();
  165. char[] secondTelephone = secondPasswordField.getPassword();
  166. int result = 0;
  167. if (name.equals("") || name == null) {
  168. result = -1;
  169. } else if (firstTelephone.length == secondTelephone.length) {
  170. for (int i = 0; i < firstTelephone.length; i++) {
  171. if (firstTelephone[i] == secondTelephone[i]) {
  172. result = 0;
  173. } else {
  174. result = 1;
  175. break;
  176. }
  177. }
  178. } else {
  179. result = 2;
  180. }
  181. switch (result) {
  182. case -1: {
  183. LogInError error1 = new LogInError();
  184. error1.lunch(-1);
  185. break;
  186. }
  187. case 0: {
  188. String logInPassword = "";
  189. for (int i = 0; i < firstTelephone.length; i++) {
  190. logInPassword += firstTelephone[i];
  191. }
  192. String logInMessage = "1" + "-" + 0 + "-" + name + "-" + "00000000-" + logInPassword;
  193. ATMNet net = ATMNet.getAtmNet();
  194. PrintWriter out = net.getPrintWriter();
  195. out.println(logInMessage);
  196. BufferedReader logInRead = net.getBufferedReader();
  197. String id = "";
  198. try {
  199. id = logInRead.readLine();
  200. } catch (IOException e1) {
  201. e1.printStackTrace();
  202. }
  203. JDialog dialog = new JDialog(logInDialog, "Message", false);
  204. JLabel label1 = new JLabel("", JLabel.CENTER);
  205. JLabel label2 = new JLabel("", JLabel.CENTER);
  206. JPanel panel = new JPanel(new BorderLayout());
  207. JPanel northPanel = new JPanel();
  208. northPanel.setPreferredSize(new Dimension(300, 30));
  209. JPanel southPanel = new JPanel();
  210. southPanel.setPreferredSize(new Dimension(300, 30));
  211. JPanel centerPanel = new JPanel();
  212. centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
  213. dialog.setPreferredSize(new Dimension(300, 150));
  214. String information = "ID:" + id;
  215. String info = "Password:123456";
  216. label2.setText(info);
  217. label1.setText(information);
  218. JLabel unLabel = new JLabel();
  219. unLabel.setPreferredSize(new Dimension(30,30));
  220. centerPanel.add(unLabel);
  221. centerPanel.add(Box.createRigidArea(new Dimension(80,30)));
  222. centerPanel.add(label1);
  223. centerPanel.add(Box.createRigidArea(new Dimension(20, 30)));
  224. centerPanel.add(label2);
  225. panel.add(northPanel, BorderLayout.NORTH);
  226. panel.add(southPanel, BorderLayout.SOUTH);
  227. panel.add(centerPanel, BorderLayout.CENTER);
  228. dialog.add(panel);
  229. dialog.pack();
  230. dialog.setLocationRelativeTo(null);
  231. dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
  232. dialog.setVisible(true);
  233. break;
  234. }
  235. case 1: {
  236. LogInError error1 = new LogInError();
  237. error1.lunch(1);
  238. break;
  239. }
  240. case 2: {
  241. LogInError error2 = new LogInError();
  242. error2.lunch(2);
  243. break;
  244. }
  245. }
  246. }
  247. }
  248. }
  249. private class LogInError {
  250. public void lunch(int result) {
  251. JDialog error = new JDialog(frame, "ERROR", false);
  252. error.setPreferredSize(new Dimension(300, 150));
  253. JLabel errorMessage = new JLabel("", JLabel.CENTER);
  254. if (result == -1) {
  255. errorMessage.setText("The Name Is Empty.");
  256. } else {
  257. errorMessage.setText("The Passwords are different.");
  258. }
  259. error.add(errorMessage);
  260. error.pack();
  261. error.setLocationRelativeTo(null);
  262. error.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
  263. error.setVisible(true);
  264. }
  265. }
  266. private class SignUpAction implements ActionListener {
  267. @Override
  268. public void actionPerformed(ActionEvent e) {
  269. boolean mark = false;
  270. String account = accountTextField.getText();
  271. char[] passwordTemp = passwordTextField.getPassword();
  272. String password = "";
  273. for (int i = 0; i < passwordTemp.length; i++) {
  274. password += passwordTemp[i];
  275. }
  276. ATMNet atmNet = ATMNet.getAtmNet();
  277. BufferedReader inBufferedReader = atmNet.getBufferedReader();
  278. PrintWriter outPrintWriter = atmNet.getPrintWriter();
  279. String result = "0";
  280. try {
  281. outPrintWriter.println("1" + "-" + 1 + "-" + "YCL" + "-" + account + "-" + password);
  282. result = inBufferedReader.readLine();
  283. } catch (IOException e1) {
  284. e1.printStackTrace();
  285. }
  286. StringTokenizer stringTokenizer = new StringTokenizer(result, "-", false);
  287. String num = stringTokenizer.nextToken();
  288. String balance = stringTokenizer.nextToken();
  289. JDialog errorDialog = new JDialog(frame, "Error", false);
  290. JLabel labelError = new JLabel("", JLabel.CENTER);
  291. switch (num) {
  292. case "0": {
  293. labelError.setText("The Account Doesn't Exist.");
  294. errorDialog.add(labelError);
  295. break;
  296. }
  297. case "1": {
  298. labelError.setText("Account Is Empty.");
  299. errorDialog.add(labelError);
  300. break;
  301. }
  302. case "2": {
  303. labelError.setText("Password Is Empty.");
  304. errorDialog.add(labelError);
  305. break;
  306. }
  307. case "3": {
  308. mark = true;
  309. frame.setVisible(false);
  310. Card card = new Card(account);
  311. card.setBalance(balance, 1);
  312. ATMMainWindow mainWindow = new ATMMainWindow(card);
  313. mainWindow.lunchFrame();
  314. break;
  315. }
  316. case "4": {
  317. labelError.setText("Password Is Wrong.");
  318. errorDialog.add(labelError);
  319. break;
  320. }
  321. case "5":{
  322. labelError.setText("The client has logged.");
  323. errorDialog.add(labelError);
  324. break;
  325. }
  326. }
  327. if (mark == false) {
  328. errorDialog.setPreferredSize(new Dimension(300, 150));
  329. errorDialog.pack();
  330. errorDialog.setLocationRelativeTo(null);
  331. errorDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  332. errorDialog.setVisible(true);
  333. }
  334. }
  335. }
  336. private class FindPasswordAction implements ActionListener {
  337. JDialog logInDialog;
  338. JTextField nameTextField;
  339. JPasswordField firstPasswordField;
  340. JPasswordField secondPasswordField;
  341. @Override
  342. public void actionPerformed(ActionEvent e) {
  343. logInDialog = new JDialog(frame, "Forget Password", false);
  344. logInDialog.setPreferredSize(new Dimension(700, 400));
  345. logInDialog.setLayout(new BorderLayout());
  346. JPanel dialogPanel = new JPanel();
  347. dialogPanel.setLayout(new BorderLayout());
  348. JPanel northPanel = new JPanel();
  349. northPanel.setPreferredSize(new Dimension(700, 100));
  350. JPanel southPanel = new JPanel();
  351. southPanel.setPreferredSize(new Dimension(700, 100));
  352. JPanel westPanel = new JPanel();
  353. westPanel.setPreferredSize(new Dimension(30, 400));
  354. JPanel eastPanel = new JPanel();
  355. eastPanel.setPreferredSize(new Dimension(30, 400));
  356. JPanel diaLeftPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  357. JPanel diaRightPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  358. JLabel nameLabel = new JLabel("ID");
  359. JLabel dialogPasswordLabel = new JLabel("Telephone");
  360. JLabel againLabel = new JLabel("Again");
  361. JLabel nullLabel = new JLabel();
  362. diaLeftPanel.add(nameLabel);
  363. diaLeftPanel.add(dialogPasswordLabel);
  364. diaLeftPanel.add(againLabel);
  365. diaLeftPanel.add(nullLabel);
  366. nameTextField = new JTextField();
  367. firstPasswordField = new JPasswordField();
  368. secondPasswordField = new JPasswordField();
  369. JLabel noneLabel = new JLabel();
  370. diaRightPanel.add(nameTextField);
  371. diaRightPanel.add(firstPasswordField);
  372. diaRightPanel.add(secondPasswordField);
  373. diaRightPanel.add(noneLabel);
  374. dialogPanel.add(diaLeftPanel, BorderLayout.WEST);
  375. dialogPanel.add(diaRightPanel, BorderLayout.CENTER);
  376. JButton OKButton = new JButton("OK");
  377. JButton finishButton = new JButton("Finish");
  378. OKButton.addActionListener(new TeleErrorAction());
  379. finishButton.addActionListener(new FinishAction());
  380. JPanel buttonPanel = new JPanel();
  381. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
  382. JLabel unUseLabel = new JLabel();
  383. unUseLabel.setPreferredSize(new Dimension(150, 30));
  384. buttonPanel.add(unUseLabel);
  385. buttonPanel.add(Box.createRigidArea(new Dimension(220, 30)));
  386. buttonPanel.add(OKButton);
  387. buttonPanel.add(Box.createRigidArea(new Dimension(100, 30)));
  388. buttonPanel.add(finishButton);
  389. dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
  390. logInDialog.add(dialogPanel, BorderLayout.CENTER);
  391. logInDialog.add(northPanel, BorderLayout.NORTH);
  392. logInDialog.add(southPanel, BorderLayout.SOUTH);
  393. logInDialog.add(westPanel, BorderLayout.WEST);
  394. logInDialog.add(eastPanel, BorderLayout.EAST);
  395. logInDialog.pack();
  396. logInDialog.setLocationRelativeTo(null);
  397. logInDialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
  398. logInDialog.setVisible(true);
  399. }
  400. private class FinishAction implements ActionListener {
  401. @Override
  402. public void actionPerformed(ActionEvent e) {
  403. logInDialog.setVisible(false);
  404. }
  405. }
  406. private class TeleErrorAction implements ActionListener {
  407. @Override
  408. public void actionPerformed(ActionEvent e) {
  409. String name = nameTextField.getText();
  410. char[] firstTelephone = firstPasswordField.getPassword();
  411. char[] secondTelephone = secondPasswordField.getPassword();
  412. int result = 0;
  413. if (name.equals("") || name == null) {
  414. result = -1;
  415. } else if (firstTelephone.length == secondTelephone.length) {
  416. for (int i = 0; i < firstTelephone.length; i++) {
  417. if (firstTelephone[i] == secondTelephone[i]) {
  418. result = 0;
  419. } else {
  420. result = 1;
  421. break;
  422. }
  423. }
  424. } else {
  425. result = 2;
  426. }
  427. switch (result) {
  428. case -1: {
  429. FindError error1 = new FindError();
  430. error1.lunch(-1);
  431. break;
  432. }
  433. case 0: {
  434. String logInPassword = "";
  435. for (int i = 0; i < firstTelephone.length; i++) {
  436. logInPassword += firstTelephone[i];
  437. }
  438. String logInMessage = "1" + "-" + 9 + "-" + name + "-" + "00000000-" + logInPassword;
  439. ATMNet net = ATMNet.getAtmNet();
  440. PrintWriter out = net.getPrintWriter();
  441. out.println(logInMessage);
  442. BufferedReader logInRead = net.getBufferedReader();
  443. String id = "";
  444. try {
  445. id = logInRead.readLine();
  446. } catch (IOException e1) {
  447. e1.printStackTrace();
  448. }
  449. switch (id) {
  450. case "0": {
  451. JDialog dialog = new JDialog(logInDialog, "Message", false);
  452. JLabel label1 = new JLabel("", JLabel.CENTER);
  453. JLabel label2 = new JLabel("", JLabel.CENTER);
  454. JPanel panel = new JPanel(new BorderLayout());
  455. JPanel northPanel = new JPanel();
  456. northPanel.setPreferredSize(new Dimension(300, 30));
  457. JPanel southPanel = new JPanel();
  458. southPanel.setPreferredSize(new Dimension(300, 30));
  459. JPanel centerPanel = new JPanel();
  460. centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
  461. dialog.setPreferredSize(new Dimension(300, 150));
  462. label1.setPreferredSize(new Dimension(30,30));
  463. String info = "Password:123456";
  464. label2.setText(info);
  465. centerPanel.add(label1);
  466. centerPanel.add(Box.createRigidArea(new Dimension(100, 30)));
  467. centerPanel.add(label2);
  468. panel.add(northPanel, BorderLayout.NORTH);
  469. panel.add(southPanel, BorderLayout.SOUTH);
  470. panel.add(centerPanel, BorderLayout.CENTER);
  471. dialog.add(panel);
  472. dialog.pack();
  473. dialog.setLocationRelativeTo(null);
  474. dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
  475. dialog.setVisible(true);
  476. break;
  477. }
  478. case "0-0":{
  479. FindError error0 = new FindError();
  480. error0.lunch(99);
  481. }
  482. }
  483. break;
  484. }
  485. case 1: {
  486. FindError error1 = new FindError();
  487. error1.lunch(1);
  488. break;
  489. }
  490. case 2: {
  491. FindError error2 = new FindError();
  492. error2.lunch(2);
  493. break;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. private class FindError {
  500. public void lunch(int result) {
  501. JDialog error = new JDialog(frame, "ERROR", false);
  502. error.setPreferredSize(new Dimension(300, 150));
  503. JLabel errorMessage = new JLabel("", JLabel.CENTER);
  504. if (result == -1) {
  505. errorMessage.setText("The Name Is Empty.");
  506. }else if(result==99){
  507. errorMessage.setText("The Account Doesn't Exist.");
  508. }
  509. else {
  510. errorMessage.setText("The Telephone are different.");
  511. }
  512. error.add(errorMessage);
  513. error.pack();
  514. error.setLocationRelativeTo(null);
  515. error.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
  516. error.setVisible(true);
  517. }
  518. }
  519. public static void main(String[] args) {
  520. javax.swing.SwingUtilities.invokeLater(new Runnable() {
  521. @Override
  522. public void run() {
  523. ATMLogIn atmLog = new ATMLogIn();
  524. atmLog.lunchFrame();
  525. }
  526. });
  527. }
  528. }
  1. package client;
  2. import bank.Card;
  3. import bank.Customer;
  4. import javax.swing.*;
  5. import java.awt.*;
  6. import java.awt.event.ActionEvent;
  7. import java.awt.event.ActionListener;
  8. import java.io.BufferedReader;
  9. import java.io.PrintWriter;
  10. import java.text.NumberFormat;
  11. public class ATMMainWindow {
  12. private JFrame frame;
  13. private JLabel nameLabel;
  14. private JPanel northPanel;
  15. private JPanel westPanel;
  16. private JPanel eastPanel;
  17. private JButton displayButton;
  18. private JButton withdrawButton;
  19. private JButton depositButton;
  20. private JButton transferButton;
  21. private JButton modifyButton;
  22. private JButton exitButton;
  23. private JTextField messageArea;
  24. private JPanel southPanel;
  25. private Operation operation;
  26. private Customer ATMCustomer;
  27. private Card ATMCard;
  28. NumberFormat currency_format = NumberFormat.getCurrencyInstance();
  29. public ATMMainWindow(Card card) {
  30. ATMCustomer = card.getCustomer(card);
  31. ATMCard = card;
  32. frame = new JFrame("ATM");
  33. nameLabel = new JLabel("Welcome, " + "" + ATMCustomer.getName());
  34. northPanel = new JPanel();
  35. westPanel = new JPanel();
  36. eastPanel = new JPanel();
  37. displayButton = new JButton("Display");
  38. withdrawButton = new JButton("WithDraw");
  39. depositButton = new JButton("Deposit");
  40. transferButton = new JButton("Transfer");
  41. modifyButton = new JButton("Modify");
  42. exitButton = new JButton("Exit");
  43. messageArea = new JTextField();
  44. messageArea.setHorizontalAlignment(JTextField.CENTER);
  45. messageArea.setBackground(Color.WHITE);;
  46. southPanel = new JPanel();
  47. operation = new Operation(card);
  48. }
  49. public void lunchFrame() {
  50. frame.setPreferredSize(new Dimension(700, 400));
  51. frame.setLayout(new BorderLayout());
  52. northPanel.add(nameLabel);
  53. frame.add(northPanel, BorderLayout.NORTH);
  54. westPanel.setLayout(new GridLayout(3, 1, 80, 80));
  55. westPanel.add(displayButton);
  56. westPanel.add(modifyButton);
  57. westPanel.add(exitButton);
  58. eastPanel.setLayout(new GridLayout(3, 1, 80, 80));
  59. eastPanel.add(depositButton);
  60. eastPanel.add(withdrawButton);
  61. eastPanel.add(transferButton);
  62. displayButton.addActionListener(new DisplayAction());
  63. modifyButton.addActionListener(new ModifyAction());
  64. exitButton.addActionListener(new ExitAction());
  65. depositButton.addActionListener(new Deposit());
  66. withdrawButton.addActionListener(new Withdraw());
  67. transferButton.addActionListener(new Transfer());
  68. messageArea.setEditable(false);
  69. southPanel.setPreferredSize(new Dimension(700, 30));
  70. frame.add(messageArea, BorderLayout.CENTER);
  71. frame.add(westPanel, BorderLayout.WEST);
  72. frame.add(eastPanel, BorderLayout.EAST);
  73. frame.add(southPanel, BorderLayout.SOUTH);
  74. frame.pack();
  75. frame.setLocationRelativeTo(null);
  76. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  77. frame.setVisible(true);
  78. }
  79. private class DisplayAction implements ActionListener {
  80. @Override
  81. public void actionPerformed(ActionEvent e) {
  82. String message = operation.display();
  83. messageArea.setText(message);
  84. }
  85. }
  86. private class ExitAction implements ActionListener {
  87. @Override
  88. public void actionPerformed(ActionEvent e) {
  89. System.exit(0);
  90. }
  91. }
  92. private class ModifyAction implements ActionListener {
  93. JDialog ModifyDialog;
  94. JTextField nameTextField;
  95. JPasswordField firstPasswordField;
  96. JPasswordField secondPasswordField;
  97. @Override
  98. public void actionPerformed(ActionEvent e) {
  99. ModifyDialog = new JDialog(frame, "Modify Password", false);
  100. ModifyDialog.setPreferredSize(new Dimension(700, 400));
  101. ModifyDialog.setLayout(new BorderLayout());
  102. JPanel dialogPanel = new JPanel();
  103. dialogPanel.setLayout(new BorderLayout());
  104. JPanel northPanel = new JPanel();
  105. northPanel.setPreferredSize(new Dimension(700, 100));
  106. JPanel southPanel = new JPanel();
  107. southPanel.setPreferredSize(new Dimension(700, 100));
  108. JPanel westPanel = new JPanel();
  109. westPanel.setPreferredSize(new Dimension(30, 400));
  110. JPanel eastPanel = new JPanel();
  111. eastPanel.setPreferredSize(new Dimension(30, 400));
  112. JPanel diaLeftPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  113. JPanel diaRightPanel = new JPanel(new GridLayout(4, 1, 10, 10));
  114. JLabel nameLabel = new JLabel("Name");
  115. JLabel dialogPasswordLabel = new JLabel("Password");
  116. JLabel againLabel = new JLabel("Again");
  117. JLabel nullLabel = new JLabel();
  118. diaLeftPanel.add(nameLabel);
  119. diaLeftPanel.add(dialogPasswordLabel);
  120. diaLeftPanel.add(againLabel);
  121. diaLeftPanel.add(nullLabel);
  122. nameTextField = new JTextField();
  123. firstPasswordField = new JPasswordField();
  124. secondPasswordField = new JPasswordField();
  125. JLabel noneLabel = new JLabel();
  126. diaRightPanel.add(nameTextField);
  127. diaRightPanel.add(firstPasswordField);
  128. diaRightPanel.add(secondPasswordField);
  129. diaRightPanel.add(noneLabel);
  130. dialogPanel.add(diaLeftPanel, BorderLayout.WEST);
  131. dialogPanel.add(diaRightPanel, BorderLayout.CENTER);
  132. JButton OKButton = new JButton("OK");
  133. OKButton.addActionListener(new PassErrorAction());
  134. JPanel buttonPanel = new JPanel();
  135. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
  136. OKButton.setAlignmentX(Component.CENTER_ALIGNMENT);
  137. buttonPanel.add(OKButton);
  138. dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
  139. ModifyDialog.add(dialogPanel, BorderLayout.CENTER);
  140. ModifyDialog.add(northPanel, BorderLayout.NORTH);
  141. ModifyDialog.add(southPanel, BorderLayout.SOUTH);
  142. ModifyDialog.add(westPanel, BorderLayout.WEST);
  143. ModifyDialog.add(eastPanel, BorderLayout.EAST);
  144. ModifyDialog.pack();
  145. ModifyDialog.setLocationRelativeTo(null);
  146. ModifyDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  147. ModifyDialog.setVisible(true);
  148. }
  149. private class PassErrorAction implements ActionListener {
  150. @Override
  151. public void actionPerformed(ActionEvent e) {
  152. String name = nameTextField.getText();
  153. char[] firstPassword = firstPasswordField.getPassword();
  154. char[] secondPassword = secondPasswordField.getPassword();
  155. String password = "";
  156. int result = 0;
  157. if (firstPassword.length == secondPassword.length) {
  158. for (int i = 0; i < firstPassword.length; i++) {
  159. if (firstPassword[i] == secondPassword[i]) {
  160. password += firstPassword[i];
  161. result = 0;
  162. } else {
  163. result = 1;
  164. break;
  165. }
  166. }
  167. } else {
  168. result = 2;
  169. }
  170. switch (result) {
  171. case 0: {
  172. ATMNet atmNet = ATMNet.getAtmNet();
  173. BufferedReader bufferedReader = atmNet.getBufferedReader();
  174. PrintWriter printWriter = atmNet.getPrintWriter();
  175. printWriter.println(1 + "-" + 4 + "-" + name + "-" + ATMCard.getID() + "-" + password);
  176. ModifyDialog.setVisible(false);
  177. messageArea.setText("Password has been modified successfully...");
  178. break;
  179. }
  180. case 1: {
  181. ModifyError error1 = new ModifyError();
  182. error1.lunch();
  183. break;
  184. }
  185. case 2: {
  186. ModifyError error2 = new ModifyError();
  187. error2.lunch();
  188. break;
  189. }
  190. }
  191. }
  192. }
  193. }
  194. private class ModifyError {
  195. public void lunch() {
  196. JDialog error = new JDialog(frame, "ERROR", false);
  197. error.setPreferredSize(new Dimension(300, 150));
  198. JLabel errorMessage = new JLabel("", JLabel.CENTER);
  199. errorMessage.setText("The Passwords are different.");
  200. error.add(errorMessage);
  201. error.pack();
  202. error.setLocationRelativeTo(null);
  203. error.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  204. error.setVisible(true);
  205. }
  206. }
  207. private class InputMoney {
  208. JDialog inputMoney;
  209. JTextField inputMoneyText;
  210. JTextField IDTextField;
  211. public void lunch(String op) {
  212. inputMoney = new JDialog(frame, "InputMoney", false);
  213. JPanel northPanel = new JPanel();
  214. northPanel.setPreferredSize(new Dimension(300, 10));
  215. JPanel southPanel = new JPanel();
  216. southPanel.setPreferredSize(new Dimension(300, 10));
  217. JPanel inputPanel = new JPanel(new FlowLayout());
  218. JLabel inputMoneyLabel = new JLabel("Money");
  219. inputMoneyText = new JTextField();
  220. JButton inputButton = new JButton("OK");
  221. if (op == "10") {
  222. JPanel labelPanel = new JPanel(new GridLayout(2, 1, 5, 5));
  223. JPanel textPanel = new JPanel(new GridLayout(2, 1, 5, 5));
  224. JLabel IDLabel = new JLabel("ID");
  225. IDTextField = new JTextField();
  226. IDTextField.setPreferredSize(new Dimension(150, 20));
  227. labelPanel.add(IDLabel);
  228. labelPanel.add(inputMoneyLabel);
  229. textPanel.add(IDTextField);
  230. textPanel.add(inputMoneyText);
  231. inputPanel.add(labelPanel);
  232. inputPanel.add(textPanel);
  233. inputPanel.add(inputButton);
  234. } else {
  235. inputMoneyText.setPreferredSize(new Dimension(150, 20));
  236. inputPanel.setLayout(new FlowLayout());
  237. inputPanel.add(inputMoneyLabel);
  238. inputPanel.add(inputMoneyText);
  239. inputPanel.add(inputButton);
  240. }
  241. inputMoney.setLayout(new BorderLayout());
  242. inputMoney.add(inputPanel, BorderLayout.CENTER);
  243. inputMoney.add(northPanel, BorderLayout.NORTH);
  244. inputMoney.add(southPanel, BorderLayout.SOUTH);
  245. inputButton.addActionListener(new InputActionListener(op));
  246. inputMoney.pack();
  247. inputMoney.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  248. inputMoney.setLocationRelativeTo(null);
  249. inputMoney.setVisible(true);
  250. //return money[0];
  251. }
  252. private class InputActionListener implements ActionListener {
  253. private String operationInput;
  254. private String money;
  255. private String transferID;
  256. public InputActionListener(String op) {
  257. operationInput = op;
  258. }
  259. @Override
  260. public void actionPerformed(ActionEvent e) {
  261. money = inputMoneyText.getText();
  262. float displayMessage =Float.parseFloat(money);
  263. if (operationInput == "00") {
  264. operation.deposit(money);
  265. messageArea.setText(currency_format.format(displayMessage) + " has been deposited...");
  266. } else if (operationInput == "01") {
  267. boolean result = operation.withdraw(money);
  268. if (result) {
  269. messageArea.setText(currency_format.format(displayMessage) + " has been withdrew...");
  270. } else {
  271. messageArea.setText(currency_format.format(displayMessage) + " is withdrew unsuccessful...");
  272. }
  273. } else if (operationInput == "10") {
  274. transferID = IDTextField.getText();
  275. boolean result = operation.transfer(money, transferID);
  276. if (result) {
  277. messageArea.setText(currency_format.format(displayMessage) + " has been transferred...");
  278. } else {
  279. messageArea.setText(currency_format.format(displayMessage) + " is transferred unsuccessful...");
  280. }
  281. }
  282. inputMoney.setVisible(false);
  283. }
  284. }
  285. }
  286. private class Deposit implements ActionListener {
  287. @Override
  288. public void actionPerformed(ActionEvent e) {
  289. InputMoney inputMoney = new InputMoney();
  290. inputMoney.lunch("00");
  291. }
  292. }
  293. private class Withdraw implements ActionListener {
  294. @Override
  295. public void actionPerformed(ActionEvent e) {
  296. InputMoney inputMoney = new InputMoney();
  297. inputMoney.lunch("01");
  298. }
  299. }
  300. private class Transfer implements ActionListener {
  301. @Override
  302. public void actionPerformed(ActionEvent e) {
  303. InputMoney inputMoney = new InputMoney();
  304. inputMoney.lunch("10");
  305. }
  306. }
  307. }
  1. package client;
  2. import java.io.*;
  3. import java.net.Socket;
  4. public class ATMNet {
  5. private Socket socket;
  6. private BufferedReader bufferedReader;
  7. private PrintWriter printWriter;
  8. private static ATMNet atmNet;
  9. private ATMNet() {
  10. try {
  11. socket = new Socket("127.0.0.1", 4448);
  12. bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  13. printWriter = new PrintWriter(socket.getOutputStream(), true);
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. public BufferedReader getBufferedReader() {
  19. return bufferedReader;
  20. }
  21. public PrintWriter getPrintWriter() {
  22. return printWriter;
  23. }
  24. public static ATMNet getAtmNet() {
  25. if (atmNet == null) {
  26. atmNet = new ATMNet();
  27. }
  28. return atmNet;
  29. }
  30. }
  1. package client;
  2. import bank.ATMBank;
  3. import bank.Card;
  4. import bank.Customer;
  5. import server.CardIDGenerate;
  6. import server.MyObjectOutputStream;
  7. import java.io.*;
  8. import java.text.NumberFormat;
  9. import java.util.Iterator;
  10. import java.util.StringTokenizer;
  11. public class ClientManager {
  12. private ObjectOutputStream out;
  13. private File accountRecord;
  14. private ATMBank bank;
  15. public ClientManager() {
  16. accountRecord = new File("Client.ser");
  17. try {
  18. bank = ATMBank.getATMBank();
  19. if (!accountRecord.exists()) {
  20. accountRecord.createNewFile();
  21. }
  22. if (accountRecord.length() == 0) {
  23. out = new ObjectOutputStream(new FileOutputStream(accountRecord, true));
  24. } else {
  25. out = new MyObjectOutputStream(new FileOutputStream(accountRecord, true));
  26. }
  27. } catch (FileNotFoundException e) {
  28. e.printStackTrace();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. public String clientManage(String name, String password, String operation) {
  34. switch (operation) {
  35. case "0": {
  36. String id = "";
  37. try {
  38. Customer customer = new Customer(name, password);
  39. CardIDGenerate cardIDGenerate = CardIDGenerate.getCardIDGenerate();
  40. id = cardIDGenerate.generateID();
  41. Card card = new Card(id);
  42. customer.addCards(card);
  43. bank.addCustomer(customer);
  44. out.writeObject(customer);
  45. out.flush();
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. }
  49. return id;
  50. }
  51. case "1": {
  52. ObjectInputStream in = null;
  53. FileInputStream newFileInput = null;
  54. try {
  55. newFileInput = new FileInputStream(accountRecord);
  56. in = new ObjectInputStream(newFileInput);
  57. if (name == null || name.equals("")) {
  58. return "1-0";
  59. } else {
  60. if (password == null || password.equals("")) {
  61. return "2-0";
  62. } else {
  63. Customer curCustomer = (Customer) in.readObject();
  64. while (curCustomer != null) {
  65. Iterator<Card> iterator = curCustomer.cardIterator();
  66. while (iterator.hasNext()) {
  67. Card curCard = iterator.next();
  68. String message = curCard.getID() + "-" + curCard.getPassword();
  69. if (message != null && !message.equals("")) {
  70. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  71. String ID = stringTokenizer.nextToken();
  72. String pass = stringTokenizer.nextToken();
  73. if (ID.equals(name)) {
  74. if (pass.equals(password)) {
  75. float balance = curCard.getBalance();
  76. if (curCard.getNormal() == true) {
  77. return "3-" + balance;
  78. }
  79. else {
  80. return "0-0";
  81. }
  82. } else {
  83. return "4-0";
  84. }
  85. }
  86. }
  87. }
  88. curCustomer = (Customer) in.readObject();
  89. }
  90. }
  91. }
  92. } catch (IOException e) {
  93. } catch (ClassNotFoundException e) {
  94. e.printStackTrace();
  95. }
  96. break;
  97. }
  98. case "2": {
  99. Customer curCustomer = null;
  100. FileInputStream fileInputStream = null;
  101. try {
  102. Iterator<Customer> temp = bank.getCustomers();
  103. while (temp.hasNext()) {
  104. temp.next();
  105. temp.remove();
  106. }
  107. fileInputStream = new FileInputStream(accountRecord);
  108. ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
  109. curCustomer = (Customer) objectInputStream.readObject();
  110. while (curCustomer != null) {
  111. Iterator<Card> iterator = curCustomer.cardIterator();
  112. while (iterator.hasNext()) {
  113. Card curCard = iterator.next();
  114. String message = curCard.getID() + "-" + curCard.getPassword();
  115. if (message != null && !message.equals("")) {
  116. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  117. String ID = stringTokenizer.nextToken();
  118. if (ID.equals(name)) {
  119. curCard.setBalance(password, 1);
  120. bank.addCustomer(curCustomer);
  121. break;
  122. } else {
  123. bank.addCustomer(curCustomer);
  124. }
  125. }
  126. }
  127. curCustomer = (Customer) objectInputStream.readObject();
  128. }
  129. } catch (IOException e) {
  130. } catch (ClassNotFoundException e) {
  131. e.printStackTrace();
  132. } finally {
  133. try {
  134. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream((accountRecord)));
  135. Iterator<Customer> iteratorOfPrint = bank.getCustomers();
  136. while (iteratorOfPrint.hasNext()) {
  137. curCustomer = iteratorOfPrint.next();
  138. objectOutputStream.writeObject(curCustomer);
  139. }
  140. objectOutputStream.flush();
  141. } catch (IOException e) {
  142. e.printStackTrace();
  143. }
  144. }
  145. break;
  146. }
  147. case "3": {
  148. Customer curCustomer = null;
  149. FileInputStream fileInputStream = null;
  150. try {
  151. Iterator<Customer> temp = bank.getCustomers();
  152. while (temp.hasNext()) {
  153. temp.next();
  154. temp.remove();
  155. }
  156. fileInputStream = new FileInputStream(accountRecord);
  157. ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
  158. curCustomer = (Customer) objectInputStream.readObject();
  159. while (curCustomer != null) {
  160. Iterator<Card> iterator = curCustomer.cardIterator();
  161. while (iterator.hasNext()) {
  162. Card curCard = iterator.next();
  163. String message = curCard.getID() + "-" + curCard.getPassword();
  164. if (message != null && !message.equals("")) {
  165. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  166. String ID = stringTokenizer.nextToken();
  167. ObjectOutputStream objectOutputStream = null;
  168. if (ID.equals(name)) {
  169. curCard.setBalance(password, 2);
  170. bank.addCustomer(curCustomer);
  171. break;
  172. } else {
  173. bank.addCustomer(curCustomer);
  174. }
  175. }
  176. }
  177. curCustomer = (Customer) objectInputStream.readObject();
  178. }
  179. } catch (IOException e) {
  180. } catch (ClassNotFoundException e) {
  181. e.printStackTrace();
  182. } finally {
  183. try {
  184. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream((accountRecord)));
  185. Iterator<Customer> iteratorOfPrint = bank.getCustomers();
  186. while (iteratorOfPrint.hasNext()) {
  187. curCustomer = iteratorOfPrint.next();
  188. objectOutputStream.writeObject(curCustomer);
  189. }
  190. objectOutputStream.flush();
  191. } catch (IOException e) {
  192. e.printStackTrace();
  193. }
  194. }
  195. break;
  196. }
  197. case "4": {
  198. FileInputStream fileInputStream = null;
  199. Customer curCustomer = null;
  200. try {
  201. Iterator<Customer> temp = bank.getCustomers();
  202. while (temp.hasNext()) {
  203. temp.next();
  204. temp.remove();
  205. }
  206. fileInputStream = new FileInputStream(accountRecord);
  207. ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
  208. curCustomer = (Customer) objectInputStream.readObject();
  209. while (curCustomer != null) {
  210. Iterator<Card> iterator = curCustomer.cardIterator();
  211. while (iterator.hasNext()) {
  212. Card curCard = iterator.next();
  213. String message = curCard.getID() + "-" + curCard.getPassword();
  214. if (message != null && !message.equals("")) {
  215. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  216. String ID = stringTokenizer.nextToken();
  217. if (ID.equals(name)) {
  218. curCard.setPassword(password);
  219. bank.addCustomer(curCustomer);
  220. } else {
  221. bank.addCustomer(curCustomer);
  222. }
  223. }
  224. }
  225. curCustomer = (Customer) objectInputStream.readObject();
  226. }
  227. } catch (IOException e) {
  228. } catch (ClassNotFoundException e) {
  229. e.printStackTrace();
  230. } finally {
  231. ObjectOutputStream objectOutputStream = null;
  232. try {
  233. objectOutputStream = new ObjectOutputStream(new FileOutputStream((accountRecord)));
  234. Iterator<Customer> iteratorOfPrint = bank.getCustomers();
  235. while (iteratorOfPrint.hasNext()) {
  236. curCustomer = iteratorOfPrint.next();
  237. objectOutputStream.writeObject(curCustomer);
  238. }
  239. objectOutputStream.flush();
  240. } catch (IOException e) {
  241. e.printStackTrace();
  242. }
  243. }
  244. break;
  245. }
  246. case "5": {
  247. boolean from=false;
  248. boolean to =false;
  249. StringTokenizer stringTokenizer = new StringTokenizer(name, "-", false);
  250. String IDFrom = stringTokenizer.nextToken();
  251. String IDTo = stringTokenizer.nextToken();
  252. Customer curCustomer = null;
  253. FileInputStream fileInputStream = null;
  254. try {
  255. Iterator<Customer> temp = bank.getCustomers();
  256. while (temp.hasNext()) {
  257. temp.next();
  258. temp.remove();
  259. }
  260. fileInputStream = new FileInputStream(accountRecord);
  261. ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
  262. curCustomer = (Customer) objectInputStream.readObject();
  263. while (curCustomer != null) {
  264. Iterator<Card> iterator = curCustomer.cardIterator();
  265. while (iterator.hasNext()) {
  266. Card curCard = iterator.next();
  267. String message = curCard.getID();
  268. if (message != null && !message.equals("")) {
  269. if (message.equals(IDFrom)) {
  270. curCard.setBalance(password, 3);
  271. bank.addCustomer(curCustomer);
  272. from=true;
  273. } else if (message.equals(IDTo)) {
  274. if(curCard.getNormal()==false){
  275. return "0-0";
  276. }
  277. curCard.setBalance(password, 1);
  278. bank.addCustomer(curCustomer);
  279. to=true;
  280. } else {
  281. bank.addCustomer(curCustomer);
  282. }
  283. }
  284. }
  285. curCustomer = (Customer) objectInputStream.readObject();
  286. }
  287. } catch (IOException e) {
  288. } catch (ClassNotFoundException e) {
  289. e.printStackTrace();
  290. } finally {
  291. try {
  292. if(from==true && to==true) {
  293. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream((accountRecord)));
  294. Iterator<Customer> iteratorOfPrint = bank.getCustomers();
  295. while (iteratorOfPrint.hasNext()) {
  296. curCustomer = iteratorOfPrint.next();
  297. objectOutputStream.writeObject(curCustomer);
  298. }
  299. objectOutputStream.flush();
  300. return "0";
  301. }
  302. else {
  303. return "0-0";
  304. }
  305. } catch (IOException e) {
  306. e.printStackTrace();
  307. }
  308. }
  309. break;
  310. }
  311. case "6": {
  312. boolean sign = false;
  313. Customer curCustomer = null;
  314. FileInputStream fileInputStream = null;
  315. try {
  316. fileInputStream = new FileInputStream(accountRecord);
  317. ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
  318. curCustomer = (Customer) objectInputStream.readObject();
  319. while (curCustomer != null) {
  320. Iterator<Card> iterator = curCustomer.cardIterator();
  321. while (iterator.hasNext()) {
  322. Card curCard = iterator.next();
  323. String message = curCard.getID() + "-" + curCard.getPassword();
  324. if (message != null && !message.equals("")) {
  325. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  326. String ID = stringTokenizer.nextToken();
  327. float balance = curCard.getBalance();
  328. String telephone = curCustomer.getTelephone();
  329. String nameOfSearch = curCustomer.getName();
  330. String searchInformation = "1-" + nameOfSearch + "-" + telephone + "-" + balance;
  331. if (ID.equals(name)) {
  332. return searchInformation;
  333. }
  334. }
  335. }
  336. curCustomer = (Customer) objectInputStream.readObject();
  337. }
  338. } catch (IOException e) {
  339. return "error";
  340. } catch (ClassNotFoundException e) {
  341. e.printStackTrace();
  342. }
  343. break;
  344. }
  345. case "7": {
  346. // int index =0;
  347. boolean mark = false;
  348. boolean first = true;
  349. FileInputStream fileInputStream = null;
  350. Customer curCustomer = null;
  351. try {
  352. Iterator<Customer> temp = bank.getCustomers();
  353. while (temp.hasNext()) {
  354. temp.next();
  355. temp.remove();
  356. }
  357. fileInputStream = new FileInputStream(accountRecord);
  358. ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
  359. curCustomer = (Customer) objectInputStream.readObject();
  360. while (curCustomer != null) {
  361. Iterator<Card> iterator = curCustomer.cardIterator();
  362. while (iterator.hasNext()) {
  363. Card curCard = iterator.next();
  364. String message = curCard.getID() + "-" + curCard.getPassword();
  365. if (message != null && !message.equals("")) {
  366. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  367. String ID = stringTokenizer.nextToken();
  368. if (ID.equals(name)) {
  369. curCard.setNormal();
  370. bank.addCustomer(curCustomer);
  371. mark = true;
  372. break;
  373. } else {
  374. bank.addCustomer(curCustomer);
  375. }
  376. }
  377. }
  378. curCustomer = (Customer) objectInputStream.readObject();
  379. }
  380. } catch (IOException e) {
  381. } catch (ClassNotFoundException e) {
  382. e.printStackTrace();
  383. } finally {
  384. try {
  385. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream((accountRecord)));
  386. Iterator<Customer> iteratorOfPrint = bank.getCustomers();
  387. while (iteratorOfPrint.hasNext()) {
  388. curCustomer = iteratorOfPrint.next();
  389. objectOutputStream.writeObject(curCustomer);
  390. }
  391. objectOutputStream.flush();
  392. } catch (IOException e) {
  393. e.printStackTrace();
  394. }
  395. }
  396. break;
  397. }
  398. case "8": {
  399. ObjectInputStream in = null;
  400. FileInputStream newFileInput = null;
  401. try {
  402. Iterator<Customer> temp = bank.getCustomers();
  403. while (temp.hasNext()) {
  404. temp.next();
  405. temp.remove();
  406. }
  407. newFileInput = new FileInputStream(accountRecord);
  408. in = new ObjectInputStream(newFileInput);
  409. Customer curCustomer = (Customer) in.readObject();
  410. while (curCustomer != null) {
  411. Iterator<Card> iterator = curCustomer.cardIterator();
  412. while (iterator.hasNext()) {
  413. Card curCard = iterator.next();
  414. String message = curCard.getID();
  415. if (message.equals(password)) {
  416. float balance = curCard.getBalance();
  417. NumberFormat currency_format = NumberFormat.getCurrencyInstance();
  418. String cash = "" + currency_format.format(balance);
  419. in.close();
  420. return cash;
  421. }
  422. }
  423. curCustomer = (Customer) in.readObject();
  424. }
  425. } catch (IOException e) {
  426. } catch (ClassNotFoundException e) {
  427. e.printStackTrace();
  428. }
  429. break;
  430. }
  431. case "9": {
  432. ObjectInputStream in = null;
  433. FileInputStream newFileInput = null;
  434. Customer curCustomer = null;
  435. try {
  436. Iterator<Customer> temp = bank.getCustomers();
  437. while (temp.hasNext()) {
  438. temp.next();
  439. temp.remove();
  440. }
  441. newFileInput = new FileInputStream(accountRecord);
  442. in = new ObjectInputStream(newFileInput);
  443. curCustomer = (Customer) in.readObject();
  444. while (curCustomer != null) {
  445. Iterator<Card> iterator = curCustomer.cardIterator();
  446. while (iterator.hasNext()) {
  447. Card curCard = iterator.next();
  448. String message = curCard.getID() + "-" + curCard.getPassword();
  449. if (message != null && !message.equals("")) {
  450. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  451. String ID = stringTokenizer.nextToken();
  452. String pass = stringTokenizer.nextToken();
  453. if (ID.equals(name)) {
  454. if (curCard.getNormal() == true) {
  455. curCard.setPassword("123456");
  456. bank.addCustomer(curCustomer);
  457. }
  458. } else {
  459. bank.addCustomer(curCustomer);
  460. }
  461. }
  462. }
  463. curCustomer = (Customer) in.readObject();
  464. }
  465. } catch (IOException e) {
  466. } catch (ClassNotFoundException e) {
  467. e.printStackTrace();
  468. } finally {
  469. try {
  470. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream((accountRecord)));
  471. Iterator<Customer> iteratorOfPrint = bank.getCustomers();
  472. while (iteratorOfPrint.hasNext()) {
  473. curCustomer = iteratorOfPrint.next();
  474. objectOutputStream.writeObject(curCustomer);
  475. }
  476. objectOutputStream.flush();
  477. return "0";
  478. } catch (IOException e) {
  479. e.printStackTrace();
  480. }
  481. }
  482. break;
  483. }
  484. }
  485. return "0-0";
  486. }
  487. }
  1. package client;
  2. import bank.ATMBank;
  3. import bank.Card;
  4. import bank.Customer;
  5. import java.io.*;
  6. import java.text.NumberFormat;
  7. import java.util.Iterator;
  8. public class Operation {
  9. ATMBank bank;
  10. Customer customer;
  11. Card card;
  12. public Operation(Card card) {
  13. bank = ATMBank.getATMBank();
  14. Iterator<Customer> customers = bank.getCustomers();
  15. while (customers.hasNext()) {
  16. Customer curCustomer = customers.next();
  17. Iterator<Card> cardIterator = curCustomer.cardIterator();
  18. while (cardIterator.hasNext()) {
  19. Card curCard = cardIterator.next();
  20. if (card.equals(curCard)) {
  21. customer = curCustomer;
  22. }
  23. }
  24. }
  25. this.card = card;
  26. }
  27. public void deposit(String money) {
  28. card.setBalance(money, 1);
  29. ATMNet atmNet = ATMNet.getAtmNet();
  30. PrintWriter printWriter = atmNet.getPrintWriter();
  31. printWriter.println("1-2-" + card.getCustomer(card).getName() + "-" + card.getID() + "-" + money);
  32. }
  33. public boolean withdraw(String money) {
  34. float cash = card.getBalance();
  35. float balance = Float.parseFloat(money);
  36. if (cash > balance) {
  37. card.setBalance(money, 2);
  38. ATMNet atmNet = ATMNet.getAtmNet();
  39. PrintWriter printWriter = atmNet.getPrintWriter();
  40. printWriter.println("1-3-" + card.getCustomer(card).getName() + "-" + card.getID() + "-" + money);
  41. return true;
  42. }
  43. return false;
  44. }
  45. public boolean transfer(String money, String id) {
  46. float cash = card.getBalance();
  47. float balance = Float.parseFloat(money);
  48. if (cash > balance) {
  49. card.setBalance(money, 3);
  50. ATMNet atmNet = ATMNet.getAtmNet();
  51. PrintWriter printWriter = atmNet.getPrintWriter();
  52. printWriter.println("1-5-" + id + "-" + card.getID() + "-" + money);
  53. BufferedReader bufferedReader = atmNet.getBufferedReader();
  54. String result = "";
  55. try {
  56. result = bufferedReader.readLine();
  57. } catch (IOException e) {
  58. e.printStackTrace();
  59. }
  60. if (result.equals("0")) {
  61. return true;
  62. }
  63. }
  64. return false;
  65. }
  66. public String display() {
  67. String ID = card.getID();
  68. String balance = "";
  69. ATMNet atMnet = ATMNet.getAtmNet();
  70. PrintWriter printWriter = atMnet.getPrintWriter();
  71. printWriter.println("1-8-00000000-123456-" + ID);
  72. BufferedReader bufferedReader = atMnet.getBufferedReader();
  73. try {
  74. balance = bufferedReader.readLine();
  75. } catch (IOException e) {
  76. e.printStackTrace();
  77. }
  78. return balance;
  79. }
  80. }
  1. package server;
  2. import admin.AdminAccountManage;
  3. import bank.ATMBank;
  4. import client.ClientManager;
  5. import java.io.*;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8. import java.util.ArrayList;
  9. import java.util.Iterator;
  10. import java.util.StringTokenizer;
  11. public class ServerNet {
  12. private BufferedReader bufferedReader;
  13. private PrintWriter printWriter;
  14. private BufferedReader inOfClient;
  15. private PrintWriter outOfClient;
  16. private PrintWriter outOfAdmin;
  17. private ServerSocket serverSocketOfAdmin;
  18. private ServerSocket serverSocketOfClient;
  19. private Socket socketOfAdmin;
  20. private Socket socketOfClient;
  21. private ATMBank bank;
  22. private AdminAccountManage adminAccountManage;
  23. private ClientManager clientManager;
  24. private BufferedReader aBuffered;
  25. private PrintWriter aPrinter;
  26. private static ArrayList<String> onlineClient;
  27. public ServerNet(Socket socket) {
  28. try {
  29. // inOfClient = new BufferedReader(new InputStreamReader(socketOfClient.getInputStream()));
  30. adminAccountManage = new AdminAccountManage();
  31. clientManager = new ClientManager();
  32. outOfAdmin = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
  33. onlineClient =OnlineClient.getOnlineClient();
  34. bank = ATMBank.getATMBank();
  35. } catch (FileNotFoundException e) {
  36. e.printStackTrace();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. public void adminOperation(StringTokenizer stringTokenizer) {
  42. String condition = null;
  43. String account = null;
  44. String password = null;
  45. condition = stringTokenizer.nextToken();
  46. account = stringTokenizer.nextToken();
  47. password = stringTokenizer.nextToken();
  48. switch (condition) {
  49. case "0": {
  50. String result = "" + adminAccountManage.accountManage(account, password, "0");
  51. break;
  52. }
  53. case "1": {
  54. String result = "" + adminAccountManage.accountManage(account, password, "1");
  55. outOfAdmin.println(result);
  56. break;
  57. }
  58. }
  59. }
  60. public void clientOperation(StringTokenizer stringTokenizer) {
  61. String operation = "";
  62. String name = "";
  63. String ID = "";
  64. String password = "";
  65. operation = stringTokenizer.nextToken();
  66. name = stringTokenizer.nextToken();
  67. ID = stringTokenizer.nextToken();
  68. password = stringTokenizer.nextToken();
  69. switch (operation) {
  70. case "0": {
  71. String result = clientManager.clientManage(name, password, "0");
  72. outOfAdmin.println(result);
  73. break;
  74. }
  75. case "1": {
  76. // Customer customer = new Customer(name,ID);
  77. String result = "" + clientManager.clientManage(ID, password, "1");
  78. boolean online = false;
  79. if (!result.equals("1-0") && !result.equals("2-0") && !result.equals("4-0") && !result.equals("0-0")) {
  80. Iterator<String> iterator = onlineClient.iterator();
  81. while (iterator.hasNext()) {
  82. String curOnlineClient = iterator.next();
  83. if (curOnlineClient.equals(ID)) {
  84. outOfAdmin.println("5-0");
  85. online = true;
  86. }
  87. }
  88. if (online == false) {
  89. onlineClient.add(ID);
  90. outOfAdmin.println(result);
  91. }
  92. }
  93. else {
  94. outOfAdmin.println(result);
  95. }
  96. break;
  97. }
  98. case "2": {
  99. clientManager.clientManage(ID, password, "2");
  100. break;
  101. }
  102. case "3": {
  103. clientManager.clientManage(ID, password, "3");
  104. break;
  105. }
  106. case "4": {
  107. String result = "" + clientManager.clientManage(ID, password, "4");
  108. outOfAdmin.println(result);
  109. break;
  110. }
  111. case "5": {
  112. String result = clientManager.clientManage(ID + "-" + name, password, "5");
  113. outOfAdmin.println(result);
  114. break;
  115. }
  116. case "6": {
  117. String informationOfAdmin = clientManager.clientManage(ID, password, "6");
  118. outOfAdmin.println(informationOfAdmin);
  119. break;
  120. }
  121. case "7": {
  122. clientManager.clientManage(ID, password, "7");
  123. break;
  124. }
  125. case "8": {
  126. String result = clientManager.clientManage(ID, password, "8");
  127. outOfAdmin.println(result);
  128. break;
  129. }
  130. case "9": {
  131. String result = clientManager.clientManage(name, password, "9");
  132. outOfAdmin.println(result);
  133. break;
  134. }
  135. }
  136. }
  137. /* public static void main(String[] args) {
  138. ServerSocket serverSocketOfAdmin = null;
  139. Socket socketOfAdmin = null;
  140. BufferedReader bufferedReader = null;
  141. String message = null;
  142. boolean firstRead = false;
  143. // boolean content = false;
  144. try {
  145. serverSocketOfAdmin = new ServerSocket(4448);
  146. socketOfAdmin = serverSocketOfAdmin.accept();
  147. bufferedReader = new BufferedReader(new InputStreamReader(socketOfAdmin.getInputStream()));
  148. } catch (IOException e) {
  149. e.printStackTrace();
  150. }
  151. ServerNet serverNet = new ServerNet(socketOfAdmin);
  152. while (true) {
  153. try {
  154. message = bufferedReader.readLine();
  155. } catch (IOException e) {
  156. }
  157. if (!message.equals("") && message != null) {
  158. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  159. String side = stringTokenizer.nextToken();
  160. if (side.equals("0")) {
  161. serverNet.adminOperation(stringTokenizer);
  162. } else {
  163. serverNet.clientOperation(stringTokenizer);
  164. }
  165. }
  166. }
  167. }*/
  168. }
  1. package server;
  2. import java.io.IOException;
  3. import java.io.ObjectOutputStream;
  4. import java.io.OutputStream;
  5. public class MyObjectOutputStream extends ObjectOutputStream {
  6. protected MyObjectOutputStream() throws IOException, SecurityException {
  7. super();
  8. }
  9. @Override
  10. protected void writeStreamHeader() throws IOException {
  11. }
  12. public MyObjectOutputStream(OutputStream o) throws IOException {
  13. super(o);
  14. }
  15. }
  1. package server;
  2. import java.io.*;
  3. public class CardIDGenerate {
  4. private static String cardID;
  5. private static CardIDGenerate cardIDGenerate;
  6. private File file;
  7. private CardIDGenerate() {
  8. file = new File("ID.txt");
  9. String id = "";
  10. try {
  11. BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
  12. id = bufferedReader.readLine();
  13. } catch (FileNotFoundException e) {
  14. e.printStackTrace();
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. cardID = id;
  19. }
  20. public static CardIDGenerate getCardIDGenerate() {
  21. if (cardIDGenerate == null) {
  22. cardIDGenerate = new CardIDGenerate();
  23. }
  24. return cardIDGenerate;
  25. }
  26. public String generateID() {
  27. String newID;
  28. int ID = Integer.parseInt(cardID);
  29. newID = ID + 1 + "";
  30. try {
  31. PrintWriter printWriter = new PrintWriter(new FileWriter(file), true);
  32. printWriter.println(newID);
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. return newID;
  37. }
  38. }
  1. package server;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. public class OnlineClient {
  5. private static ArrayList<String> onlineClient;
  6. private static OnlineClient onlineClientInstance;
  7. private OnlineClient(){
  8. onlineClient = new ArrayList<String>();
  9. }
  10. public static ArrayList<String> getOnlineClient(){
  11. if(onlineClientInstance==null){
  12. onlineClientInstance = new OnlineClient();
  13. }
  14. return onlineClient;
  15. }
  16. }
  1. package server;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.net.*;
  6. import java.util.StringTokenizer;
  7. public class ServerThread extends Thread {
  8. Socket socketOfAdmin = null;
  9. BufferedReader bufferedReader = null;
  10. String message = null;
  11. public ServerThread(Socket socket) {
  12. try {
  13. socketOfAdmin = socket;
  14. bufferedReader = new BufferedReader(new InputStreamReader(socketOfAdmin.getInputStream()));
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. @Override
  20. public void run() {
  21. ServerNet serverNet = new ServerNet(socketOfAdmin);
  22. while (true) {
  23. try {
  24. message = bufferedReader.readLine();
  25. } catch (IOException e) {
  26. }
  27. if (!message.equals("") && message != null) {
  28. StringTokenizer stringTokenizer = new StringTokenizer(message, "-", false);
  29. String side = stringTokenizer.nextToken();
  30. if (side.equals("0")) {
  31. serverNet.adminOperation(stringTokenizer);
  32. } else {
  33. serverNet.clientOperation(stringTokenizer);
  34. }
  35. }
  36. }
  37. }
  38. }
  1. package server;
  2. import java.io.IOException;
  3. import java.net.ServerSocket;
  4. public class TestServer {
  5. public static void main(String[] args) {
  6. ServerSocket serverSocket = null;
  7. boolean listening = true;
  8. try {
  9. serverSocket = new ServerSocket(4448);
  10. } catch (IOException e) {
  11. System.exit(-1);
  12. }
  13. while (listening) {
  14. try {
  15. ServerThread serverThread = new ServerThread(serverSocket.accept());
  16. serverThread.start();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注