CoreJava - Chapter 4: Objects and Classes

Introduction to Object-Oritented Programming

  • Introduction
    • Each object has a specific functionality, exposed to its users, and a hidden implementation
    • Basically, as long as an object satisfies your specifications, you don't care how the functionality is implemented
    • OOP vs Procedural Programming
      • for procedural programming, Algorithms + Data Structures = Program. Algorithms come first
      • for OOP, we put the data first, then looks at the algorihtms to operate on the data
    • OOP is more appropriate for larger programs
  • Classes
    • A class is the template or blue print from which objects are made
    • When you construct an object from a class, you are said to have crated an instance of the class
    • Encapsulation (information hiding)
      • combining data and behavior in one package and hiding implementation details from the users of the object
      • instance fields
      • methods
      • the key is to have methods never directly access instance fields in a class other than their own. Programs should interact with object data only through the object's methods
    • Cosmic super class - Object
    • Inheritance
  • Objects
    • Three key characteristics
      • behavior: what can you do with this object, or what methos can you apply to it?
      • state: how does the object react when you invoke those methods? 
      • identity: how is the object distinguisehd from others that may have the same behavior and state?
        • individual objects that are instances of a class always differ in their identity and usually differ in their state
  • Identifying classes
  • Relationship between classes
    • Dependence ("uses-a")
      • Try to minimize the number of classes that depend on each other - minimize the coupling between clsses
    • Aggregation("has-a")
    • Inheritance("is-a")
    • UML notations
      • CoreJava - Chapter 4: Objects and Classes_第1张图片

        A -> B: A is a child class of B

Using Predefined Classes

  • Objects and Object Variables
    • Constructors 
      • new keyword
    • Object vs Object variables
      • Date deadline

        defines an object variable, deadline, that can refer to objects of type Date. It is important to realize that the variable deadline is not an object and, in fact, deos not even refer to an object yet

      • It is important to realize that 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 storedelsewhere. The return value of the new operator is also a reference

      • Date deadline = new Date();

        The above sattement has two parts. The expression new Date() makes an object of type Date, and its value is a reference to that newly crated object. That reference is then stored in the deadline variable

      • You can explicitly set an object variable to null to indicate that it currentlyrefers to no object

      • Java object variables are similar to C++ references

      • All Java objects live on the heap. When an object contains another object variable, it contains just a pointer to yet another heap object 

    • The LocalDate Class of the Java Library

      • The library designers decided to separate the concenrs of keeping time and attaching names to points in time. Therefore, the standard Java library contains two separte classes: the Date class, which represents a point in time, and the LocalDate class, which expresses days in the familiar calendar notation

      • You do not use a constructor to construct objects of the LocalDate class. Instead, use static factory methods that call constructors on your behalf

        • LocalDate.now()
          
          LocalDate newYearsEve = LocalDate.of(1999, 12, 31);
          
          int year = newYearsEve.getYear(); // 1999
          int month = newYearsEve.getMonthValue(); // 12
          int day = newYearsEve.getDayOfMonth(); // 31
          
          LocalDate aThousandDaysLater = newYearsEve.plusDays(1000);
          
          year = aThousandDaysLater.getYear(); // 2002
          month = aThousandDaysLater.getMonthValue(); // 09
          day = aThousandDaysLater.getDayOfMonth(); // 26

           

  • Mutator and Accessor Methods
    • After invoking the method on an object, the state of the object changes
    • In contrast, methos that only access objects without modifying them are sometimes called accessor methods

 

