Post

Data Structures - Basic 0


DS

source:


Type

Base Type

base types (also called primitive types):

  • boolean a boolean value: true or false
  • char 16-bit Unicode character
  • byte 8-bit signed two’s complement integer
  • short 16-bit signed two’s complement integer
  • int 32-bit signed two’s complement integer
  • long 64-bit signed two’s complement integer
  • float 32-bit floating-point number (IEEE 754-1985)
  • double 64-bit floating-point number (IEEE 754-1985)
1
2
3
4
5
6
7
8
9
boolean flag = true;
boolean verbose, debug;
char grade = 'A';
byteb=12;
short s = 24;
inti,j,k=257;
long l = 890L;
float pi = 3.1416F;
double e = 2.71828, a = 6.022e23;

Char

  • Java’s char: stores a value that represents a single text character.
    • In Java, the set of all possible characters, an alphabet, is the Unicode international character set, a 16-bit character encoding that covers most used written languages. (Some programming languages use the smaller ASCII character set, which is a proper subset of the Unicode alphabet based on a 7-bit encoding.)
    • The form for expressing a character literal in Java is using single quotes, such as ‘G’.

Enum Types 枚举

before

  • In olden times, programmers would often define a series of constant integer values to be used for representing a finite set of choices.
  • A slightly better programming style is to define static constants (with the final keyword), to make the associations
    • because it becomes possible to make assignments such as today = TUE, rather than the more obscure today = 1.
1
2
3
static final int MON = 0;
static final int TUE = 1;
static final int WED = 2;
  • Unfortunately, the variable today is still declared as an int using such a programming style, and it may not be clear that you intend for it to represent a day of the week when storing it as an instance variable or sending it as a parameter.

enumerated type (enum)

  • Java supports a more elegant approach to representing choices from a finite set by defining an enumerated type (enum).

  • These are types that are only allowed to take on values that come from a specified set of names.

    • modifier can be blank, public, protected, or private.
    • name, can be any legal Java identifier.
    • Each of the value identifiers, valueNamei, is the name of a possible value that variables of this enum type can take on.
    • Each of these name values can also be any legal Java identifier, but the Java convention is that these should usually be capitalized words.
    • For example,
      • an enumerated type definition for days of the weak might appear as: public enum Day { MON, TUE, WED, THU, FRI, SAT, SUN };
      • Once defined, Day becomes an official type
      • declare variables or parameters with type Day: Day today;
      • assignment of a value to that variable: today = Day.TUE;
1
2
3
4
5
6
7
8
modifier enum name { valueName0 , valueName1 , . . . , valueNamen1 };

// 例如定义一个颜色的枚举类。
enum Color {RED, GREEN, BLUE;}

Color c1 = Color.RED;
System.out.println(c1);
// RED
1
2
3
4
5
6
7
// 例如定义一个颜色的枚举类。

enum Color {RED, GREEN, BLUE;}

Color c1 = Color.RED;
System.out.println(c1);
// RED

Enum是在Java中用来定义枚举类型的关键字。

  • Enum一般用来表示一组相同类型的常量,如性别、日期 、颜色等.
  • 在Java中枚举类型本质上就是一个类,其继承自java.lang.Enum类。
  • Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。
  • 使用 enum 关键字来定义,各个常量使用逗号 , 来分割。

  • 每个枚举都是通过 Class 在内部实现的,且所有的枚举值都是 public static final 的。

枚举类 Color 转化在内部类实现

1
2
3
4
5
class Color {
     public static final Color RED = new Color();
     public static final Color BLUE = new Color();
     public static final Color GREEN = new Color();
}

内部类 中使用 枚举

  • 可以声明在内部类中:
1
2
3
4
5
6
7
8
9
public class Test {
    enum Color {RED, GREEN, BLUE;}
    // 执行输出结果
    public static void main(String[] args){
        Color c1 = Color.RED;
        System.out.println(c1);
    }
}
// RED

迭代枚举元素

  • 使用 for 语句来迭代枚举元素:
1
2
3
4
5
6
enum Color {RED, GREEN, BLUE;}

for (Color myVar : Color.values() ) System.out.println(myVar);
// RED
// GREEN
// BLUE

在 switch 中使用枚举类

  • 枚举类常应用于 switch 语句中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum Color {RED, GREEN, BLUE;}

Color myVar = Color.BLUE;
switch(myVar) {
  case RED:
    System.out.println("红色");
    break;
  case GREEN:
     System.out.println("绿色");
    break;
  case BLUE:
    System.out.println("蓝色");
    break;
}
// 蓝色

values(), ordinal() 和 valueOf() 方法

  • enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Serializable 和 java.lang.Comparable 两个接口。

  • values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:

    • values() : 返回枚举类中所有的值。
    • ordinal() : 找到每个枚举常量的索引,就像数组索引一样。
    • valueOf() : 返回指定字符串值的枚举常量。
1
2
3
4
5
6
7
8
9
10
11
12
13
enum Color {RED, GREEN, BLUE;}

Color myVar = Color.BLUE;

Color[] arr = Color.values();
// 查看索引
for (Color col : arr) System.out.println(col + " at index " + col.ordinal());
// 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
System.out.println(Color.valueOf("RED"));
// RED at index 0
// GREEN at index 1
// BLUE at index 2
// RED

枚举类成员

  • 枚举跟普通类一样可以用自己的变量、方法和构造函数
  • 构造函数只能使用 private 访问修饰符,所以外部无法调用。
  • 枚举既可以包含具体方法,也可以包含抽象方法
    • 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
enum Color {
    RED, GREEN, BLUE;
    // 构造函数

    // 抽象方法
    private Color() {
        System.out.println("Constructor called for : " + this.toString());
    }
    // 具体方法
    public void colorInfo() {
        System.out.println("Universal Color");
    }
}
 
Color c1 = Color.RED;
System.out.println(c1);
c1.colorInfo();
// 执行以上代码输出结果为:
// Constructor called for : RED
// Constructor called for : GREEN
// Constructor called for : BLUE
// RED
// Universal Color

枚举类中的抽象方法实现

  • 需要枚举类中的每个对象都对其进行实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
enum Color{
    RED {
        public String getColor() {//枚举对象实现抽象方法
            return "红色";
        }
    },
    GREEN {
        public String getColor(){ //枚举对象实现抽象方法
            return "绿色";
        }
    },
    BLUE {
        public String getColor(){ //枚举对象实现抽象方法
            return "蓝色";
        }
    };

    public abstract String getColor();//定义抽象方法
}

for (Color c:Color.values() ) System.out.print(c.getColor() + "、");
// 红色、绿色、蓝色

Type Conversions

Casting is an operation that allows us to change the type of a value.

  • take a value of one type and cast it into an equivalent value of another type.

There are two forms of casting in Java:

  • explicit casting and implicit casting.

Explicit Casting

  • Java supports an explicit casting syntax with the following form: (type) exp
  • This syntax may only be used to cast from one primitive type to another primitive type, or from one reference type to another reference type.

  • Casting from an int to a double is known as a widening cast, as the double type is more broad than the int type, and a conversion can be performed without losing information.
  • cast from a double to an int is a narrowing cast; we may lose precision, as any fractional portion of the value will be truncated.
1
2
3
4
5
double d1 = 3.2;
double d2 = 3.9999;
int i1 = (int) d1; // i1 gets value 3
int i2 = (int) d2; // i2 gets value 3
double d3 = (double) i2; // d3 gets value 3.0
  • Although explicit casting cannot directly convert a primitive type to a reference type, or vice versa, there are other means for performing such type conversions. We already discussed, as part of Section 1.3, conversions between Java’s primitive types and corresponding wrapper classes (such as int and Integer).
  • For convenience, those wrapper classes also provide static methods that convert between their corresponding primitive type and String values.
    • For example,
    • Integer.toString method accepts an int parameter and returns a String representation of that integer,
    • Integer.parseInt method accepts a String as a parameter and returns the corresponding int value that the string represents.
