Linux and Vi

If you search the web for ‘linux cheat sheet‘ you find numerous one-page documents that list the most commonly used Linux commands.  I recommend that you print or bookmark one to help you learn them.

Navigating the File System

Some of the most common commands that we’ll use are for listing the files within a directory and moving around in the file system.

  • ls
  • ls -l
  • ls -al
  • pwd
  • cd /
  • cd $HOME
  • cd ..
  • cd [dir] (absolute or relative path)

UNIX directory structure

Standard-unix-filesystem-hierarchy

Manipulating Directories and Files

  • mkdir [dir]
  • rmdir [dir]
  • mv [src] [dest]
  • touch [file]
  • cp [orig] [new]
  • cp -r [src_dir] [dest_dir]
  • rm [file]
  • rm -r [dir]    (BE CAREFUL!)
  • chmod [mode] [file]

Displaying File, Manual, Environment and System Information

  • cat [file]
  • man [command]
  • which [command]
  • whereis [command]
  • env
  • whoami
  • hostname
  • date
  • clear

Viewing and Killing Processes

  • ps
  • ps -ax
  • kill [pid]
  • kill -9 [pid]

Pipes

  • [command] | [command]
  • cat filename | less

Vi – The Editor of Champions

  • Insert Mode (i)
    • arrow keys
    • delete
  • Command Mode (esc)
    • x – delete char
    • r [char] – replace char
    • dd – delete line
    • # dd – delete multiple lines
    • u – undo last command
    • yy – copy to clipboard
    • # yy – copy multiple lines
    • p – paste contents of clip board
    • ciw – change inner word
    • v – visual mode
      • use arrows to highlight text
      • y – yank
      • x – delete
    • $ – go to the end of a line
    • 0 – go to the beginning of a line
    • shift + G – go to the end of the file
    • shift + H – go to the beginning of the file
    • :# – goto line a particular line
    • :/search_term – search for a particular term
    • :%s/old/new/g – find and replace
    • :w – write the file
    • :q – quit vi
    • :q! – quit without writing
    • 😡 – write and quit

When copy and pasting text that contains comments into vi, vi erroneously adds additional // characters.  To prevent this, enter the following command to suppress this behavior.

:autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o

Programming Advice

  1. As you develop your code remember to compile often.  When I’m writing code, I compile and test my code after writing each block of code (think { }) and after each function call.  This helps me find bugs immediately so that I never have more than one or two at any given time.
  2. To speed up the development process, open up two terminals; one always open for writing source code in vi and the other available for compiling and testing.
  3. Learn the vi keyboard commands for searching, replacing and navigating by downloading a vi cheat sheet.

Advice by Joshua Boch

From Effective Java, 2nd Edition by Joshua Bloch, lead designer of Java 5

Creating and Destroying Objects

  • Item 1: Consider static factory methods instead of constructors
  • Item 2: Consider a builder when faced with many constructor parameters
  • Item 3: Enforce the singleton property with a private constructor or an enum type
  • Item 4: Enforce noninstantiability with a private constructor
  • Item 5: Avoid creating unnecessary objects
  • Item 6: Eliminate obsolete object references
  • Item 7: Avoid finalizers

Methods Common to All Objects

  • Item 8: Obey the general contract when overriding equals
  • Item 9: Always override hashCode when overriding equals
  • Item 10: Always override toString
  • Item 11: Override clone judiciously
  • Item 12: Consider implementing Comparable

Classes and Interfaces

  • Item 13: Minimize the accessibility of classes and members
  • Item 14: In public classes, use accessor methods, not public fields
  • Item 15: Minimize mutability
  • Item 16: Favor composition to inheritance
  • Item 17: Design and document for inheritance or else prohibit it
  • Item 18: Prefer interfaces to abstract classes
  • Item 19: Use interfaces only to define types
  • Item 20: Prefer class hierarchies to tagged classes
  • Item 21: Use function objects to represent strategies
  • Item 22: Favor static member classes over nonstatic

Generics

  • Item 23: Don’t use raw types in new code
  • Item 24: Eliminate unchecked warnings
  • Item 25: Prefer lists to arrays
  • Item 26: Favor generic types
  • Item 27: Favor generic methods
  • Item 28: Use bounded wildcards to increase API flexibility
  • Item 29: Consider typesafe heterogeneous containers

Enums and Annotations

  • Item 30: Use enums instead of int constants
  • Item 31: Use instance fields instead of ordinals
  • Item 32: Use EnumSet instead of bit fields
  • Item 33: Use EnumMap instead of ordinal indexing
  • Item 34: Emulate extensible enums with interfaces
  • Item 35: Prefer annotations to naming patterns
  • Item 36: Consistently use the override annotation
  • Item 37: Use marker interfaces to define types

