Declarations and Access Control

In Java the unit of programming is the class from which objects are eventually instantiated. An Object encapsulates data (attributes) and methods (behaviors), the implementation details are hidden within the objects themselves. See Java Object-Oriented for more information on OOP.

When you are writing Java code you are writing classes, within classes are variables and methods from which objects are eventually instantiated. How you declare a class affects your code's behavior.

Class rules

Declarations and Modifiers

Class Access

There are two types of modifiers that can be used for class declaration

Every class you declare has an access control, whether you explicity type one or not. When a class has access to another class it means he can do one of 3 things

Access means visibility, if you do not have access to a class you cannot use any methods or variables of that class.

Class Access Modifiers
Default Access When no modifier is present then default access is applied, think of default access as package access, a class with default access can be seen only by classes within the same package
Public Access When declared with public access it gives all classes from all packages access to the public class, although you still need to import the class
Class non-Access Modifers
Final Classes When used with classes this means that the class cannot be subclassed (cannot extend). Many of classes in the Java library are final classes.
Abstract Classes

An abstract class can never be instantiated, its sole purpose is to be extended (subclassed). If a single method in a class is abstract the whole class must be declared abstract. You can put non-abstract methods in a abstract class (also known as a concrete method), you will be unable to override the non-abstract method. An abstract class can extend another abstract class.

You cannot mark a class as both abstract and final as they mean the opposite, you will get a compiler error (illegal combination of modifiers).

The first concrete class to extend an abstract class must implement all abstract methods.

Abstract classes can have constructors.

Method and Variable Access

Methods and Variables within a class are collectively known as members.There are two types of modifiers that can be used for a member declaration

Every member you declare has an access control, whether you explicity type one or not. Members accessed with using the dot operator (.) must belong to the same class, the this keyword is used to reference the currently executing object.

Member Access Modifiers
Public Access When the member is declared protected it means that only the following can access the member
  • class that declared the member
  • any subclasses
  • any class thats in the same package can access it
  • any class
Protected Access When the member is declared protected it means that only the following can access the member
  • class that declared the member
  • any subclasses
  • any class thats in the same package can access it
Default Access When the member has no modifier it has default access only the following can access the member
  • class that declared the member
  • any subclasses
Private Access When the member is declared protected it means that only the following can access the member. Methods that are declared private are implicity final.
  • class that declared the member
Member non-Access Modifers
Final When used this means that the member (method or variable) cannot be overridden. A variable in a interface is implicity marked as final.
Abstract An abstract method is a method that has been declared but not implemented, in other words the method contains no functional code. The abstract method must be implemented in either the sub-class or any other subclass that has extend it.
Transient This modifier can only be applied to variables, you are telling JVM to skip this variable when you attempt to serialize the object declaring it.
Synchronized When used this means that the method can be accessed by only one thread at a time. It can only be applied to methods.
Native Indicates that a method is implemented in a platform-dependent language such as C.
Strictfp Indicates that strict floating-point will be adhered too.
Static

The best way i can describe a static variable or method is that one copy of the static member is contained in memory that allows all instances to access this copy, an example of this is like having a single counter variable that all classes can update.

There is a rule that states that a static method of a class can't access a nonstatic member or variable of its own class. Static methods are also declared final implicity.

You can Make Static:        Methods, Variables and Top-Level nested Classes
You cannot make static:    Constructors, Classes, Interfaces, Inner Classes, Inner Class Methods/Variables, Local variables

There is also no this reference when using static, also all static variables and methods are loaded first in order of appearance, you may find a simple static block of code to initialize variables or execute code.

Quick lookup table to show the access to members permitted by each modifier

Modifier
Class
Package
Subclass
World
public
Y
Y
Y
Y
protected
Y
Y
Y
N
no modifier (default)
Y
Y
N
N
private
Y
N
N
N

Now for some examples

Class Examples
Default Access class myclass { /* any code that you want */ }
Public Access

public class myclass{ /* any code that you want */ }

Note: you can have only one public class in a source file

Final public final class myclass{ /* any code that you want */ }
Abstract abstract class myclass {                  // must add the abstract keyword otherwise compiler error
   public abstract void displaySalary();  // notice no curly braces
}

Note: an abstract class sole purpose is to be extended, any one of the sub-class below the abstract class must provide the the code to the method at somepoint
Method Examples
Public Access