1
2
3
String s1 = "2014";
int i1 = Integer.parseInt(s1); // i1 gets value 2014 int i2 = −35;
String s2 = Integer.toString(i2); // s2 gets value ”-35”

Implicit Casting

  • perform an implicit cast based upon the context of an expression.

  • For example, you can perform a widening cast between primitive types (from an int to a double), without explicit use of the casting operator.
  • However, implicit narrowing cast -> a compiler error results.
1
2
3
int i1 = 42;
double d1 = i1; // d1 gets value 42.0
i1 = d1; // compile error: possible loss of precision
  • Implicit casting also occurs when performing arithmetic operations involving a mixture of numeric types. Most notably, when performing an operation with an in- teger type as one operand and a floating-point type as the other operand, the integer value is implicitly converted to a floating-point type before the operation is per- formed.
  • For example, the expression 3 + 5.7 is implicitly converted to 3.0 + 5.7 before computing the resulting double value of 8.7.
  • It is common to combine an explicit cast and an implicit cast to perform a floating-point division on two integer operands.
  • The expression (double) 7 / 4 produces the result 1.75
  • because operator precedence dictates that the cast happens first, as ( (double) 7) / 4, and thus 7.0 / 4, which implicitly becomes 7.0 / 4.0. Note however that the expression, (double) (7 / 4) produces the result 1.0.

string concatenation

  • one situation in Java when only implicit casting is allowed
    • Any time a string is concatenated with any object or base type, that object or base type is automatically converted to a string.
    • Explicit casting of an object or base type to a string is not allowed
  • To perform a conversion to a string, we must use the appropriate toString method or perform an implicit cast via the concatenation operation.
1
2
3
4
5
6
7
8
String s = 22; // this is wrong!
String t = (String) 4.5; // this is wrong!
String u = "Value = " + (String) 13; // this is wrong!

// Thus, the following statements are correct:
String s = Integer.toString(22);
String t = "" + 4.5;
String u = "Value=" + 13;

Wrapper

  • There are many data structures and algorithms in Java’s libraries that are specifically designed so that they only work with object types (not primitives).
  • To get around this obstacle, Java defines a wrapper class for each base type.
  • An instance of each wrapper type stores a single value of the corresponding base type.
  • Java’s wrapper classes. Each class is given with its corresponding base type and example expressions for creating and accessing such objects.

Screen Shot 2022-03-01 at 23.17.20

Automatic Boxing and Unboxing

  • Java provides additional support for implicitly converting between base types and their wrapper types through a process known as automatic boxing and unboxing.
  • In any context for which an Integer is expected (for example, as a parameter), an int value k can be expressed, Java automatically boxes the int, with an implicit call to new Integer(k).
  • In reverse, in any context for which an int is expected, an Integer value v can be given, Java automatically unboxes it with an implicit call to v.intValue().
  • Similar conversions are made with the other base-type wrappers.
  • Finally, all of the wrapper types provide support for converting back and forth between string literals.
1
2
3
4
5
6
7
8
9
int j=8; // box
Integer a = new Integer(12);

int k=a; // implicit call to a.intValue()
int m=j+a; // a is automatically unboxed before the addition

a =3m; // result is automatically boxed before assignment
Integer b = new Integer("-135");  // constructor accepts a String
int n = Integer.parseInt("2013"); // using static method of Integer class

Classes and Objects

Every object is an instance of a class

  • class serves as the type of the object and as a blueprint
  • class defining the data which the object stores and the methods for accessing and modifying that data.

The critical members of a class in Java are the following:

  • Instance variables/fields
    • represent the data associated with an object of a class.
    • Instance variables must have a type, which can either be a base type (such as int, float, or double) or any class type (reference type)
  • Methods
    • blocks of code that can be called to perform actions (similar to functions and procedures in other high-level languages).
    • Methods can accept parameters as arguments, and their behavior may depend on the object upon which they are invoked and the values of any parameters that are passed.
    • accessor method: returns information to the caller without changing any instance variables
    • update method : may change one or more instance variables when called.

Creating and Using Objects

Counter class does not have a main method, and so it cannot be run as a complete program. Instead, the purpose of the Counter class is to create instances that might be used as part of a larger program.

1
2
3
4
5
6
7
8
9
10
public class Counter {
    private int count;
    public Counter() { } // default constructor (count is 0)
    public Counter(int initial) { count = initial; } // an alternate constructor
    public int getCount() { return count; }  // an accessor method
    public void increment() { count++; }  // an update method
    public void increment(int delta) { count += delta; }  // an update method
    public void reset() { count = 0; }  // an update method
}

a new variable c is declared with the syntaxm Counter c;

  • This establishes the identifier c, as a variable of type Counter,
  • but it does not create a Counter instance.
  • Classes are reference types in Java, and a variable of that type (c) is a reference variable.
    • A reference variable is capable of storing the location (i.e., memory address) of an object from the declared class.
    • So we might assign it to reference an existing instance or a newly constructed instance.
    • A reference variable can also store a special value, null, that represents the lack of an object.

a new object is created by using the new operator + a call to a constructor for the class;

  • a constructor: a method that always shares the same name as its class.
  • The new operator returns a reference to the instance; the returned reference is typically assigned to a variable for further use.
  • Counter c; c = new Counter();
  • a new Counter is constructed with its reference assigned to the variable c. That relies on a form of the constructor, Counter(), that takes no arguments between the parentheses. (Such a zero-parameter constructor is known as a default constructor.)

Three events occur as part of the creation of a new instance of a class:

  • A new object is dynamically allocated in memory
    • all instance variables are initialized to standard default values.
    • The default values are null for reference variables and 0 for all base types except boolean variables (which are false by default).
  • The constructor for the new object is called with the parameters specified.
    • The constructor may assign more meaningful values to any of the instance variables, and perform any additional computations that must be done due to the creation of this object.
  • After the constructor returns, the new operator returns a reference (a memory address) to the newly created object. If the expression is in the form of an assignment statement, then this address is stored in the object variable, so the object variable refers to this newly created object.

the Dot operator

Screen Shot 2022-02-20 at 21.36.51

One of the primary uses of an object reference variable is to access the members of the class for this object

  • an instance of its class.

  • to access the methods and instance variables associated with an object.
  • This access is performed with the dot (“.”) operator.
  • call a method associated with an object:
    • reference variable name + dot operator + the method name and its parameters.
    • c.increment()
  • If the dot operator is used on a reference that is currently null, the Java runtime environment will throw a NullPointerException.

  • If there are several methods with this same name defined for a class, then the Java runtime system uses the one that matches the actual number of parameters sent as arguments, as well as their respective types.
    • two methods named increment: a zero-parameter form and a one- parameter form.
    • Java determines which version to call when evaluating commands such as c.increment( ) versus c.increment(3).
  • A method’s name combined with the number and types of its parameters is called a method’s signature, for it takes all of these parts to determine the actual method to perform for a certain method call.
    • Note, however, that the signature of a method in Java does not include the type that the method returns, so Java does not allow two methods with the same signature to return different types.
  • A reference variable v can be viewed as a “pointer” to some object o.
    • the variable is a holder for a remote control that can be used to control the newly created object (the device).
    • the variable has a way of pointing at the object and asking it to do things or give us access to its data.
    • Using the remote control analogy, a null reference is a remote control holder that is empty.

The assignment

the aliasing of two reference variables to the same object is not permanent.

  • may reassign a reference variable to a new instance, a different existing instance, or null.
1
2
3
4
5
6
7
Counter c = new Counter(5);
Counter d = new Counter(5);
// d is a distinct instance from the one identified as c.

Counter e = d;
// a new reference variable named e, and assigns that variable a reference to the existing counter instance currently identified as d.
// At that point, both variables d and e are aliases for the same object

Defining a Class

Modifiers


Access Control Modifiers public, protected, private, or the default package-level
  • control the level of access (visibility) that the defining class grants to other classes in larger Java program.
  • The ability to limit access among classes supports a key principle of object-orientation -> encapsulation