Defining Your Own Classes

  • An Employee Class
    • class definition example
      • class ClassName {
            field1
            field2
            ...
            constructor1
            constructor2
            ...
            method1
            method2
            ...
        }

         

      • Given that the example program consists of two classes: the Employee class and a class EmployeeTest with the public access specifier, the main method is contained in the EmployeeTest class, and the name of the source file is EmployeeTest.java because the name of the file must match the name of the public class

      • You can only have one public class in a source file, but you can have any number of nonpublic classes

      • Nextm when you compile this source code, the compiler creates two clas files in the directory: EmployeeTest.class and Employee.class

      • You then start the program by giving the bytecode interpreter the name of the class that contains the main method of your program

  • Use of Multiple Source Files

    • If you put different classes into different java files, you can invoke the Java compiler with a wildcard:

      • javac Employee*.java
        //or 
        javac EmployeeTest.java

        When the compiler sees the Employee class being used inside EmployeeTEst,java, it will look for a file named Emloyee.class. If it does not find that file, it automatically searches for Employee.java nd compiles it

  • Constructors

    • A constructor has the same name as the class

    • A class can have more than one constructor

    • A constructor can take zero, one, or more parameters

    • A constructor has no return value

    • A constructor is always called with the new operator

    • All Java objects are constructed on the head and that a constructor must be combined with new

    • Note that do not declare local variables inside a constructor, which is only accessible inside the constructor

  • Declaring Local Variables with var

    • As of Java 10, you can declare local variables with the var keyword instead of specifiying hteir type, provided their type can be inferred from the initial value

  • Working with null References

    • Permissive approach

      • turn a null argument into an appropriate non-null value

    • Tough approach

      • reject a null argument

        • Objects.requireNonNull(n, "the name cannot be null");

           

  • Implicit and Explicit Parameters

    • public void raiseSalary(double byPercent)
      {
          double raise = this.salary * byPercent / 100;
          this.salary += raise;
      }
      
      // number007.raiseSalary(5);

      The raiseSalary method has two parameters. The first parrameter, called the implicit parameter, is the object of type Employee that appears before the method name. The second parameter, the number inside the parentheses after the method name, is an explicit parameter

    • In every method, the keyword this refers to the implicit parameter

  • Benefits of Encapsulation

    •  If you want to get and set the value of an instance field, then you need to supply three items

      • A private data field

      • A public field accessor method; and

        • Be careful not to write accessor methods that returm references to mutatble objects, because this will lead to the break of encapsulation (the returned reference and the private field refer to the same mutable object)

        • 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 stored in a new location

      • A public field mutator method

    • Benefits

      • You can change hte internal implementation without affecting any code other than the methods of the class

      • Mutator methods can perform error checking

  • Class-Based Acess Privileges

    • A method of an object class is permitted to acess the private fields of any object of the same type

      • class Employee
        {
        . . .
            public boolean equals(Employee other)
            {
                return name.equals(other.name);
            }
        }

         

  • Private Methods

    • Sometimes, you may wish to break up the code for a computation into separate helper methods. Typically, htese helper methods should not be part of hte public interface - they may be too close to the current implementation or require a special protocol or calling order. Such methods are best implemented as private

    • As long as the method is private, the designers of the class can be assured that it is never used elsewhere, so they can simply drop it

  • Final Instances Fields

    • You can define an instance field as final. Such a field must be initialized when the object is contructed. Afterwards, the field may not be modified again

    • 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)

    • The final keyword for a object reference merely means that the object reference stored in a variable will never again refer to a different object, but the object can be mutated