public void coolMethod { /* any code that you want */ }

Protected Access protected int coolMethod { /* any code that you want */ }
Default Access int coolMethod { /* any code that you want */ }

Note: no access modifier at the beginning of the statement
Private Access private String coolMethod { /* any code that you want */ }
Final public final void superCoolMethod { /* any code that you want */ }
Abstract

public abstract int coolMethod();

Note: No curly braces at the end, code for this method must be in a sub-class

Synchronized

public synchronized Record getUserInfo() { /* any code that you want */ }

Note: synchronized can never be used with abstract but you can use the other access modifiers

Static public static void myStaticMethod() { /* any code that you want */ }

Note: this method is shared by all objects within the class, there is only one copy in memory
Local Variable Examples (contained in method or code block)
Local

int bonus = 1.1;

Note: a local variable must be initialized

Final

final int bonus = 1.1;

Note: the final non-access modifier is the only option for a local variable

non-Local (instance) Variable Examples
Public public counter = 0;
Protected protected counter = 0;
Private private counter = 0;
final public final bonus = 1.5;

Note: a final variable has to be initialized, it can be initialized in the constructor of a class, also a variable in an interface is implicity marked as final whether you declare it or not
Static

public class VariableExample {
   private static int classCounter = 0;  // Will get incremented everytime a new class is created
   private int instanceCounter = 0;      // will get incremented when the method increment is called

   public void increment() {
      int localCounter = 0;
      classCounter++;
      instanceCounter++;
      localCounter++;

      System.out.println(
         "classCounter:\t\t" + classCounter + "\n" +
         "instanceCounter:\t\t" + instanceCounter + "\n" +
         "localCounter:\t\t" + localCounter + "\n"
      );
   }

   public static void main(String args[]) {
      VariableExample var1 = new VariableExample();
      VariableExample var2 = new VariableExample();
      VariableExample var3 = new VariableExample();

      var1.increment();
      var2.increment();
      var3.increment();
      var2.increment();
   }
}

# This Java program will increase the static variable classCounter everytime a new class is created, the instanceCounter will only get affect everytime we call the increment method of that instance, the localCounter gets reset everytime we call the increment method

Static initializer block

public class myTestClass {
   private static int count;                // must come before the static block to allow access

   public static void main(String[] args) {
      // nothing here
   }

   // static initializer block, this will execute even though it is not called
   static {
      System.out.println(" This is a static initializer block");
      count++;                                      // will access the above static instance variable
      System.out.println("Count: " + count);
   }

   static {
      System.out.println("You can have more than one static block");   // this will execute last
   }
}

Note: static objects are initialized in order of appearance

A example using abstraction and using the keywords this and super

Abstraction, this and super public class arrayTest {
   public static void main(String[] args) {

      test1 t1 = new test1();      // create the test1 object which extends the abstract class test2
      t1.testMethod();             // call the abstracted method
      t1.testMethod2();            // calling the normal inheriated method
   }
}

class test1 extends test2{
   int count = 10;                // instance variable

   void testMethod() {            // body of the testMethod to satisify the abstraction
      int count = 5;              // local variable

      System.out.println("local testMethod variable count = " + count);                 // local variable
      System.out.println("test1 instance variable count = " + this.count);              // instance variable
      System.out.println("test2 instance variable count = " + super.count);             // super class variable
      //System.out.println("test3 instance variable count = " + super.super.count);     // illegal super super class variable, use below
      System.out.println("test3 instance variable count = " + super.getSuperCount() );  // get super super count variable
   }
}

abstract class test2 extend test3{            // the abstract class
   int count = 15;                            // super class variable

   abstract void testMethod();                // the abstract method, must at some point provide the body

   void testMethod2(){                        // plain old method, you can mix and match abstract and non-abstract
      System.out.println("testMethod2");
   }

   int getSuperCount() {
      return super.count;                     // return super class test3 count's variable
   }
}

class test3 {
   int count = 20;                            // super super class - getting a bit silly but explains it's possible
}

Note: there is lots going on in this program buts its a good refresher and not a difficult program to work out. By the way there is no such thing as super.super you must get the super class to access the so called super.super class.

Packages