In general, the different access control modifiers and their meaning are as follows:

public

  1. The public class modifier
    • designates that all classes may access the defined aspect.
    • For example
      • public class Counter {
      • all other classes (such as CounterDemo) are allowed to construct new instances of the Counter class, as well as to declare variables and parameters of type Counter.
    • In Java, each public class must be defined in a separate file named class_name.java
      • for example, file Counter.java for the Counter class definition
  2. public access for a particular method of a class
    • allows any other class to make a call to that method.
    • For example
      • public int getCount() { return count; }
      • the CounterDemo class may call c.getCount().
  3. an instance variable is declared as public
    • dot notation can be used to directly access the variable by code in any other class that possesses a reference to an instance of this class.
    • For example, were the count variable of Counter to be declared as public (which it is not), then the CounterDemo would be allowed to read or modify that variable using a syntax such as c.count.

protected

  1. The protected class modifier
    • designates that access to the defined aspect is only granted to the following groups of other classes:
      • Classes that are designated as subclasses of the given class through inheritance.
      • Classes that belong to the same package as the given class

private

  1. The private class modifier
    • designates that access to a defined member of a class be granted only to code within that class. Neither subclasses nor any other classes have access to such members.
    • For example
      • defined the count instance variable of the Counter class to have private access level.
      • We were allowed to read or edit its value from within methods of that class (such as getCount, increment, and reset),
      • but other classes such as CounterDemo cannot directly access that field.
      • Of course, we did provide other public methods to grant outside classes with behaviors that depended on the current count value.

package-private access level

  • if no explicit access control modifier is given, the defined aspect has what is known as package-private access level.
  • This allows other classes in the same package to have access, but not any classes or subclasses from other packages.

Non-Access Control Modifiers
  • abstract is a non-access modifier in java applicable for classes, methods but not variables. It is used to achieve abstraction which is one of the pillar of Object Oriented Programming(OOP).
  1. Abstract classes
    • having partial implementation
    • not all methods present in the class have method definition
    • Due to partial implementation, cannot instantiate abstract classes.
    • Any subclass of an abstract class must either implement all of the abstract methods in the super-class, or be declared abstract itself.
    • Some of the predefined classes in java are abstract. They depends on their sub-classes to provide complete implementation.
    • For example, java.lang.Number is a abstract class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public abstract class Employee {
   private String name;
   private String address;
   private int number;
   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   public void mailCheck() {
      System.out.println("Mailing a check to " + this.name + " " + this.address);
   }
}

/* 以下是不允许的,会引发错误 */
Employee e = new Employee("George W.", "Houston, TX", 43);
// Employee.java:46: Employee is abstract; cannot be instantiated
//       Employee e = new Employee("George W.", "Houston, TX", 43);
//                    ^
// 1 error


public class Salary extends Employee {
   private double salary; //Annual salary
   public Salary(String name, String address, int number, double salary) {
       super(name, address, number);
   }
}
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
s.mailCheck();
e.mailCheck();
  1. Abstract methods
    • Sometimes, require just method declaration in super-classes.
    • This can be achieve by specifying the abstract type modifier.
    • These methods are sometimes referred to as subclasser responsibility because they have no implementation specified in the super-class.
    • Thus, a subclass must override them to provide method definition.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
abstract type method-name(parameter-list){
  // body
};


abstract class A  {
    // abstract with method it has no body
    abstract void m1();
    // concrete methods are still allowed in abstract classes
    void m2() { System.out.println("This is a concrete method."); }
}

// concrete class B
class B extends A {
    // class B must override m1() method
    // otherwise, compile-time exception will be thrown
    void m1() { System.out.println("B's implementation of m2."); }
}


B b = new B();
b.m1();
b.m2();
// Output:
// B's implementation of m2.
// This is a concrete method.

The static Modifier

Math.sqrt(2)

The static modifier in Java can be declared for any variable or method of a class (or for a nested class)

  1. When a variable of a class is declared as static 静态变量
    • its value is associated with the class as a whole, rather than with each individual instance of that class. (可以用于引用所有对象的公共属性(对于每个对象不是唯一的)。如:员工公司名称,学生所在的大学名称。)

    • Static variables are used to store “global” information about a class.
      • For example, be used to maintain the total number of instances of that class that have been created.
    • Static variables exist even if no instance of their class exists.
    • 优点:
      • 能使程序存储器高效(即它节省内存)。
      • 静态化(使用static关键字修饲),这个字段将只获得内存一次。
      • Java静态属性被共享给所有对象

        117100301_14333

        1
        2
        3
        4
        5
        6
        7
        8
        
         class Student{
             int rollno;
             String name;
             // String college="ITS";
             static String college = "ITS";
         }
         Student s1 = new Student(111, "Karan");
         Student s2 = new Student(222, "Aryan");/
        
  2. When a method of a class is declared as static 静态方法
    • associated with the class itself, and not with a particular instance of the class.
      • the method is not invoked on a particular instance of the class using the traditional dot notation.
      • Instead, it is typically invoked using the name of the class as a qualifier.
    • For example
      • in the java.lang package, which is part of the standard Java distribution, there is a Math class that provides many static methods, including one named sqrt that computes square roots of numbers.
      • To compute a square root, you do not need to create an instance of the Math class; that method is called using a syntax such as Math.sqrt(2), with the class name Math as the qualifier before the dot operator.
    • Static methods can be useful for providing utility behaviors related to a class that need not rely on the state of any particular instance of that class.
    • 静态方法属于类,而不属于类的对象。
    • 可以直接调用静态方法,而无需创建类的实例。
    • 静态方法可以访问静态数据成员,并可以更改静态数据成员的值。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      
         class Student9 {
             int rollno;
             String name;
             static String college = "ITS";
      
             static void change() {
                 college = "BBDIT";
             }
      
             Student9(int r, String n) {
                 rollno = r;
                 name = n;
             }
      
             public static void main(String args[]) {
                 // 直接调用静态方法,而无需创建类的实例。
                 Student9.change();
                 Student9 s1 = new Student9(111, "Karan");
             }
         }
         // 上面代码执行输出以下结果 -
         111 Karan BBDIT
      

The abstract Modifier
  1. A method of a class may be declared as abstract
    • its signature is provided but without an implementation of the method body.
    • Abstract methods are an advanced feature of object-oriented programming to be combined with inheritance
    • In short, any subclass of a class with abstract methods is expected to provide a concrete implementation for each abstract method.
  2. A class with one or more abstract methods must also be formally declared as abstract, because it is essentially incomplete.
    • also permissible to declare a class as abstract even if it does not contain any abstract methods.
    • As a result, Java will not allow any instances of an abstract class to be constructed, although reference variables may be declared with an abstract type.

The final Modifier

final可以是:

  • 变量
  • 方法

final关键字应用有以下几点需要注意:

  • 禁止变量的值被改变;
  • 禁止方法重写;
  • 禁止类继承;
  1. A variable that is declared with the final modifier can be initialized as part of that declaration, but can never again be assigned a new value.
    • If it is a base type, then it is a constant.
    • If a reference variable is final, then it will always refer to the same object (even if that object changes its internal state).
    • If a member variable of a class is declared as final, it will typically be declared as static as well, because it would be unnecessarily wasteful to have every instance store the identical value when that value can be shared by the entire class.
  2. Designating a method or an entire class as final has a completely different consequence, only relevant in the context of inheritance.
    • A final method cannot be overridden by a subclass,
    • a final class cannot even be subclassed.

final变量 final int speedlimit = 90;
  • 如果将变量设置为final,则不能更改final变量的值(它将是常量)。
  • 要改变final变量的值,这是不可能的,因为一个final变量一次分配一个值永远不能更改。
1
2
3
4
5
6
7
8
9
10
class Bike9 {
    final int speedlimit = 90;// final variable
    void run() {
        speedlimit = 400; // 不可以修改 final 变量的值
    }
}
Bike9 obj = new Bike9();
obj.run();
// 上面代码执行后生成以下结果 -
[编译错误]Compile Time Error
  1. 空白final变量

    • 空白/未初始化的final变量
    • 在声明时未初始化的final变量
    • 在创建一个对象时初始化变量,并且变量在初始化后就不会被改变
    • 例如员工的PAN CARD号码。
    1
    2
    3
    4
    5
    
     class Student{
         int id;
         String name;
         final String PAN_CARD_NUMBER;
     }
    
    • 它只能在构造函数初始化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     class Bike10 {
         final int speedlimit;// blank final variable
    
         Bike10() { // 在构造函数中初始化
             speedlimit = 70;
             System.out.println(speedlimit);
         }
     }
     new Bike10();
     // 上面代码执行后生成以下结果 -
     70
    
  2. 静态空白final变量

    • 在声明时未初始化的静态final变量
    • 只能在静态块初始化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
     class A {
         static final int data;// static blank final variable
         static {
             data = 50;
         }
    
         public static void main(String args[]) {
             System.out.println(A.data);
         }
     }
    

final参数 int cube(final int n) {}
  • 如果将任何参数声明为final,则不能更改它的值。
1
2
3
4
5
6
7
8
9
10
class Bike11 {
    int cube(final int n) {
        n = n + 2; // can't be changed as n is final
        return n;
    }
}
Bike11 b = new Bike11();
b.cube(5);
// 上面代码执行后生成以下结果 -
[编译错误]Compile Time Error

final方法 final void run() {}
  • 如果任何方法声明为final,则不能覆盖它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
      class Bike {
          final void run() {
              System.out.println("running");
          }
      }
    
      class Honda extends Bike {
          void run() { // final方法,不可以重写
              System.out.println("running safely with 100kmph");
          }
      }
      Honda honda = new Honda();
      honda.run();
      // 上面代码执行后生成以下结果 -
      [编译错误]Compile Time Error
    
  • final方法是继承的,但是不能覆盖它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      class Bike {
          final void run() {
              System.out.println("running...");
          }
      }
    
      class Honda2 extends Bike {
          public static void main(String args[]) {
              new Honda2().run();
          }
      }
      // 上面代码执行后生成以下结果 -
      Output:running...
    

final类 final class Bike {}
  • 如果把任何一个类声明为final,则不能扩展它。
1
2
3
4
5
6
7
8
9
10
11
12
// 不可以扩展 final 类
final class Bike {}

class Honda1 extends Bike {
    void run() {
        System.out.println("running safely with 100kmph");
    }
}
Honda1 honda = new Honda();
honda.run();
// 上面代码执行后生成以下结果 -
[编译错误]Compile Time Error

Instance Variables

  • When defining a class, we can declare any number of instance variables.
  • An important principle of object-orientation is that each instance of a class maintains its own individual set of instance variables.
    • in the case of the Counter class, each instance will store its own (independent) value of count.
  • The general syntax for declaring one or more instance variables of a class is as follows:
1
2
3
4
[modifiers] type identifier1[=initialValue1], identifier2[=initialValue2];
private int count;

// Because we did not declare an initial value, it automatically receives the default of zero as a base-type integer.

Methods

  • A method definition has two parts:
    • the signature
      • which defines the name and parameters for a method,
      • specifies how the method is called
    • and the body,
      • which defines what the method does.
      • specifies what the object will do when it is called.

The syntax for defining a method:

1
2
3
[modifiers] returnType methodName(type1 param1 , ..., typen paramn) {
    // method body . . .
}
  • the significance of modifiers such as public, private, and static.
  • The returnType designation defines the type of value returned by the method.
  • The specifies how the method is called can be any valid Java identifier.
  • The list of parameters and their types declares the local variables that correspond to the values that are to be passed as arguments to this method.
  • Each type declaration typei can be any Java type name and each parami can be any distinct Java identifier. This list of parameters and their types can be empty, which signifies that there are no values to be passed to this method when it is invoked.
  • These parameter variables, as well as the instance variables of the class, can be used inside the body of the method. Likewise, other methods of this class can be called from inside the body of a method.
  • When a (nonstatic) method of a class is called, it is invoked on a specific instance of that class and can change the state of that object.

    • For example, the follow- ing method of the Counter class increases the counter’s value by the given amount.
1
2
3
public void increment(int delta) {
    count += delta;
}

Notice that the body of this method uses count, which is an instance variable, and delta, which is a parameter.

Return Types

  • A method definition must specify the type of value the method will return.
    • If the method does not return a value, the keyword void must be used.
    • To return a value in Java, the body of the method must use the return keyword, followed by a value of the appropriate return type.
  • Java methods can return only one value.
    • To return multiple values in Java, combine all the values to return in a compound object, whose instance variables include all the values we want to return, and then return a reference to that compound object.
    • In addition, we can change the internal state of an object that is passed to a method as another way of “returning” multiple results.
1
2
3
public int getCount() {
    return count;
}

Parameters

  • A method’s parameters are defined in a comma-separated list enclosed in parentheses after the name of the method.
  • A parameter consists of two parts, the parameter type and the parameter name.
  • If a method has no parameters, then only an empty pair of parentheses is used.

All parameters in Java are passed by value

  • any time pass a parameter to a method, a copy of that parameter is made for use within the method body.
    • So if pass an int variable to a method, then that variable’s integer value is copied. The method can change the copy but not the original.
    • If we pass an object reference as a parameter to a method, then the reference is copied as well.
  • Remember that we can have many different variables that all refer to the same object.
  • Reassigning the internal reference variable inside a method will not change the reference that was passed in.

For the sake of demonstration, we will assume that the following two methods were added to an arbitrary class (such as CounterDemo).

1
2
3
4
5
6
7
8
9
public static void badReset(Counter c) {
    c = new Counter();
    // reassigns local name c to a new counter
}

public static void goodReset(Counter c) {
    c.reset();
    // resets the counter sent by the caller
}

Now we will assume that variable strikes refers to an existing Counter instance in some context, and that it currently has a value of 3.

  • If we were to call badReset(strikes), this has no effect on the Counter known as strikes.
  • The body of the badReset method reassigns the (local) parameter variable c to reference a newly created Counter instance;
    • but this does not change the state of the existing counter that was sent by the caller (i.e., strikes).

In contrast, if we were to call goodReset(strikes), this does indeed reset the caller’s counter back to a value of zero.

  • That is because the variables c and strikes are both reference variables that refer to the same Counter instance.
  • So when c.reset() is called, that is effectively the same as if strikes.reset() were called.

Constructors public, protected, private, or the default package-level

declaring a constructor in Java:

1
2
3
modifiers name(type0 parameter0 , ..., typen1 parametern1) {
    // constructor body . . .
}

constructor

  • a special kind of method to initialize a newly created instance of the class so that it will be in a consistent and stable initial state.

  • This is typically achieved by initializing each instance variable of the object (unless the default value will suffice),

  • very similar way as other methods of a class, but few important distinctions:
    1. Constructors cannot be static, abstract, or final, so the only modifiers that are allowed are those that affect visibility (i.e., public, protected, private, or the default package-level visibility).

    2. The name of the constructor must be identical to the name of the class it constructs.
      1. For example, defining the Counter class, a constructor must be named Counter as well.
    3. don’t specify a return type for a constructor (not even void).
      1. Nor does the body of a constructor explicitly return anything.
      2. When a user of a class creates an instance using a syntax such as Counter d = new Counter(5);
      3. the new operator is responsible for returning a reference to the new instance to the caller;
      4. the responsibility of the constructor method is only to initialize the state of the new instance.
  • A class can have many constructors, but each must have a different signature
    • each must be distinguished by the type and number of the parameters it takes.
    • If no constructors are explicitly defined, Java provides an implicit default constructor for the class, having zero arguments and leaving all instance variables initialized to their default values.
    • However, if a class defines one or more nondefault constructors, no default constructor will be provided.
    • As an example, our Counter class defines the following pair of constructors:
    1
    2
    
    public Counter() { }
    public Counter(int initial) { count = initial; }
    
    • The first of these has a trivial body, { }, as the goal for this default constructor is to create a counter with value zero, and that is already the default value of the integer instance variable, count.

    • it is important to declare such an explicit constructor,

      • because otherwise none would have been provided, given the existence of the nondefault constructor.
      • In that scenario, a user would have been unable to use the syntax, new Counter().

The Keyword this

在java中,这是一个引用当前对象的引用变量。

Within the body of a (nonstatic) method in Java, the keyword this is automatically defined as a reference to the instance upon which the method was invoked.

  • if a caller uses a syntax such as thing.foo(a, b, c), then within the body of method foo, the keyword this refers to the object known as thing in the caller’s context.

3 common reasons why this reference is needed from within a method body:

  1. To store the reference in a variable, or send it as a parameter to another method that expects an instance of that type as an argument.

  2. To differentiate between an instance variable and a local variable with the same name.
    • If a local variable is declared in a method having the same name as an instance variable for the class, that name will refer to the local variable within that method body.
    • the local variable masks the instance variable.
    • In this case, the instance variable can still be accessed by explicitly using the dot notation with this as the qualifier.
    1
    2
    3
    4
    
     public Counter(int count) {
         this.count = count;
     // set the instance variable equal to parameter
     }
    
  3. To allow one constructor body to invoke another constructor body.
    • When one method of a class invokes another method of that same class on the current instance, that is typically done by using the (unqualified) name of the other method.
    • But the syntax for calling a constructor is special.
    • Java allows use of the keyword this as a method within the body of one constructor, to invoke another constructor with a different signature.
    • This is often useful because all of the initialization steps of one constructor can be reused with appropriate parameterization.
    • As a trivial demonstration of the syntax, we could reimplement the zero-argument version of our Counter constructor to have it invoke the one-argument version sending 0 as an explicit parameter.
    1
    2
    3
    4
    
     public Counter() {
         this(0);
         // invoke one-parameter constructor with value zero
     }
    

java this关键字的用法如下:

  1. 可用来引用 当前类的实例变量。
  2. 可用于调用 当前类方法(隐式)。
  3. 可用于调用 当前类的构造函数。
  4. 可用于作为调用方法中的参数传递。
  5. 可用于作为参数在构造函数调用中传递。
  6. 可用于从方法返回当前类的实例。

1. 引用 当前类 的实例变量

如果实例变量和参数之间存在歧义,则 this 关键字可用于明确地指定类变量以解决歧义问题。

  • 参数(形式参数)和实例变量(rollno和name)是相同的。 所以要使用this关键字来区分局部变量和实例变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Student {
    // 实例变量
    int rollno;
    String name;
    float fee;

    Student(int rollno, String name, float fee) { // 局部变量
        rollno = rollno;
        name = name;
        fee = fee;
    }
    // output == 0
    // 在上面的例子中,参数(形式参数)和 实例变量(rollno和name) 是相同的。
    // 所以要使用this关键字来区分 局部变量 和 实例变量。


    Student(int rollno, String name, float fee) {
        this.rollno = rollno;
        this.name = name;
        this.fee = fee;
    }

    // 如果局部变量(形式参数)和实例变量不同,则不需要使用this关键字
    Student(int r, String n, float f) {
        rollno = r;
        name = n;
        fee = f;
    }
}

2. 调用 当前类 方法

使用this关键字调用当前类的方法。

  • 如果不使用this关键字,编译器会在调用方法时自动添加此 this 关键字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {
    void m(){}
    void n(){
        m();
    }
}
new A().n();


class A {
    void m(){}
    void n(){
        this.m();
    }
}
new A().n();

3. 调用 当前类 的构造函数

this() 构造函数调用

  • 可以用来调用当前类的构造函数。
  • 它用于重用构造函数, 构造函数链接。

从 参数化构造函数 调用 默认构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
    A() {
        System.out.println("hello a");
    }
    A(int x) {
        this();
        System.out.println(x);
    }
}