Static Fields and Methods

  • Static Fields
    • If you define a field as static, then there is only one such field per class. In contrast, each object has its own copy of nonstatic instance fields
  • Static Constants
    • public class Math
      {
          . . .
          public static final double PI = 3.14159265358979323846;
          . . .
      }

      You can access this constant in your program as Math.PI. If the keyword static had been omitted, the nPI would have been an instance field of the Math class. Then you would need an object of this class to access Pi

    • Another static constant that you have used many times is System.out. It is declared in the System class as follows:

      • public class System
        {
            . . .
            public static final PrintStream out = . . .;
            . . .
        }

        Note that public constants are fine since they has been declared as final, you cannot reassign another print stream to it

      • If you look at the System class, you will notice a method setOut that sets System.out to a different stream. You may wonder how that method can cahnge the value of a final varaible. However, the setOut method is a native method, not implemented in the Java programming language. Native methods can bypass the access control mechanisms f the Java language

  • Static Methods

    • Static methods are methods that do not operate on objects

      • Math.pow(x, a)

        The above expression computes the power of x to a. It does not use any Math object to carry out its task

      • You can think of static methods as methods that don't have a this parameter

    • A static method cannot acess instance fields because it does not operate on an object. However, a staic method can access a static field

    • It is legal to use an object to call a static method. However, it is recommended to use the class name instead of the object reference

    • The situations to use static methods

      • When a method doesn't need to access the object state because all needed parameters are supplied as explicit parameters

      • When a method only needs to access static fields of the class

    • The meaning of static in Java: to denote variables and functions that belong t oa class but not to any particular object of the class

  • Factory Methods

    • A static method that is used to generate instances of objects

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

        Above is how hte NumberFormat class yields formatter objects for various styles

    • Reasons to use a factory method

      • You can't give names to constructors. The constructor name is always the smae as the class name. But we want two different names to get the currency instance and the percent instance

      • When you use a constructor, you can't vary the type of the constructed object. But the factory methods actually return objects of the calss DecimalFormat, a subclass tha inherits from NumberFormat

  • The main Method

    • The main method is a static method

    • The main method does not operate on any objects. In fact, when a proram starts, there aren't any objects yet. The static main method executes, and constructs the objects that the proram needs

    • Every class can have a main class, which can be useful for unit testing of classes

      • class Employee
        {
            public Employee(String n, double s, int year, int month, int day)
        {
                name = n;
                salary = s;
                hireDay = LocalDate.of(year, month, day);
        }
        
        . . .
        public static void main(String[] args) // unit test
        {
            var e = new Employee("Romeo", 50000, 2003, 3, 31);
            e.raiseSalary(10);
            System.out.println(e.getName() + " " + e.getSalary());
        }
            . . .
        }
        
        // If you want to test the Employee class in isolation, execute
        // java Employee
        
        // If the Employee class is a part of a larger application, you start the application with 
        // java Application
        // and the main method of the Employee class is never executed

         

Method Parameters

  • Call by Value vs Call by Reference
    • Call by Value: the method gets jeust hte value that the caller provides
    • Call by Reference: the method gets the location of the variable that the caller provides
      • Thus, a method can modify the value stored in a variable passed by reference but no in one passed by value
    • The Java programming language always uses call by value. That means that the method gets a copy of all parameter values. In particular, the method cannot modify the contents of any parameter variables passed to it
    • There are two kinds of method parameters:
      • Primitive types
        • It is impossible for a method to change values of primitive data types
      • Object references
        • You can implement a method that changes the value of an object
        • public static void tripleSalary(Employee x) // works
          {
              x.raiseSalary(200);
          }
          
          // harry = new Employee(...);
          // tripleSalary(harry);

          1. x is initialized with a copy of the value of harry - an object reference 2. The reaiseSalary method is applied to that object reference. The Employee object to which both x and harry refer gets its salary raised by 200 percent. 3. The method ends, and the parameter variable x is no longer in use. The object variable harry continues to refer to the object whose salary was tripled

    • Summary

      • A method cannot modify a parameter of a primitive type

      • A method can change the state of an object paramete 

      • A method cannot make an object parameter refer to a new object

Object Construction 

  • Overloading
    • Some classed have more than one constructor. This capability is called overloading. Overloading occurs if several methods have the same name but different parameters
    • The process for a compiler to find a match is called overloading resolution
    • Signature of the method
      • To completely describe a method, you need to specify its name together with its parameter types
      • Note that the return type is not part of the method signature
  • 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
  • The Constructor with No Arguments
    • public Employee()
      {
          name = "";
          salary = 0;
          hireDay = LocalDate.now();
      }

      If you write a class with no constructors whatsoever, then a no-argument constructor is provided for you. This constructor sets all the instance fields to their default values

    • If a class supplies at least one constructor but does not supply a no-argument constructor, it is illegal to construct objects without supplying arguments

    • Keep in mind that you get a free no-argument constructor only when your class has no other constructors

  • Explicit Field Initialization

    • It is always a good idea to make sure that, regardless of the constructor call, every instance field is set ot something meaningful

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

        The assignment is carried out before the constructor executes

    • The initialization value doesn't have to be a constant value

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

         

  • Parameter Names

    • single-letter parameter names

    • a + parameter names

    • shadow instance fields with the same name

      • this.salary = salary

         

  • Calling Another Constructor

    • The keyworkd this refers to the implicit parameter of a method. However, this keyword has a second meaning

      • If the first statement of 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

    • Currently, we have seen two ways to initalizae a data field

      • By setting a value in a constructor

      • By assigning a value in the delcaration

    • The third mechanism in Java is called an initialization block. Class declarations can contain arbitrary blocks of code. These blocks are executed whenever an object of that class is constructed

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

        In this example, the id field is initialized in the object initialization block, no matter which constructor is used to construct an object. The initialization block runs first, and then the body of the constructor is executed

      • Note: it is legal to define a variable after initializing it in an object initialization block

    • Order of operations

      • If the first line of the constructor calls a second constructor, then the second constructor executes with the provided arguments

      • Otherwise,

        • All data fields are initialized to their default values (0, false, or null)

        • All field initializers and initialization blocks are executed in the order in which they occur in the class declaration

      • The body of the constructor is executed

    • Initalize a static field

      • To initialize a static field, either supply an initial value or use a static initialization block

      • static
        {
            var generator = new Random();
            nextId = generator.nextInt(10000);
        }

        Static initialization occurs when the class is first loaded

  • Object Destruction and the finalize Method

    • If a resource needs to be closed as soon as you have finised using it, supply a close method that does the necessary cleanup. You can call the close method when you are done with the object

    • If you can wait until the virtual machine exits, add a "shutdown hook" with the method Runtime.addShutfownHook

    • Note: do not use the finilize method for cleanup. That method was intended to be called before the garbage collector sweeps away an object, and it is now deprecated