Methods

  • Item 38: Check parameters for validity
  • Item 39: Make defensive copies when needed
  • Item 40: Design method signatures carefully
  • Item 41: Use overloading judiciously
  • Item 42: Use varargs judiciously
  • Item 43: Return empty arrays or collections, not nulls
  • Item 44: Write doc comments for all exposed API elements

General Programming

  • Item 45: Minimize the scope of local variables
  • Item 46: Prefer for-each loops to traditional for loops
  • Item 47: Know and use the libraries
  • Item 48: Avoid float and double if exact answers are required
  • Item 49: Prefer primitive types to boxed primitives
  • Item 50: Avoid strings where other types are more appropriate
  • Item 51: Beware the performance of string concatenation
  • Item 52: Refer to objects by their interfaces
  • Item 53: Prefer interfaces to reflection
  • Item 54: Use native methods judiciously
  • Item 55: Optimize judiciously
  • Item 56: Adhere to generally accepted naming conventions

Exceptions

  • Item 57: Use exceptions only for exceptional conditions
  • Item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
  • Item 59: Avoid unnecessary use of checked exceptions
  • Item 60: Favor the use of standard exceptions
  • Item 61: Throw exceptions appropriate to the abstraction
  • Item 62: Document all exceptions thrown by each method
  • Item 63: Include failure-capture information in detail messages
  • Item 64: Strive for failure atomicity
  • Item 65: Don’t ignore exceptions

Introduction to Classes

Java include syntax that allows programers to create user-defined types.  A user-defined type is defined in a class definition.

The general form of a class definition is as follows:

class className {
    // fields
    // constructors
    // methods
    // inner classes
}

An instance of a class is called an object.

Fields

A field is a variable declaration within a class definition.

Fields allow us to store within a single object various types of data. For example, suppose you want to store information about a box in a program, you could create three variables named height, width, and length. That’s simple enough.  But by constructing a new type, lets name it Box, and adding fields to class definition, we can store the dimensions of a box within a single object.

class Box {
    int height;
    int width;
    int length;
}

In the example above, we say the Box class has 3 fields named height, width, and length.

We can create an instance of a Box using the new keyword and invoking a  constructor.

Box aBox = new Box();

When the new keyword is used, a new instance of that type (or object) is created in heap memory. Then a constructor is called which initializes the object. Finally, a reference (memory address) to that new object is stored in the variable on the left hand side of the assignment statement. Note that the object itself is not stored in the variable, but rather a reference to the object is stored in the variable.

When no constructor is included in a class definition, as in the above example, a default constructor is used which initializes all unassigned numeric, reference, and booloean fields to 0, null, and false respectively.   So in the example above, the 3 fields of the object referenced by aBox are initialized to the value 0.

We can access the fields of the object using the reference to the object and the dot operator.

int volume = aBox.length * aBox.width * aBox.height;

We can modify the fields of an object also using the reference to the object and dot operator on the left hand side of an assignment operator (=).

aBox.height = 6;
aBox.width = 6;
aBox.length = 12;

You can optionally initialize the fields in the class definition so that when an instance of the class is created the fields have some initial value.

class Box {
    int height = 0;
    int width = 0;
    int length = 0;
}
Final Fields

A field can be declared as final which prohibits it from being modified after the constructor is run.  This implies the field is essentially a constant.  Since it can’t be modified after the constructor’s code is executed, the field’s value has to be initialized either when it is declared or within a constructor.  The former is usually the norm.

Final Reference Fields

It should be noted that when a field is declared final, the fields value can not be changed after the constructor is executed.  If the field is a reference type, that implies that the field will always refer to the same object.  This doesn’t prohibit modifying the object itself.  Consider the following example:

class A {
    int x = 0;
}
class Driver {
    final static A obj = new A();

    public static void main(String[] args) {
        //obj = new A();                        // error!
        System.out.println(obj.x);              // prints 0
        obj.x = 10;                             
        System.out.println(obj.x);              // prints 10
    }
}

So, although the reference stored in obj can not change, the properties of the object that obj references can be modified.

Constructors

As mentioned above, a constructor is a block of code that is executed to initialize a newly created class object.  Constructors are defined using the following general form.  Notice the constructor uses the name of the class in its definition.

ClassName (parameter-list) {
    ...
}

To continue the box example, we can include a parameterless constructor that initialize each of the fields of a newly created object to -1.

class Box {
    int height;
    int width;
    int length;

    Box() {        
        height = -1;
        width = -1;
        length = -1;
    }
}
Overloading Constructors

A class can have multiple constructors so long as they don’t create ambiguity when determining which constructor is to be invoked.  When we provide more than one constructor we say the constructor is overloaded.

In order to allow the creation of a Box object that has dimensions that are different than the default dimensions, we can include a constructor with parameters that will require the user to pass values into the constructor when creating a new instance of Box.

class Box {
    int height;
    int width;
    int length;

    Box() {        
        height = -1;
        width = -1;
        length = -1;
    }
        