A a = new A(10);
// 输出结果:
hello a
10

从 默认构造函数 调用 参数化构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
    A() {
        this(5);
        System.out.println("hello a");
    }
    A(int x) {
        System.out.println(x);
    }
}
A a = new A();
// 输出结果
5
hello a

使用 this() 调用 构造函数

this()构造函数 调用 用于从 构造函数 重用 构造函数。

  • 它维护构造函数之间的链,即它用于构造函数链接。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Student {
    int rollno;
    String name, course;
    float fee;

    Student(int rollno, String name, String course) {
        this.rollno = rollno;
        this.name = name;
        this.course = course;
    }

    Student(int rollno, String name, String course, float fee) {
        // 注意:调用this()必须是构造函数中的第一个语句。
        // 不把 this() 语句放在第一行,因此编译不通过。
        this(rollno, name, course);// reusing constructor
        this.fee = fee;
    }

    void display() {
        System.out.println(rollno + " " + name + " " + course + " " + fee);
    }
}
Student s1 = new Student(111, "ankit", "java");
Student s2 = new Student(112, "sumit", "java", 6000f);
s1.display();
s2.display();
// 输出结果:
111 ankit java null
112 sumit java 6000

4. 作为参数 传递给 方法

可以作为方法中的参数传递。

  • 它主要用于事件处理