Packages are directory structures used to organize classes and interfaces, Packages provide a mechanism for software reuse, they also provide a convention for unique class names. When coding for a large project, sometimes classes can be called the same name, especially if third party developers are involved by using packages you can distinguish between class names. Normally you supply your domain name as a package location.

Package Example

package uk.co.datadisk;   // this directory structure will contain your classes.

Note:the directory structure will be uk/co/datadisk and will contain the compiled classes

Importing Classes

The import directive tells the compiler where to look for the class definitions when it comes upon a class that it cannot find in the default java.lang package.

Import examples import java.applet.*;                          // the applet class can be found in java.applet

import uk.co.datadisk.*                     // the datadisk classes can be found in uk.co.datadisk
import uk.co.datadisk.StockQuote     // import a specific class

Declaration Rules

There are a number of source file declaration rules that must be followed

Declaration Rules
Package

package uk.co.datadisk;
package com.javaguru;     // Only one package allowed, compiler error

Note: only one package declaration per source code file

Import

import java.util.*;                // Using wildcard, import all classes
import uk.co.datadisk.fooClass;    // a specific class

Note: import statements must be below package declaration and above the class declaration, you can have as many as you want. Import statements have no performance hits and they do not increase the file size.

Public Class

public class fooClass { /* any code that you want */ }

Note: you can only have one public class declaration, the order of the public class makes no difference, the filename should match the public class name. It is possible to have a file with no public classes.

Main Method

public static void main(String args[]) { ... }

Note: Main must be public and static, must have a void return and have a single String array argument (the name of the String argument does not have to be args)

Interface Implementation

When you create a interface you are defining a contract for what a class can do, without saying anything about how the class will do it. A interface is a contract. Interfaces can be implemented by any class from any inheritance tree, this lets you take radically different classes and give them a common characterstic. By defining a interface within the class you agree to provide the code for any of the interfaces methods, an interface will only have abstract methods (a abstract class can contain both abstract and nonabstract methods).

The rules of an interface are

Interface declaration public abstract interface Rollable { ... }    # should use the below declaration as the keyword abstract is                                               # redundant, but this is acceptable
public interface Rollable { ... }             # there is no need to specify the abstract keyword
Method declaration

public interface Bounceable {
   public abstract void bounce();
   void setBounceFactor();
}

Note: you do not need to specify the public abstract modifiers (now redundant), so both above methods are acceptable, all methods are public and abstract no matter what you see.

Interface Constants

public interface Bounceable {
   public final static int LOW_BOUNCE = 1;
   int HIGH_BOUNCE = 10;                      # HIGH_BOUNCE will be implicity be defined as public final static
}

Note: by putting constants in an interface you are guaranteeing that any class implementing the interface will have access to the same constant. They are also used to associate values with easy names to remember. as with the same with methods you do not need to specify the public final static modifiers (now redundant), so both above declarations are acceptable, all constants are public final static no matter what you see.

Implementing a interface

public class rubberBall implements Bounceable {
   public void bounce() { ... }               # must supply the code for the implemented interfaces method
}

Note: you are binded by a contract to supply the code for any of the interfaces methods, otherwise the compiler will complain. The signature of the method must be same as in the interface.

Also a abstract class can implement a interface but at somepoint the interface methods code must be implemented to honour the binding contract.

Implementing multiple interfaces

public class rubberBall implements Bounceable, Serializable, Runnable { ... }

Extending an interface public interface Bounceable extends Moveable { ... }

Note: an interface can itself extend another interface but never implement anything

A complete example explaining implementing an interface

Implementing an interface class arrayTest {
   public static void main(String[] args) {

      test t1 = new test();
      t1.methodA();
   }
}

class test implements inter1 {                        // enter into the interfaces contract, abstraction rules now apply

   public void methodA() {                            // method body for abstract methodA
      System.out.println("interface inter1 - methodA");
      count = 50;                                     // illegal - count has been marked public, static and final by the interface
      System.out.println("count" + count);
   }
}

interface inter1 {                                    // 100% abstract class - all methods are abstract
   int count = 20;                                    // implicity marked public, static and final - even if not stated

   public void methodA();                             // implicity marked public and abstract - even if not stated

   public void methodB() {                            // illegal - must be abstract method - no curly braces
      System.out.println("class test - methodB");
   }
}

Note: this program will not compile as there are a number of errors.