学习《core java》记录 -- 第四章 Objects and Classes

来源:互联网 发布:淘宝swot分析矩阵图 编辑:程序博客网 时间:2024/05/21 05:21

学习《core java》记录 – 第四章 Objects and Classes

摘自《Java核心技术》(第8版)(评注版) Cay S. Horstmann, Gary Cornell, 公飞

Introduction To Object-Oriented Programming

Classes

The data in an object are called its instance fields, and the procedures that operate the data are called its methods. A specific object that is an instance of a class will have specific values for its instance fields.

Objects

The state of an object does not completely describe it, because each object has a distinct identity. Notice that the individual objects that are instances of a class always differ in their identity and usually differ in their state.

Identifying Classes

the “noun and verb” rule

Relationships between Classes

  • Dependence (“uses-a”)
    a class depends on another class if its methods use or manipulate objects of that class. Try to minimize the number of classes that depend on each other. (minimize the coupling between classes)
  • Aggregation (“has-a”)
  • Inheritance (“is-a”)

UML
Violet UML Editor (tool for drawing UML diagram)

Using Predefined Classes

Objects and Object Variables

constructor
A constructor is a special method whose purpose is to construct and initialize objects.
An object variable doesn’t actually contain an object. It only refers to an object. In Java, the value of any object variable is a reference to an object that is stored else-where. The return value of the new operator is also a reference.
You can explicity set an object variable to null to indicate that it currently refers to no object.
If you apply a method to a variable that holds null, then a runtime error occurs.
Variables are not automatically initialized to null. You must initialize them, either by calling new or by setting them to null.

Date deadline = null;String s = deadline.toString(); // runtime error!!...if (deadline != null)    System.out.println(deadline);

All Java objects live on the heap. When an object contains another variable, that variable still contains just a pointer to yet another heap object.
In Java, you must use the clone method to get a complete copy of an object.
Java中的对象变量实际上类似于C++中的指针。Java的对象变量实质上是指向对象的对象指针,在对象变量中保存的实际上是对象在内存中存储的地址。在两个对象变量之间使用”==”运算符时,比较的是两个变量指向的是否是内存中的同一个对象,并不是比较两个对象的值是否相等。要比较两个对象是否相等,需要使用equals方法。

The GregorianCalendar Class of the Java Library

Mutator and Accessor Methods

Methods that change instance fields are called mutator methods, and those that only access instance fields without modifying them are called accessor method.
A common convention is to prefix accessor methods with the prefix get and mutator methods with the prefix set.
If you want to see the program output in a different local, add a line such as the following as the first line of the main method:
Locale.setDefault(Local.ITALY);

Defining Your Own Classes

An Emplyee Class

The name of the source file must match the name of the public class. You can have only one public class in a source file, but you can have any number of nonpublic classes.
一个.java源文件中可以有多个Java类,但是其中只能有一个public类,并且如果一个.java的文件中有public类,则这个.java文件名必须和这个public类一致,即pulic类名+.java。如果一个.java文件中没有pubic类,只是默认的类,那么对java文件名没有要求,甚至可以不跟其中任何类名一致。由.java编译生成的.class类文件与类是一一对应的,一个类生成一个.class文件,且文件名与类名一致,即类名+.class,如果是内部类,则为外部类名+S+内部类名+.class(例如,在类A中定义的内部类B,编译后的.class文件名为A$B.class。)

Use of Multiple Source Files

目前Java开发中和make具有类似作用的常用工具是Ant。

Dissecting the Employee Class

The keyword public means that any method in any class can call the method.
The keyword private makes sure that the only methods that can access these instance fields are the methods of the Employee calss itself. No outside method can read or write to these fields.

  • A constructor has the same name as the class.
  • A class can have more than one constructor.
  • A constructor can take 0, 1 or more parameters.
  • A constructor has no return value.
  • A constructor is always called with the new operator.

访问修饰符

  • private,其他类都不可见
  • protected,子类中(不论是否为同一个包)及同一个包中所有的类可见
  • public,所有的类都可见
  • 默认的类型(不加访问修饰符),同一个包中的类可见

Implicit and Explicit Paramenters

In every method, the object before the method name is the implicit paramenter, the keyword this refers to the implict paramenter.
the explicit paramenters are explicitly listed in the method declaration.
In Java, all methods are defined inside the class itself.
Be careful not to write accessor methods that return references to mutable objects. If you need to return a reference to a mutable object, you should clone it first. A clone is an exact copy of an object that is stored in a new location.

Class-Based Access Privileges

a method can access the private data of all objects of its class.