1
2
3
4
5
6
7
8
9
10
11
12
class S2 {
    void m(S2 obj) {
        System.out.println("hi");
    }
    void p() {
        m(this);
    }
}
S2 s1 = new S2();
s1.p();
// 输出结果 -
hi

这个应用程序可以作为参数传递: 在事件处理(或)的情况下,必须提供一个类的引用到另一个。 它用于在多个方法中重用一个对象。

5. 在构造函数调用中 作为参数传递

也可以在构造函数中传递this关键字。

  • 如果必须在多个类中使用一个对象,可以使用这种方式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class B {
    A4 obj;

    B(A4 obj) {
        this.obj = obj;
    }
    void display() {
        System.out.println(obj.data);// using data member of A4 class
    }
}

class A4 {
    int data = 10;

    A4() {
        B b = new B(this);
        b.display();
    }

    public static void main(String args[]) {
        A4 a = new A4();
    }
}
// 输出结果 -
10

6. 返回 当前类 的实例

可以从方法中 this 关键字作为语句返回

  • 在这种情况下,方法的返回类型必须是类类型(非原始)

作为语句返回的语法

1
2
3
return_type method_name(){
    return this;
}

从方法中返回 为语句的 this 关键字的示例

class A {
    A getA() {
        return this;
    }
    void msg() {
        System.out.println("Hello java");
    }
}
new A().getA().msg();
// 输出结果
Hello java

验证 this 关键字 this 关键字引用当前类的实例变量。

  • 在这个程序中将打印参考变量,这两个变量的输出是相同的。
class A5 {
    void m() {
        System.out.println(this);// prints same reference ID
    }
}
A5 obj = new A5();
System.out.println(obj);// prints the reference ID
obj.m();
// 输出结果 -
A5@22b3ea59
A5@22b3ea59

The main Method

  • The primary control for an application in Java must begin in some class with the execution of a special method named main.
  • The args parameter is an array of String objects, a collection of indexed strings,
    • Those represent what are known as command-line arguments that are given by a user when the program is executed.
1
2
3
public static void main(String[ ] args) {
    // main method body...
}
  • Java programs can be called from the command line using the java command (in a Windows, Linux, or Unix shell), followed by the name of the Java class whose main method we want to run, plus any optional arguments.
  • execute the main method of a class named Aquarium: java Aquarium
    • the Java runtime system looks for a compiled version of the Aquarium class,
    • and then invokes the special main method in that class.
  • If defined the Aquarium program to take an optional argument, invoke the program: java Aquarium 45