    Box(int h, int w, int l) {
        height = h;
        width = w;
        length = l;
    }
}

To create instances of the above Box class we can either use the parameterless constructor or pass 3 integer values as arguments to use the second constructor.

Box aBox = new Box();
Box bBox = new Box(6, 12, 24);

To call the second constructor, arguments must be passed to the constructor and the types of the arguments must match the parameters in the constructor definition.

Lets look at the code within the second constructor.  When the constructor is being executed, a local variable is created for each of the parameters; one named h, one named w, and the last named l.  These local variables are initialized with the values of the arguments that are passed to the constructor: 6, 12, and 26.  Then the statements inside the constructor’s block are executed which initializes the fields.

As mentioned earlier, when we create an instance of the class, a reference (memory address) to the new object is stored in the variable specified on the left hand side of the assignment statement.  In the example above, aBox and bBox have different values because they hold different memory addresses to two different Box objects.  We can check if two variables point to the same object in memory by using the comparison operators (==, !=).

if (aBox != bBox) {
    System.out.println("aBox points to a different Box object than bBox");
}

This

When code inside a class definition is being executed, it is being executed for some particular instance of the class.  The this keyword is used inside a class definition to refer to the specific instance of the class for which the code is executing.

For example, when we define a constructor (or method) we can use field names as identifiers in the parameter list.  When we do, since parameters define local variables inside the constructor that are different from the field variables, the parameters that have field names hide the fields with same names.  If we want to access an object’s fields when the fields are hidden, we can use the this keyword as shown below.

class Box {
    int height;
    int width;
    int length;
        
    Box(int height, int weight, int length) {
        this.height = height;
        this.width = width;
        this.length = length;
    }
}

The first statement in the constructor’s block sets the field named height equal to the value of the first argument passed into the constructor which is stored in the local variable named height.

Methods

A method is a block of code in a class definition that is executed on an instance of the class (aka object). When a programmer requests that the block of code in a method be executed on an object, we say the method is being called on the object.

A method definition includes a return type, followed by the name of the method, followed by a parameter list and a block of code.

Take for example the Box class below that contains the method named getHeight.

class Box {
    int height;
    int width;
    int length;
        
    Box(int h, int w, int l) {
        height = h;
        width = w;
        length = l;
    }

    int getHeight() {
        return height;
    }
}

The method named getHeight simply returns the value currently being stored in the field named height of some object.  Since the field named height stores an integer, the return type of the method is int.

Suppose we have a program that has created two boxes as shown below.

Box aBox = new Box(1,2,3);
Box bBox = new Box(5,5,5);

When we call a method we must call the method on an instance of the the method’s class. We call a method on an object by using the reference to the object and the dot operator as shown below.

int aBoxHeight = aBox.getHeight();
int bBoxHeight = bBox.getHeight();

In the example above, aBoxHeight holds the value 1 and bBoxHeight holds the value 5.

Methods can also receive input data through a parameter list as in the method named setHeight shown below.

class Box {
    int height;
    int width;
    int length;
        
    Box(int h, int w, int l) {
        height = h;
        width = w;
        length = l;
    }

    int getHeight() {
        return height;
    }

    void setHeight(int h) {
        height = h;
    }
}

The method named setHeight can be used to change the value of a Box object’s height field.

aBox.setHeight(10);

The method named setHeight doesn’t return any data, so we set the return type to void.  The method requires the caller to pass in an integer. When the method is called, the value passed into the method is stored in a local variable named h.  After the parameter has been initialized, the code block for the method is executed.  Recall that methods are called on instances of the class.  When the method’s block of code is executed on a particular instance of the class, the object’s height field is set equal to the value of the local variable named h.

As with constructors, we can use fields names in the parameter list of a method.  When we do, the fields are hidden, but can be accessed in the method’s block by using the this keyword.

We can also overload methods.  That is, we can include in our class more than one method with the same name, so long as there is no ambiguity as to which method is being called.

Getters and Setters

A method in a class that is defined to simply return the value of a field is called a getter.   A method in a class that is defined to simply set the value of a field is called a setter.  Block recommends (Item 14) that we use getters and setters (accessor methods) to access fields.

Garbage Collection

Recall that a variable of a user-defined type holds a reference to an object of that type.  The reference is an address pointing to some area of heap memory.  The memory that holds an object that is no longer referenced by any variable is automatically freed in a process called garbage collection. Garbage collection occurs sporadically, and may not occur at all when your program is running. But if memory is needed and there are objects that are no longer referenced, that memory will be freed by the garbage collector so that it can be reused.

finalize()

If a class definition includes a finalize() method, then before the garbage collector frees up the memory used by an object of that class, the garbage collector will call the finalize() method on the instance in memory. Since there is uncertainty as to when or if even an object will be garbage collected, it is not recommended to rely on a finalize() method to release resources.  In fact, Bloch (Item 7) recommends we avoid using finalize() altogether.