Private Methods

Final Instance Fields

You can define an instance field as final. Such a field must be initialized when the object is constructed. That is , it must be guaranteed that the field value has been set after the end of every constructor.
The final modifier is particularly useful for fields whose type is primitive or an immutable class. A class is immutable if none of its methods ever mutate its objects, eg, the String class.
For mutalbe classes, the final modifier merely means that the object references stored in the variable doesn’t get changed after the object is constructed. That does not mean that the object is constant. Any mutator method can change the object to which the constant-object-variable refers.

Static Fields and Methods

Static Fields

If you define a field as static, then there is only one such field per class. Even if there are no objects, the static field is present. It belongs to the class, not to any individual object.
static变量只初始化一次!!

class Employee{    ...    private int id;    private static int nextId = 1;  // 在定义类类型是初始化static变量}

Static Constants

eg: System.out、Math.PI
static final
If you look at the System class, you will notice a method setOut that lets you set System.out to a different stream. The setOut method is a native method, not implemented in the Java programming language. Native methods can bypass the access control mechanisms of the Java language.

Static Methods

Static methods are methods that do not operate on objects. You can think of static methods as methods that don’t have a this paramenter (implicit paramenter). Static methods can access the static fields in the class, they cannot access instance fields.
You use static methods in two situations:

  • When a method doesn’t need to access the object state because all needed paramenters are supplied as explicit paramenters (eg: Math.pow())
  • When a method only needs to access static fields of the class.

Factory Methods

(inheritance)

NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance();NumberFormat percentFormatter = NumberFormat.getPercentInstance();double x = 0.1;System.out.println(currencyFormatter.format(x)); // $0.10System.out.println(percentFormatter.format(x)); // 10%

The main Method

Every class can have a main method. That is a handy trick for unit testing of classes.
业界有个较流行的开放源代码Java单元测试工具JUnit。

Method Parameters

The term call by value means that the method gets just the value that the caller provides.
The term call by reference means that the method gets the location of the variable that the caller provides.
These “call by …” terms are standard computer science terminology that describe the behavior of method parameters in various programming languages.
The Java Programming language always uses call by value.

Object Construction

Overloading

Overloading occurs if several methods have the same name but different parameters. The compiler must sort out which method to call. It picks the correct method by matching the parameter types in the headers of the various methods with the types of the values used in the specific method call. A compile-time error occurs if the compiler cannot match the parameters or if more than one match is possible. This process is called overloading resolution.
To completely describe a method, you need to specify the name of the method together with its parameter types. This is called the signature of the method. The return type is not part of the method signature. That is, you cannot have two methods with the same names and parameter types but different return types.

Default Field Initialization

If you don’t set a field explicitly in a constructor, it is automatically set to a default value: numbers to 0, boolean values to false, and object references to null.

Default Constructors

A default constructor is a constructor with no parameters.
If you write a class with no constructors whatsoever, then a default constructor is provided for you . This default constructor sets all the instance fields to their default values. So, all numeric data contained in the instance fields would be 0, all boolean values would be false, and all object variables would be set to null.
If a class supplies at least one constructor but does not supply a default constructor, it is illegal to construct objects without construction parameters.
Please keep in mind that you get a free default constructor only when your class has no other constructors. If you write your class with even a single constructor of your own and you want the users of your class to have the ability to create an instance by a call to
new ClassName()
then you must provide a default constructor (with no parameters).

Explicit Field Initialization

You can assign a value to any field in the class definition.

class Employee{    ...    private String name = "";}

This assignment is carried out before the constructor executes. This syntax is particularly useful if all constructors of a class need to set a particular instance field to the same value.
The initialization value doesn’t have to be a constant value. A field can be initialized with a method call.

class Employee{    ...    static int assignId()    {        int r = nextId;        nextId++;        return r;    }    ...    private int id = assignId();    private static int nextId = 1;}

Parameter Names

the parameter variables shadow instance fields with the same name, you can still access the instance field by using this.(the implicit parameter).

Calling Another Constructor

If a constructor has the form this(…), then the constructor calls another constructor of the same class.

public Employee(double s) {    // calls Employee(String, double)    this("Employee #" + nextId, s);    nextId++;}

Initialization Blocks

Class declarations can contain arbitrary blocks of code. These blocks are executed whenever an abject of that class is constructed.
The initialization block runs first, and then the body of the constructor is executed.

class Employee{    public Employee(String n, double s)    {        name = n;        salary = s;    }    public Employee()    {        name = "";        salary = 0;    }    ...    private static int nextId;    private int id;    private String name;    private double salary;    ...    // object initialization block    {        id = nextId;        nextId++;    }}

You are suggested initializing blocks after the field definitions.
Here is what happens indetail when a constructor is called:

  1. All data fields are initialized to their default value (0, false, or null)
  2. All field initializers and initialization blocks are executed, in the order in which they occur in the class declaration.
  3. If the first line of the constructor calls a second constructor, then the body of the second constructor is executed.
  4. The body of the constructor is executed.

You initialize a static field either by supplying an initial value or by using a static initialization block. If the static fields of your class require complex initialization code, use a static initialization block. Place the code inside a block and tag it with the keyword static.

// static initialization blockstatic{    Random generator = new Random();    nextId = generator.nextInt(1000);}

Static initialization occurs when the class is first loaded. Static fields are 0, false, or null unless you explicitly set them to another value. All static field initializers and static initialization blocks are executed in the order in which they occor in the class declaration.
??? You can write a “Hello, world” program in Java without ever writing a main method.
Java 8不可行,报错误在类中找不到main方法,要定义main方法,否则JavaFX应用程序类必须扩展javafx.application.Application ????

public class Hello{    static     {        System.out.println("Hello, World");        System.exit(0);    }}

Object Destruction and the finalize Method

You can add a finalize method to any class. The finalize method will be called before the garbage collector sweeps away the object. In paticutlar, do not rely on the finalize method for recycling any resources that are in short supply – you simply cannot know when this method will be called.

Runtime.addShutdownHook()

If a resource needs to be closed as soon as you have finished using it, you need to manage it manually. Supply a method such as dispose or close that you call to clean up what needs cleaning. Just as important, if a class you use has such a method, you need to call it when you are done with the object.

Packages

Java allows you to group classes in a collection called a package.

Class Importation

A class can use all classes from its own package and all public classes from other packages.
java.util.Date today = new java.util.Date();

place import statements at the top of your source files
import java.util.*;

import a specific class inside a package
import java.util.Date;

Note that you can only use the * notation to import a single package. You cannot use “import java.*” or “import java.*.*” to import all packages with the java prefix.
使用*只能表示使用本层次的所有类,不包括子层次下的类。如果有两个包com.a.b和com.a.b.c,那么”import com.a.b.*”导入的类将不包括com.a.b.c下面的类。如果需要使用com.a.b.c下面的类,需要import com.a.b.c.*。
When you have a name conflict, if you only want to use one of them, you can adding a specific import statement .

import java.util.*;import java.sql.*;import java.util.Date;

如果你需要使用不同package中命名重复的多个类,你需要使用带完整的包名的类名。
If you need more than one of the classes that with the conflicted name, you need to use the full package name with every class name.

java.util.Date deadline = new java.util.Date();java.sql.Date today = new java.sql.Date();

Locating classes in packages is an activity of the compiler. The bytecodes in class files always use full package names to refer to other classes.

Static Imports

the import statement permits the importation of static methods and fields, not just classes.

import static java.lang.System.*;out.println("System.out");exit(0);

You can also import a specific method or field.
import static java.lang.System.out;

Addition of a Class into a Package

To place classes inside a package, you must put the name of the package at the top of your source file, before the code that defines the classes in the package.
If you don’t put a package statement in the source file, then the classes in that source file belong to the default package. The default package has no package name.

package com.horstmann.corejava;public class Employee{}

place source files into a subdirectory that matches the full package name. The compiler places the class files into the same directory structure.

compile and run classes from the basic directory
文件存放路径:
“basic-directory/com/horstmann/corejava/Employee.java”
“basic-directory/com/horstmann/corejava/Employee.class”
“basic-directory/com/mycompany/PayrollApp.java”
“basic-directory/com/mycompany/PayrollApp.class”
在根目录(包含com目录的目录)编译和解释类:
javac com/mycompany/PayrollApp.java
java com.mycompany.PayrollApp
Note that the compiler operates on files (with file seperators and extension .java), whereas the Java interpreter loads a class (with dot separators).

Package Scope

If you don’t specify either public or private, the feature (that is, the class, method, variable) can be accessed by all methods in the same package.
package sealing

The Class Path

To share classes among programs, you need to do the following:

  1. Place your class files inside a directory, for example, /home/user/classdir. Note that this directory is the base directory for the package tree. If you add the class com.horstmann.corejava.Employee, then the Employee.class file must be located in the subdirectory /home/user/classdir/com/horstmann/corejava.
  2. Place any JAR files inside a directory, for example, /home/user/archives.
  3. Set the class path. The class path is the collection of all locations that can contain class files.
    On Unix, the elements on the class path are separated by colons:
    /home/user/classdir:.:/home/user/archives/archive.jar
    On Windows, the elements on the class path are separated by semicolons:
    c:\classdir;.;c:\archives\archive.jar

Starting with Java SE 6, you can specify a wildcard for a JAR file directory, like this:
/home/user/classdir:.:/home/user/archives/'*'
or
c:\classdir;.;c:\archives\*
In Unix, the * must be escaped to prevent shell expasion. All JAR files (but not .class files) in the archives directory are included in this class path.
The runtime library files (rt.jar and the other JAR files in the jre/lib and jre/lib/ext directories) are always searched for classes; you don’t need to include them explicitly in the class path.
The javac compiler always looks for files in the current directory, but the java virtual machine launcher looks into the current directory only if the “.” directory is on the class path. If you have no class path set, this is not a problem – the default class path consists of the “.” directory. But if you have set the class path and forget to include the “.” directory, your programs will compile without error, but they won’t run.
The class path lists all directories and archive files that are starting points for locating classes. Consider:
/home/user/classdir:.:/home/user/archives/archive.jar
Suppose the virtual machine searches for the class file of the com.horstmann.corejava.Employee class. It first looks in the system class file that are stored in archives in the jre/lib and jre/lib/ext directories. It won’t find the class file there, so it turns to the class path. It then looks for the following files:
/home/user/classdir/com/horstmann/corejava/Employee.class
com/horstmann/corejava/Employee.class starting from the current directory
com/horstmann/corejava/Employee.class inside /home/user/archives/archive.jar
如果CLASSPATH中有同包同名的类,虚拟机会使用发现的第一个。一定要确保执行的是正确的类,尤其是在CLASSPATH中设置了很多内容时,可能会因为执行了错误的类,而产生莫名其妙的问题。
The compiler has a harder time locating files than does the virtual machine. If you refer to a class without specifying its package, the compiler first needs to find out the package that contains the class. It consults all import directives as possible sources for the class.
For example, suppose the source file contains directives

import java.util.*;import com.horstmann.corejava.*;

and the source code refers to a class Employee. The compiler then tried to find java.lang.Employee (because the java.lang package is always imported by default), java.util.Employee, com.horstmann.corejava.Employee, and Employee in the current package. It searches for each of these classes in all of the locations of the class path. It is a compile-time error if more than one class is found. (Because classes must be unique, the order of the import statements doesn’t matter.)

Setting the Class Path

It is best to specify the class path with the -classpath (-cp) option:
java -classpath /home/user/classdir:.:/home/user/archives/archive.jar MyProg.java
or
java -classpath c:\classdir;.;c:\archives\archive.jar MyProg.java
It is a good idea to place such a long command line into a shell script or a batch file.
An alternate approach is the CLASSPATH environment variable.
With the Bourne Again shell (bash), use the command
export CLASSPATH=/home/user/classdir:.:/home/user/archives/archive.jar
With the C shell, use the command
setenv CLASSPATH /home/user/classdir:.:/home/user/archives/archive.jar
With the Windows shell, use
set CLASSPATH=c:\classdir;.;c:\archives\archive.jar
It is a bad idea to set the CLASSPATH environment variable permanently.

Documentation Comments

javadoc

the special delimiter /**

Comment Insertion

The javadoc utility extracts information for the following items:

  • Packages
  • Public classes and interfaces
  • Public and protected methods
  • Public and protected fields

You can (and should) supply a comment for each of these features. Each comment is placed immediately above the feature it describes. A comment starts with a /** and ends with a */. Each /** ……. */ documentation comment contains free-form text followed by tags. A tag starts with an @, such as @author or @param.
看不懂。。。The first sentence of the free-form text should be a summary statement. The javadoc ultility automatically generates summary pages that extract these sentences.
In the free-form text, you can use HTML modifiers such as <em>…</em> for emphasis, <code>…</code> for a monospaced “typewriter” font, <strong>…</strong> for strong emphasis, and even <img…> to include an image. You should , however, stay away from headings <h1> or rules <hr> because they can interfere with the formatting of the document.
If your comments contain links to other files such as images (for example, diagrams or images of user interface components), place those files into a subdirectory of the directory containing the source file named doc-files. The javadoc utility will copy the doc-files directories and their contents from the source directory to the documentation directory. You need to use the doc-files directory in your link, such as <img src=”doc-files/uml.png” alt=”UML diagram”/>.

Class Comments

A class comment must be placed after any import statements, directly before the class definition.

/** * A <code>Card</code> object represents a playing card, * such as "Queen of Hearts".... */

There is no need to add an * in front of every line.

Method Comments

Each method comment must immediately precede the method that it describes.

Tags:

  • @param variable description
    This tag adds an entry to the “parameters” section of the current method. The description can span multiple lines and can sue HTML tags. All @param tags for one method must be kept together.
  • @return description
    This tag adds a “return” section to the current method. The description can span multiple lines and can sue HTML tags.
  • @throw class description
    This tag adds a note that this method may throw an exception.
/** * Raise the salary of an employee. * @param byPercent the percentage by which to raise the salary * @return the amount of the raise */public double raiseSalary(double byPercent){ ... }

Field Comments

You only need to document public fields – generally that means static constants.

/** * The "Hearts" card suit */public static final int HEARTS = 1;

General Comments

The following tags can be used in class documentation comments:

  • @author name
    This tag makes an “author” entry. You can have multiple @author tags, one for each author.
  • @version text
    This tag makes a “version” entry. The text can be any description of the current version.

The following tags can be used in all documentation comments:

  • @since text
    This tag makes a “since” entry. The text can be any description of the version that introduced this feature. For example, @since version 1.7.1
  • @deprecated text
    This tag adds a comment that the class, method, or variable should no longer be used. The text should suggest a replacement. For example:
    @deprecated Use <code>setVisible(true)</code> instead

You can use hyperlinks to other relevant parts of the javadoc documentation, or to external documents, with the @see and @link tags.

  • @see reference
    This tag adds a hyperlink in the “see also” section. It can be used with both classes and methods. Here, reference can be one of the following:
    package.class#feature label
    <a href="...">label</a> "text"

    @see com.horstmann.corejava.Employee#raiseSalary(double)

    makes a link to the raiseSalary(double) method in the com.horstmann.corejava.Employee class. You can omit the name of the package or both the package and class name. Then, the feature will be located in the current package or class.

    @see <a href="www.horstmann.com/corejava.html">The Core Java home page</a>

    In each of these cases, you can specify an optional label that will appear as the link anchor. If you omit the label, then the user will see the target code name or URL as the anchor.
    If the @see tag is followed by a ” character, then the text is displayed in the “see also” section. eg:
    @see "Core Java 2 volume 2"
    You can add multiple @see tags for one feature, but you must keep them all together.

  • You can place hyperlinks to other classes or methods anywhere in any of your documentation comments. You insert a special tag of the form
    {@link package.class#feature label}
    anywhere in a comment

Package and Overview Comments

To generate package comments, you need to add a separate file in each package directory. You have 2 choices:

  1. Supply an HTML file named package.html. All text between the tags <body>…</body> is extracted.
  2. Supply a Java file named package-info.java. The file must contain an initial Javadoc comment, delimited with /*and/, followed by a package statement. It should contain no further code or comments.

You can also supply an overview comment for all source files. Place it in a file called overview.html, located in the parent directory that contains all the source files. All text between the tags <body>…</body> is extracted. This comment is displayed when the user selects “Overview” from the navigation bar.

Comment Extraction

Steps:

  1. Change to the directory that contains the source files you want to document. If you have nested packages to document, such as com.horstmann.corejava, you must be working in the directory that contains the subdirectory com. (This is the directory that contains the overview.html file if you supplied one.)
  2. Run the command
    javadoc -d docDirectory nameOfPackage
    for a single package. Or run
    javadoc -d docDirectory nameOfPackage1 nameOfPackage2 ...
    to document multiple packages. If your files are in the default package, then instead run
    javadoc -d docDirectory *.java
    If you omit the -d docDirectory option, then the HTML files are extracted to the current directory. That can get messy.
    use the -author and -version options to include the @author and @version tags in the documentation. (By default, they are omitted.)
    ???? use the -link ooption to include hyperlinkds to standard classes. For example,
    javadoc -link http://java.sun.com/javase/6/docs/api *.java
    all standard library classes are automatically linked to the documentation on the Sun web site. ????
    use the -linksource option to convert each source file to HTML, and each class and method name turns into a hyperlink to the source.
    javadoc使用参考
    生成其他格式的文档的工具
    doclet

Classes Design Hints

  1. Always keep data private.
  2. Always initialize data.
    Java won’t initialize local variables for you, but it will initialize instance fields of objects.
  3. Don’t use too many basic types in a class.
  4. Not all fields need individual field accessors and mutators.
  5. Use a standard form for class defination.
  6. Break up classes that have too many responsibilites.
  7. Make the names of your classes and methods reflect their responsibilities.
0 0