Unit Testing

  • defining a class meant to be used by other classes rather than as a self-standing program, no need to define a main method.
  • provide such a method as a way to test the functionality of that class in isolation, knowing that it would not be run unless we specifically invoke the java command on that isolated class. However, for more robust testing, frameworks such as JUnit are preferred.

Expressions

  • Variables and constants are used in expressions to define new values and to modify variables.
  • Expressions involve the use of literals, variables, and operators

Literals

  • A literal is any “constant” value that can be used in an assignment or other expres- sion. Java allows the following kinds of literals:
    • The null object reference (this is the only object literal, and it is allowed to be any reference type).
    • Boolean: true and false.
    • Integer: The default for an integer which is a 32-bit integer.
      • A long integer literal must end with an “L” or “l”,
      • for example, 176L or -52l, and defines a 64-bit integer.
    • Floating Point: The default for floating-point numbers, such as 3.1415 and 135.23, is that they are double.
      • To specify that a literal is a float, it must end with an “F” or “f”.
      • Floating-point literals in exponential notation are also allowed, such as 3.14E2 or .19e10; the base is assumed to be 10.
    • Character: In Java, character constants are assumed to be taken from the Unicode alphabet.
      • Typically, a character is defined as an individual symbol enclosed in single quotes.
      • For example, ’a’ and ’?’ are character constants. In addition, Java defines the following special character constants:

        1
        2
        3
        4
        5
        6
        7
        8
        
          '\n' (newline)
          '\b' (backspace)
          '\f' (form feed)
          '\'' (single quote)
          '\t' (tab)
          '\r' (return)
          '\\' (backslash)
          '\"' (double quote).
        
    • String Literal: A string literal is a sequence of characters enclosed in double quotes, for example, the following is a string literal: "dogs cannot climb trees"

Operators

Java expressions involve composing literals and variables with operators.


Arithmetic Operators

The following are binary arithmetic operators in Java:

1
2
3
4
5
6
+ addition
 subtraction
 multiplication / division
% the modulo operator, the remainder left after an integer division.
// n = m*q + r,
// n mod m = r,

String Concatenation

With strings, the (+) operator performs concatenation

  • Java converts nonstring values (such as 5) into strings, when they are involved in a string concatenation operation!!
1
2
3
4
String rug = "carpet";
String dog = "spot";
String mess = rug + dog;
String answer = mess +"willcostme"+ 5 +"hours!";

Increment and Decrement Operators

Like C and C++, Java provides increment and decrement operators.

  • Specifically, it provides the plus-one increment (++) and decrement (−−) operators.
    • If such an operator is used in front of a variable reference, ++1
      • then 1 is added to (or subtracted from) the variable and its value is read into the expression.
    • If it is used after a variable reference, i--
      • then the value is first read and then the variable is incremented or decremented by 1.
1
2
3
4
5
int i = 8;
int j = i++; // j becomes 8 and then i becomes 9
int k = ++i; // i becomes 10 and then k becomes 10
int m = i−−; // m becomes 10 and then i becomes 9
int n = 9 + −−i; // i becomes 8 and then n becomes 17

Logical Operators

Java supports the standard comparisons operators between numbers:

  • The type of the result of any of these comparison is a boolean.
  • Comparisons may also be performed on char values, with inequalities determined according to the underlying character codes.
  • expression a == b is true if a and b both refer to the identical object (or are both null).
  • Most object types support an equals method, such that a.equals(b) is true if a and b refer to what are deemed as “equivalent” instances for that class (even if not the same instance);
1
2
3
4
5
6
< less than
<= less than or equal to
== equal to
!= not equal to
>= greater than or equal to
> greater than

Operators defined for boolean values are the following:

  • The boolean operators && and will not evaluate the second operand (to the right) in their expression if it is not needed to determine the value of the expression.
  • This “short circuiting” feature is useful for constructing boolean expressions where we first test that a certain condition holds (such as an array index being valid) and then test a condition that could have otherwise generated an error condition had the prior test not succeeded.
1
2
3
! not (prefix)
&& conditional and
|| conditional or

Bitwise Operators

Java also provides the following bitwise operators for integers and booleans:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 bitwise not complement (prefix unary operator)  [1->0 0->1]
& bitwise and                                     [1&1->1 other 0]
| bitwise or                                      [has 1 is 1]
^ bitwise exclusive-or                            [different 1 is 1]

<< shift bits left, filling in with zeros         [111 -> 110]
>> shift bits right, filling in with sign bit
>>> shift bits right, filling in with zeros       [111 -> 011]


a = 5 = 0101 (In Binary)
b = 7 = 0111 (In Binary)

// Bitwise NOT is an unary operator that flips the bits of the number i.e.,
// if the ith bit is 0, it will change it to 1 and vice versa.
// Bitwise NOT is the one’s complement of a number.
// N = 5 = (101)2
// ~N = ~5 = ~(101)2 = (010)2 = 2


// Bitwise Complement Operation of 5
// ~ 0101
//  ________
//   1010  = 10 (In decimal)


// Bitwise AND Operation of 5 and 7     (all 1 is 1)
//   0101
// & 0111
//  ________
//   0101  = 5 (In decimal)


// Bitwise OR Operation of 5 and 7       (has 1 is 1)
//   0101
// | 0111
//  ________
//   0111  = 7 (In decimal)


// Bitwise XOR Operation of 5 and 7      (different 1 is 1)
//   0101
// ^ 0111
//  ________
//   0010  = 2 (In decimal)


// 1001 <<1 = 10010

The Assignment Operator

The standard assignment operator in Java is “=”.

  • to assign a value to an instance variable or local variable.
1
2
3
4
variable = expression

// if j and k are both declared as type int
j = k = 25; // works because ’=’ operators are evaluated right-to-left Compound

Compound Assignment Operators

Besides the standard assignment operator (=), Java also provides a number of other assignment operators that combine a binary operation with an assignment.

1
2
3
4
5
6
// These other kinds of operators are of the following form:
variable op= expression
// where op is any binary operator.
// The above expression is generally equivalent to
variable = variable op expression
// x ∗= 2 is equivalent to x = x ∗ 2.

Operator Precedence

Operators in Java are given preferences, or precedence, that determine the order in which operations are performed when the absence of parentheses brings up evaluation ambiguities.

Screen Shot 2022-03-02 at 10.41.44


Control Flow


question mark and colon

1
2
a = condition ? value1 : value2;
a>b ? true : false;

The If and Switch Statements

If Statement

  • the value tested by an if statement in Java must be a boolean expression.
1
2
3
if (firstBooleanExpression) firstBody
else if (secondBooleanExpression) secondBody
else thirdBody

Switch Statements

  • Java provides for multiple-value control flow using the switch statement, which is especially useful with enum types.
  • The switch statement evaluates an integer, string, or enum expression and causes control flow to jump to the code location labeled with the value of this expression.
  • If there is no matching label, then control flow jumps to the location labeled “default.”
  • This is the only explicit jump performed by the switch statement, however, so flow of control “falls through” to the next case if the code for a case is not ended with a break statement (which causes control flow to jump to the end).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
switch (d) {
    case MON:
        System.out.println("This is tough.");
        break;
    case TUE:
        System.out.println("This is getting better.");
        break;
    case WED:
        System.out.println("Half way there.");
        break;
    case THU:
        System.out.println("I can see the light.");
        break;
    case FRI:
        System.out.println("Now we are talking.");
        break;
    default:
        System.out.println("Day off!"); }

Loops

  • Another important control flow mechanism in a programming language is looping.
  • Java provides for three types of loops.

While Loops

  • a certain condition is satisfied and will perform the body of the loop each time this condition is evaluated to be true.
1
while (booleanExpression) loopBody

Do-While Loops

  • allows the boolean condition to be checked at the end of each pass of the loop rather than before each pass.

  • A consequence of the do-while loop is that its body always executes at least once. ( while loop will execute zero times if the initial condition fails.)
  • This form is most useful for a situation in which the condition is ill-defined until after at least one pass.