Packages

  • Overview
    • Java allows you to group classes in a collection called a package
  • Package Names
    • The main reason for using packages is to guarantee the uniqueness of class names
      • Consider the domain horstmann.com, when written in reverse order, it turns in to the package name com.horstmann. You can then append a project name, such as com.horstmann.corejava. If you then place the Employee class into that package, the "fully qualifed" name becomes com.horstmann.corejava.Employee
    • Note: from the point of view of the compiler, there is absolutely no relationship between nested packages
      • For example, the packages java.util and java.util.jar have nothing to do with each other. Each is its own independent collection of classes
  • Class Importation
    • A class can use all classes from its own package and all public classes from other packages
    • Access other public classes in another package
      • To use the fully qualified name
      • To use the import statement
        • import java.time.*;

          Note that the above importation has no negative effect on code size compared to the explicit importation. However, if you import classes explicitly, the reader of your code knows exactly which classes you use

        • Note that you can use hte * notation to import a single package. You cnnot use import java.* or import java.*.* to import all packages with the java prefix

    • Naming conflict

      • Suppose you import both java.util and java.sql packages and use a Date class, which is common in both packages

        • Case 1: If you now use the Date class, you get a compile-time error

          • import java.util.*;
            import java.sql.*;
            
            
            Date today; // ERROR--java.util.Date or java.sql.Date?

             

        • Case 2: If you want to use the Date in one of the package, add an additional import statement

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

             

        • Case 3: If you need both Date classes, then use hte full package name with every class name

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

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

  • Static Imports

    • A form of the import statement permits the importing of satic methods and fields, not just classes

      • import static java.lang.System.*;
        import static java.lang.System.out; // import a specific method
        
        out.println("Goodbye, World"); //i.e., System.out

         

  • Addition of a Class into a Package

    • To place classes inside a pakcage, put hte name of the package at the top of your source file, before hte code that defines the classes in the package

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

         

    • If you don't put a package statement in the source file, the nthe classes in that source file belong to the unnamed package. The unnamed package has no package name

    • Place source files into a subdirectory that matches the full package name

      • All source files in the com.horstmann.corejava package should be in a subdirectory com/hosrtmann/corejava

    • Examples

      • The PackageTest class belongs to the unnamed package

        • CoreJava - Chapter 4: Objects and Classes_第2张图片

        • To compile this program, simply change to the base directory and run the command 

        • javac PackageTest.java

          The compiler automaticlly finds the file com/horstmann/corejava and com.mycompany

      • We have classes distributed over several packages (com.horsstmann.corejava nd com.mycompany)

        • CoreJava - Chapter 4: Objects and Classes_第3张图片

        • In this situation, you sitll must compile and run classes from the base directory - the directory containing the com directory

          • javac com/mycompany/PayrollApp.java
            java com.mycompany.PayrollApp

            Note again that the compiler operates on files (with file sperators and an extension .java), whereas the Java interpreter loads a class (with dot separators)

          • Q: What is the difference between a compiler and a Java interpreter?

  • Package Access

    • If you don't specify either public or private, the feature (the class, method, or variable) can be accessed by all methods in the same package

    • Variables must explicitly be marked private, or they will default to having package access

  • The Class Path

    • Classes are stored in subdirectories of the file system. The path to the class must match the package name

    • Class files can also be sotred in a JAR (Java archive) file. A JAR file ocntains multiple class files and subdirectories in a compressed format, saving space and improving peformance

      • Q: What is the difference between a JAR file and a package?

    • Sharing classes among programs

      • Place yoru class files inside a directory (e.g., /home/user/classdir). Note that this directory is the vase directory for the package tree

      • Place any JAR files insidea directory - for example, /home/user/archives

      • Set the class path. The class path is the collection of all locations that can contain class files

        • In UNIX, the elements on the class path are separated by colons

          • /home/user/classdir:.:/home/user/archives/archive.jar

            In the above class, this class path contians

            • The base directory /home/user/classdir or c:\classdir

            • The current directory (.); and

            • The JAR file /home/user/archives/archive.jar 

        • Starting with Java 6, you can specify a wildcard for a JAR file directory

          • /home/user/classdir:.:/home/user/archives/'*'

            In UNIX, the * must be escaped to prevent shell expansion

        • Note: the javac compiler always looks for files in the current directory, but the java virtual machine launcher only looks into the current directory if the "." directory is on the class path. If you have no class path set, it's not a problem -- the default class path consists of the "." directory. But if you have set the clas path and forgot to include the "." directory, your programs will compile without error, but they won't run

          • Q: What is the difference between javac compiler and the java virtual machine launcher?

    • The class path lists all directories and archive files that are starting points for locating classes

      • Suppose we have the sample class path

        • /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 Java API classes. 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
          
          
          com/horstmann/corejava/Employee.class starting from the
          current directory
          
          com/horstmann/corejava/Employee.class inside
          /home/user/archives/archive.jar

           

      • 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 hte package that contains the class. It consults all import directives as possible sources for the class

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

          If the source code refers to a class Employee. The compiler then tries to find java.lang.Employee (because 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

        • The compiler further looks at the source file to see if the source is newer than the class file. If so, the source file is recompiled automatically

          • If you import public classes, the compiler can easily locate source files for public classes

          • If you import a nonpublic class, the compiler seraches all source files of the current package to see which one defines the class

  • Setting the Class Path

    • It is best to specify the class path with the option -classpath

      • java -classpath /home/user/classdir:.:/home/user/archives/archive.jar
        MyProg

         

    • An alternate approach is the CLASSPATH environment variable

      • export CLASSPATH=/home/user/classdir:.:/home/user/archives/archive.jar

        Note that the above line is a impermanent change

JAR files

  • Overview
    • When you package your application, you want to give your users a single file, not a directory structure filled with class files. Java Archive (JAR) files were designed for this purpose. A JAR file can contain both class files and other file types such as image and source files. Moreover, JAR files are compressed, using the familiar ZIP compression format
  • Creating JAR files
    • Use the jar tool to make JAR files
      • jar cvf jarFileNmae file1 file2 ...
        
        // example
        // jar cvf CalculatorClasses.jar *.class icon.gif

        c - Create a new or empty archive and adds files to it; v - Generates verbose output; f - Specifies the JAR file name as the second command-line argument

  • The Manifest

    • In addition to class files, images, and other resources, each JAR file contains a manifest file that describes special features of the archive

    • The manifest file is called MANIFEST.MF and is located in a special META-INF sub-directory of the JAR file

    • The manifest entries are grouped into sections

      • The first section in the manifest is called the main section. It applies to the whole JAR file

      • Subsequent entries can sepcify properties of named entities such as individual files, packages, or URLs. Those entries must begin with a Name entry. Sections are separeted by blank lines

        • Manifest-Version: 1.0
          lines describing this archive
          
          Name: Woozle.class
          lines describing this file
          Name: com/mycompany/mypkg/
          lines describing this package

           

    • To edit the manifest, place the lines that you want to add to the manifest into a text file. Then run

      • jar cfm jarFileName manifestFileName ...
        
        // to make a new JAR file with a manifest
        jar cfm MyArchive.jar manifest.mf com/mycompany/mypkg/*.class
        
        // to update the manifest of an existing JAR file
        jar ufm MyArchive.jar manifest-additions.mf

         

  • Executable JAR Files

    • You can use the e option of the jar command to specify the entry point of your program - the cladss that you would normally specify when invoking the java program lancher

      • jar cvfe MyProgram.jar com.mycompany.mypkg.MainAppClass files to add

         

    • Alternatively, you canspecify the main class of your program in the manifest, including a statement of the from

      • Main-Class: com.mycompany.mypkg.MainAppClass

        Note: the last line in the manifest must end with a newline character

    • With either method, users can simply start the program as

      • java -jar MyProgram.jar

        Depending on the opearting system configuration, users may even be abel toe launch the application by double-clicking the JAR file icon. On Mac OS X, the operating system recognizes the ".jar" file extension and executes the Java program when you double-click a JAR file

  • Multi-Release JAR Files

    • With the introduction of modules and strgon encapusulation of packages, some previouly accessible internal APIs are no longer available. For example, you need to distribute different applications for Java 8 and Java 9 Users. To solve problems such as this one, Java 9 introduces multi-release JARs that can contain class files for different Java releases

    • For backward compatibility, the additional class files are placed in the META-INF/versions directory:

      CoreJava - Chapter 4: Objects and Classes_第4张图片

      Suppose the Application class makes use of the CssParser class. Then the legacy Application.class file can be compiled to use com.usn.javafx.css.CssParser, while the Java 9 version uses javafx.css.CssParser. Java 8 knows nothing about the META-INF/versions directory and will simply load the legacy classes. When the JAR file is read by Java 9, the new version is used instead 

    • To add versioned class files, use the --release flag

      • jar uf MyProgram.jar --release 9 Application.class

         

    • To build a multi-release JAR file from scratch, use the -C option and switch to a different class file directory for each version

      • jar cf MyProgram.jar -C bin/8 . --release 9 -C bin/9 Application.class

        When compiling for different releases, use the --release flag and the -d flag to specify the output directory:

        • javac -d bin/8 --release 8

          Note: Multi-release JARs are not intended for different versions of a program or library. The public APi of all classes should be the same for both releaess. The sole purpose of multi-release JARs is to enable a particular version of your program or library to work with multiple JDK releases

  • A Note about Comman-Line Options

    • Starting with Java 9, the Java tools are moving towards a more common option format where multiletter option names are preceded by double dashes, with single-letter shortcuts for common options

      • ls --human-readable
        ls -h //equivalent to the above

         

    • Arguments of options with -- and multiple letters are separated by whitespace or an = sign

      • javac --class-path /home/user/classdir ...
        javac --class-path=/home/user/classdir ...

         

    • Single-letter options without arguments can be grouped together

      • jar -cvf MyProgram.jar -e mypackage.MyProgram */*.class

         

Documentation Comments

  • Comment Insertation
    • The javadoc utilityextracts information for the following items
      • Modules
      • Packages
      • Public classes and interfaces
      • Public and protected fields
      • Public and protected constructors and methods
    • Comment
      • /**
        Each comment is placed immediately above the feature it describes
         */

        Each /** ... */ documentation comment contains free-form text followd by tags

      • Tag

        • Each /** ... */ documentation comment contains free-form text followed by tags. A tag starts with an @, such as @since or @param

      • Free-form text

        • The first sentence of the free-form text should be a summary satement

        • In the free-from text, you can use HTML modifiers such as ... for emphasis

      • Images

        • If your comments contain links to other files such as images, place those files into a subdirectory, named doc-files, of the directory containing the source file

        • The javadoc utility will copy the doc-files directories and their contents from the source directory to the documentation directory

  • Class Comments

    • The class comment must be placed after any import statements, directly before hte class definition

      • /**
        * A {@code Card} object represents a playing card, such
        * as "Queen of Hearts". A card has a suit (Diamond, Heart,
        * Spade or Club) and a value (1 = Ace, 2 . . . 10, 11 = Jack,
        * 12 = Queen, 13 = King)
        */
        public class Card
        {
            . . .
        }

        Note in the comment above, 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 

      • @return description

      • @throws class description

        • This tag adds a note that this method may throw an exception

      • /**
        * Raises the salary of an employee.
        * @param byPercent the percentage by which to raise the salary (e.g., 10 means 
        * @return the amount of the raise
        */
        public double raiseSalary(double byPercent)
        {
            double raise = salary * byPercent / 100;
            salary += raise;
            return raise;
        }

         

  • Field Comments

    • You only need to document public fields - generally that means static constants

  • General Comments

    • @since

      • The tag @since text makes a "since" entry. The text can be any description of the version that introduced this feature. For example, @since 1.7.1

    • @author

    • @version

      • This tag makes a "version" entry. The text can be any description of hte current version

    • @see & @link

      • You can use hyperlinks to other relrevant parts of the javadoc documentation, or to exernal documents

      • @see: The tag @see reference adds a hpyerlink in the "see also" section. It can be used with both classes and methods. The reference can be one of the following

        • package.class#feature label

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

            The above line makes a link to the raiseSalary(double) method in the com.horstmann.corejava.Employee class. Then, the feature will be located in the current package or class

          • Note that you must use a #, not a period, to separate the class from the method or variable name

        • label

        • "text"

          • @see "Core Java 2 volume 2"

            If the @see tag is followed by a " character, then the text is displayed in the "see also" section

      • @link

        • If you like, you can place hyperlinks to other classes or methods anywhere in any of your documention comments. Insert a special tag of the form

          • {@link package.class#feature label}

             

  • Package Comments

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

      • Supply a Java file named package-info.java. The file must contain an initial Javadoc comment, delimited wih /** and */, followed by a package statement. It should contain no further code or comments

      • Supply an HTML file named package.html. All text between the tags ... is extracted

  • Comment Extraction

    • docDirectory: this is the name of the directory whree you want the HTML files to go

    • Procedures

      • 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 direcotry htat contains the subdirectory com

      • Run the command

        • javadoc -d docDirectory nameOfPackage

          for a single package. Or run

        • javadoc -d docDirectory nameOfPackage1 nameOfPackage2. . .

          to document multiple packages

    • Additional options

      • https://docs.oracle.com/javase/9/javadoc/javadoc.html

Class Design Hints

  • Always keep data private
    • The principle of encapsulation
    • The data representation may change, when data are kept private, changes in their representation will not affect the users of the class, and bugs are easier to detect
  • Always initialize data
  • Don't use too mmany basic types in a class
    • The idea is to replace multiple related uses of basic types with other classes. This keeps your classes easier to understand and to change
      • private String street;
        private String city;
        private String state;
        private int zip;

        Suppose the above private fields are in a Customer class. We can place these fields into a new class called Address. This way you can easily cope with changes to addresses, such as the need to deal with internatinoal addresses

  • Not all fields need individual field accessors and mutators

  • Break up classes that have too many responsibilities

    • A bad design example

      • public class CardDeck // bad design
        {
            private int[] value;
            private int[] suit;
            public CardDeck() { . . . }
            public void shuffle() { . . . }
            public int getTopValue() { . . . }
            public int getTopSuit() { . . . }
            public void draw() { . . . }
        }

        This class really implements two separate concepts: a deck of cards, with its shuffle and draw methods, and a card, with the methods to inspect its value and suit. It makes sense to introduce a Card class that represents an individual card

    • A good design example

      • public class CardDeck
        {
            private Card[] cards;
            public CardDeck() { . . . }
            public void shuffle() { . . . }
            public Card getTop() { . . . }
            public void draw() { . . . }
        }
        
        public class Card
        {
            private int value;
            private int suit;
            public Card(int aValue, int aSuit) { . . . }
            public int getValue() { . . . }
            public int getSuit() { . . . }
        }

         

  • Make the names of your classes and methods reflect their responsibilities

    • A good convention is that a class name should be a noun (Order), or a noun preceded by an adjective (RushOrder), or a gerund (an "-ing" word, as in BillingAddress). As for methods, follow the standard convention that accessor methods begin with a lowercase get(getSalary) and mutator methods use a lowercase set(setSalary)

  • Prefer immutable classes

    • The problem with mutation is that it can happen concurrently when multiple htreads try to update an object at the same time

你可能感兴趣的:(CoreJava,java,编程语言)