1
2
3
4
5
6
7
8
9
10
do
    loopBody
while (booleanExpression)

String input;
do {
    input = getInputString();
    handleInput(input);
}
while (input.length() > 0);

For Loops

  • Java supports two different styles of for loop.
    • “traditional” style, is patterned after a similar syntax as for loops in the C and C++ languages.
    • “for-each” loop, was introduced into Java in 2004 as part of the SE 5 release. This style provides a more succinct syntax for iterating through elements of an array or an appropriate container type.
1
for (initialization; booleanCondition; increment) loopBody

For-Each Loop

  • Java provides a shorthand notation for such loops
1
for (elementType name : container) loopBody

Explicit Control-Flow Statements

Return from a Method

  • If a Java method is declared with a return type of void, then flow of control returns when it reaches the last line of code in the method or when it encounters a return statement (with no argument).
  • If a method is declared with a return type, however, the method must exit by returning an appropriate value as an argument to a return statement.
  • It follows that the return statement must be the last statement executed in a method, as the rest of the code will never be reached.

The break Statement

  • to exit from the body of a switch statement.
  • used to “break” out of the innermost switch, for, while, or do-while statement body.
  • When it is executed, a break statement causes the flow of control to jump to the next line after the loop or switch to the body containing the break.

The continue Statement

  • A continue statement can be used within a loop.
  • It causes the execution to skip over the remaining steps of the current iteration of the loop body,
  • but then, unlike the break statement, the flow of control returns to the top of the loop, assuming its condition remains satisfied.

Simple Input and Output

Simple Output Methods

  • Java provides a built-in static object, System.out, that performs output to the “standard output” device.
  • The System.out object is an instance of the java.io.PrintStream class.
    • This class defines methods for a buffered output stream
    • characters are put in a temporary location, called a buffer, which is then emptied when the console window is ready to print characters.
1
2
3
4
5
6
7
8
9
10
11
12
13
print(String s)   // Print the string s.
print(Object o)   // Print the object o using its toString method.
print(baseType b) // Print the base type value b.
println(String s) // Print the string s, followed by the newline character.
println(Object o) // Similar to print(o), followed by the newline character.
println(baseType b) // Similar to print(b), followed by the newline character.


System.out.print("Java values: ");
System.out.print(3.1416);
System.out.print(',');
System.out.print(15);
System.out.println(" (double,char,int).");

Simple Input

  • Just as there is a special object for performing output to the Java console window, there is also a special object, called System.in, for performing input from the Java console window.
  • Technically, the input is actually coming from the “standard input” device, which by default is the computer keyboard echoing its characters in the Java console.
  • The System.in object is an object associated with the standard input device.
1
2
3
import java.util.Scanner; // loads Scanner definition for our use
Scanner input = new Scanner(System.in);
double age = input.nextDouble();
  • java.util.Scanner Methods
    • The Scanner class reads the input stream and divides it into tokens, which are strings of characters separated by delimiters.
    • A delimiter is a special separating string, and the default delimiter is whitespace.
    • That is, tokens are separated by strings of spaces, tabs, and newlines, by default. Tokens can either be read immediately as strings or a Scanner object can convert a token to a base type, if the token has the right form.
    • Specifically, the Scanner class includes the following methods for dealing with tokens:
1
2
3
4
5
6
7
8
hasNext()
// Return true if there is another token in the input stream.
next()
// Return the next token string in the input stream; generate an error if there are no more tokens left.
hasNextType()
// Return true if there is another token in the input stream and it can be interpreted as the corresponding base type, Type, where Type can be Boolean, Byte, Double, Float, Int, Long, or Short.
nextType()
// Return the next token in the input stream, returned as the base type corresponding to Type; generate an error if there are no more tokens left or if the next token cannot be interpreted as a base type corresponding to Type.
  • Scanner objects can process input line by line, ignoring delimiters, and even look for patterns within lines while doing so.
1
2
3
4
5
6
7
hasNextInt()
hasNextLine()
// Returns true if the input stream has another line of text.
nextLine()
// Advances the input past the current line ending and returns the input that was skipped.
findInLine(String s)
// Attempts to find a string matching the (regular expression) pattern s in the current line. If the pattern is found, it is returned and the scanner advances to the first char- acter after this match. If the pattern is not found, the scanner returns null and doesn’t advance.

Packages and Imports

Packages

  • To aid in the organization of large code repository, Java allows a group of related type definitions (such as classes and enums) to be grouped into a package.
    • For types to belong to a package named packageName
      • their source code must all be located in a directory named packageName
      • each file must begin with the line: package packageName;
  • By convention, most package names are lowercased.

  • Public definitions within a file that does not have an explicit package declaration are placed into what is known as the default package.

  • To refer to a type within a named package, we may use a fully qualified name based on dot notation, with that type treated as an attribute of the package.
    • For example, we might declare a variable with architecture.Window as its type.

subpackages

  • Packages can be further organized hierarchically into subpackages.
  • Code for classes in a subpackage must be located within a subdirectory of the package’s directory, and qualified names for subpackages rely on further use of dot notation.
    • For example, there is a java.util.zip subpackage (with support for working with ZIP compression) within the java.util package, and the Deflater class within that subpackage is fully qualified as java.util.zip.Deflater.

advantages to organizing classes into packages:

  • Packages help us avoid the pitfalls of name conflicts.
    • If all type definitions were in a single package, there could be only one public class named Window.
    • But with packages, we can have an architecture.Window class that is independent from a gui.Window class for graphical user interfaces.
  • It is much easier to distribute a comprehensive set of classes for other programmers to use when those classes are packaged.

  • When type definitions have a related purpose, easier for other programmers to find them in a large library and to better understand their coordinated use when they are grouped as a package.

  • Classes within the same package have access to any of each others’ members having public, protected, or default visibility (i.e., anything but private).

Import Statements

  • construct a new instance of that class: java.util.Scanner input = new java.util.Scanner(System.in);
  • However, all the extra typing needed to refer to a class outside of the current package can get tiring.
  • use the import keyword to include external classes or entire packages in the current file.

  • it is illegal to import a class with the above syntax if a similarly named class is defined elsewhere in the current file, or has already been imported from another package.
    • For example, we could not simultaneously import both architecture.Window and gui.Window to use with the unqualified name Window.
1
2
3
4
5
6
// To import an individual class from a specific package
import packageName.className;

// imported the Scanner class from the java.util
import java.util.Scanner;
Scanner input = new Scanner(System.in);
1
2
3
4
5
6
7
8
9
10
11
12
# Importing a Single Class
from car import Car
my_new_car = Car('audi', 'a4', 2019)

# Importing Multiple Classes from a Module
from car import Car, ElectricCar

# Importing an Entire Module
import car

# Using Aliases
from car import ElectricCar as EC

Importing a Whole Package

  • using many definitions from the same package, import all of them using an asterisk character (∗) to denote a wildcard,
1
2
3
4
5
6
import packageName.;

import architecture.; // which we assume includes a Window class
import gui.;          // which we assume includes a Window class
architecture.Window
gui.Window

Software Development

Traditional software development involves several phases. Three major steps are:

  1. Design
  2. Pseudocode

  3. Coding

  4. Testing and Debugging

Design

  1. Responsibilities: Divide the work into different actors/responsibility. Try to describe responsibilities using action verbs. These actors will form the classes for the program.
  2. Independence: Define the work for each class to be as independent from other classes as possible. Subdivide responsibilities between classes so that each class has autonomy over some aspect of the program. Give data (as in- stance variables) to the class that has jurisdiction over the actions that require access to this data.
  3. Behaviors: Define the behaviors for each class carefully and precisely, so that the consequences of each action performed by a class will be well understood by other classes that interact with it. These behaviors will define the methods that this class performs, and the set of behaviors for a class form the protocol by which other pieces of code will interact with objects from the class.

CRC cards

  • A common tool for developing an initial high-level design for a project
  • Class-Responsibility-Collaborator (CRC) cards
  • index cards that subdivide the work required of a program.
  • The main idea behind this tool is to have each card represent a component, which will ultimately become a class in the program.
    • write the name of each component on the top of an index card.
    • On the left-hand side of the card, we begin writing the responsibilities for this component.
    • On the right-hand side, we list the collaborators for this component, that is, the other components that this component will have to interact with to perform its duties.
  • The design process iterates through an action/actor cycle, where we first identify an action (that is, a responsibility), and we then determine an actor (that is, a component) that is best suited to perform that action.

  • The design is complete when we have assigned all actions to actors.
    • In using index cards for this process
    • each component should have a small set of responsibilities and collaborators.
    • Enforcing this rule helps keep the individual classes manageable.

UML (Unified Modeling Language)

  • a standard approach to explain and document the design to express the organization of a program.
  • UML diagrams are a standard visual notation to express object-oriented software designs.
  • Several computer-aided tools are available to build UML diagrams.
  • One type of UML figure is known as a class diagram.

  • The diagram has three portions,
    • the first designating the name of the class,
    • the second designating the recommended instance variables,
    • and the third designating the recommended methods of the class.
  • The type declarations of variables, parameters, and return values are specified in the appropriate place following a colon, and the visibility of each member is designated on its left,
    • “+” symbol for public visibility,
    • “−” symbol for private visibility.
    • “#” symbol for protected visibility,

Screen Shot 2022-03-02 at 15.20.58

Pseudocode

  • before the implementation of a design, o describe algorithms in a way that is intended for human eyes only.

coding

  • implementing an object-oriented program is coding the descriptions of classes and their respective data and methods.

  • In order to accelerate the development of this skill, we will discuss various design patterns for designing object-oriented programs at various points throughout this text. These patterns provide templates for defining classes and the interactions between these classes.

  • settled on a design for the classes or program and their responsibilities, drafted pseudocode for their behaviors, begin the actual coding on a computer.

  • We type the Java source code for the classes of our program by using either an independent text editor (such as emacs, WordPad, or vi), or the editor embedded in an integrated development environment (IDE), such as Eclipse.

  • Once we have completed coding for a class (or package), we compile this file into working code by invoking a compiler.
    • If we are not using an IDE, then we compile our program by calling a program, such as javac, on our file.
    • If we are using an IDE, then we compile our program by clicking the appropriate compilation button.
    • If program has no syntax errors, then this compilation process will create files with a “.class” extension.

    • If our program contains syntax errors, then these will be identified, and we will have to go back into our editor to fix the offending lines of code.
  • after eliminated all syntax errors, and created the appropriate compiled code, we can run our program by either invoking a command, such as “java” (outside an IDE), or by clicking on the appropriate “run” button (within an IDE).

  • When a Java program is run in this way, the runtime environment locates the directories containing the named class and any other classes that are referenced from this class according to a special operating system environment variable named CLASSPATH
  • This variable defines an order of directories in which to search, given as a list of directories, which are separated by colons in Unix/Linux or semicolons in DOS/Windows.

  • An example
    • CLASSPATH assignment in the DOS/Windows: SET CLASSPATH=.;C:\java;C:\Program Files\Java\
    • CLASSPATH assignment in the Unix/Linux: setenv CLASSPATH ".:/usr/local/java/lib:/usr/netscape/classes"

Documentation and Style

Javadoc

  • In order to encourage good use of block comments and the automatic production of documentation, the Java programming environment comes with a documentation production program called javadoc.
  • This program takes a collection of Java source files that have been commented using certain keywords, called tags, and it produces a series of HTML documents that describe the classes, methods, variables, and constants contained in these files.
  • Each javadoc comment is a block comment that starts with “/*” and ends with “/”, and each line between these two can begin with a single asterisk, “*”, which is ignored.
  • The block comment is assumed to
    • start with a descriptive sentence, which is followed by special lines that begin with javadoc tags.
    • A block comment that comes just before a class definition, instance variable declaration, or method definition is processed by javadoc into a comment about that class, variable, or method.
    • The primary javadoc tags that we use are the following:
      • @author text: Identifies each author (one per line) for a class.
      • @throws exceptionName description: Identifies an error condition that is signaled by this method (see Section 2.4).
      • @param parameterName description: Identifies a parameter accepted by this method.
      • @return description: Describes the return type and its range of values for a method.

Readability and Programming Conventions

  • Programs should be made easy to read and understand.
    • Use meaningful names for identifiers.
    • Use named constants or enum types instead of literals.
    • Indent statement blocks.
    • Organize each class in the following order:
        1. Constants
        1. Instance variables
        1. Constructors
        1. Methods
    • Use comments that add meaning to a program and explain ambiguous or confusing constructs.

Testing and Debugging

  • Testing: experimentally checking the correctness of a program
  • debugging: tracking the execution of a program and discovering the errors in it.

Testing

  • While verifying the correctness of a program over all possible inputs is usually infeasible, we should aim at executing the program on a representative subset of inputs.
  • every method of a program is tested at least once (method coverage).
  • each code statement should be executed at least once (statement coverage).
  • Programs often tend to fail on special cases of the input.
    • The array has zero length (no elements).
    • The array has one element.
    • All the elements of the array are the same.
    • The array is already sorted.
    • The array is reverse sorted.
    • run the program on a large collection of randomly generated inputs
  • There is a hierarchy among the classes and methods of a program induced by the caller-callee relationship.
    • a method A is above a method B in the hierarchy if A calls B.
  • There are two main testing strategies,
    • top-down testing
      • testing proceeds from the top to the bottom of the program hierarchy,
      • It is typically used in conjunction with stubbing
        • a boot-strapping technique
        • replaces a lower-level method with a stub, a replacement for the method that simulates the functionality of the original.
      • For example, if method A calls method B to get the first line of a file, when testing A we can replace B with a stub that returns a fixed string.
    • bottom-up testing
      • Bottom-up testing proceeds from lower-level methods to higher-level methods.
      • which do not invoke other methods, are tested first, followed by methods that call only bottom-level methods, and so on.
      • Similarly a class that does not depend upon any other classes can be tested before another class that depends on the former.
      • This form of testing is usually described as unit testing, as the functionality of a specific component is tested in isolation of the larger software project.
      • If used properly, this strategy better isolates the cause of errors to the component being tested, as lower-level components upon which it relies should have already been thoroughly tested.
    • automated testing
      • Java provides several forms of support for automated testing. We have already discussed how a class’s static main method can be repurposed to perform tests of the functionality of that class (as was done in Code 1.6 for the CreditCard class). Such a test can be executed by invoking the Java virtual machine directly on this secondary class, rather than on the primary class for the entire application. When Java is started on the primary class, any code within such secondary main methods will be ignored.

      • More robust support for automation of unit testing is provided by the JUnit framework, which is not part of the standard Java toolkit but freely available at www.junit.org. This framework allows the grouping of individual test cases into larger test suites, and provides support for executing those suites, and reporting or analyzing the results of those tests.
      • As software is maintained, regression testing should be performed, whereby automation is used to re-execute all previous tests to ensure that changes to the software do not introduce new bugs in previously tested components.

Debugging

  • The simplest debugging technique consists of
    • using print statements to track the values of variables during the execution of the program.
      • A problem with this approach is that eventually the print statements need to be removed or commented out, so they are not executed when the software is finally released.
    • debugger
      • better approach is to run the program within a debugger, which is a specialized environment for controlling and monitoring the execution of a program.
      • The basic functionality provided by a debugger is the insertion of breakpoints within the code. When the program is executed within the debugger, it stops at each breakpoint.
      • While the program is stopped, the current value of variables can be inspected.
      • In addition to fixed breakpoints, advanced debuggers allow specification of conditional breakpoints, which are triggered only if a given expression is satisfied.
      • The standard Java toolkit includes a basic debugger named jdb, which has a command-line interface. Most IDEs for Java programming provide advanced debugging environments with graphical user interfaces.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.