ZOFTINO.COM android and web dev tutorials

Java classes and Objects

Java is an object oriented programming language. When you create an application in java, you create classes. Classes contain fields (data) and methods (behavior). Before you learn about classes and objects in Java, see Java language basics.

Table of Contents

Declaring Classes and Member Fields & Methods

Simple class declaration starts with access modifier, which defines who can access the class, then class key word, class name and class body in {}. Class body contains fields and methods.

In eclipse, you can create class by right clicking a package in your java project, then clicking new, then clickng class and entering name, it will create the class with empty body.

Then declare fields. Fields declaration contains access modifier, data type and name of the field. Then add methods. Method declaration contains access modifier, return data type, method name, parameters and method body. Private and public are access modifiers which make fields and methods accessible only within the class and from everywhere respectively.

For example, Product class declaration is provided below. Class access modifier public makes it accessible to everyone. Class name is Product. Member variables or fields are id, name and price. Member methods are getId, getName, getPrice, SetPrice, getDiscount, etc.

public class Product {	
	
	private String id;
	private String name;
	private float price;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public float getPrice() {
		return price;
	}
	public void setPrice(float price) {
		this.price = price;
	}

	public float getDiscount(int pct) {
		return price*pct/100;
	}
} 

Instantiating Object

Once class declaration is done, to use or access members of a class, you need to create an object of the class. The process of creating an object is called instantiation. To create an object, you need to declare type, new operation and call constructor. The new operator allocates memory for the object, calls constructor and returns reference to the memory.

Product p = new Product();
p.getDiscount(10);

Constructors

Class declaration can contain constructors. Constructors are used to instantiate an object. Constructor declaration is similar to method declaration but without return type and class name is used as constructor name.

If no constructor is defined, compiler adds default constructor which is a no argument constructor and it calls no argument constructor of super class. If you define a constructor with arguments and compiler will not add default constructor. In this case if you need default constructor, you must define it.

 public class Coupon {	
	
	private String offer;
	private String store;
	
	public Coupon() {}
	
	public Coupon(String off, String stre) {
		offer = off;
		store = stre;
	}
	
	public String getOffer() {
		return offer;
	}
	public String getStore() {
		return store;
	}
}
 

You can create coupon object using its default or arguments constructor using new operator.

Coupon c= new Coupon(); 
Coupon c= new Coupon("up to 5o% off", "amazon"); 

If constructors of a class are declared as private, the class can’t be instantiated outside of the class. In this case, you need to provide a public static method which gives the instance of the object. One of the use cases of private constructor is to implement singleton pattern which makes sure that only one instance of a class is created in the application.

 public class Configuration {
	private String settings;
	
	private Configuration() {}
	
	public static Configuration getConfigurationObject() {
		return new Configuration();
	}

	public String getSettings() {
		return settings;
	}

	public void setSettings(String settings) {
		this.settings = settings;
	}
}

Keyword this

Keyword this refers to current object when it is used in constructor or instance method. For example, if constructor or method uses the same parameter name as the name of a member field of the class, then to assign the parameter to the member variable, you can use this to refer to the member variable.

One more use of this keyword is that when you need to call a parameter constructor from default constructor, you can use this keyword to refer to the other constructor. Both use cases of this keyword are shown in the example.

 public class Settings {

	private String backup;
	private String vibration;
	
	public Settings() {
		this("server", "alert type");
	}
	public Settings(String backup, String vibration) {
		this.backup = backup;
		this.vibration = vibration;
	}
	public void setBackup(String backup) {
		this.backup = backup;
	}
	public void setVibration(String vibration) {
		this.vibration = vibration;
	}
	
}
 

Modifiers

Modifiers define the accessibility of the class or its members. At class level, public or default (no modifier) modifiers can be used. Public classes are accessible from everywhere. Classes with no modifier are accessible within the package to which the class belongs to, these classes are called package-private classes.

public class Account {}

Package private class.

class Account {}

Accessibility of member variables and methods of the class can be specified using modifiers such as public, private, protected and no modifier. Members declared public can be accessed from everywhere, private members are accessible within the class, protected members can be accessed within the package and from subclasses which exist in any package, and no-modifier members of a class can be accessed from within the package.

In other words, members of a class with any access modifier can be accessed within the class. Except private members, all member of a class are accessible within the package. Sub classes of a class, no matter which package they are in, can access public and protected members of the class. Lastly, anyone can access public members of a class.

public class Account {

	protected String name;
	private int amount;
	public String company;
	String address;

	public Account(String nme, int amt, String comp, String add) {
		name = nme;
		amount = amt;
		company = comp;
		add = address;
	}

	protected String getName() {
		return name;
	}

	private int getAmount() {
		return amount;
	}

	public String getCompany() {
		return company;
	}
	String getAddress() {
		return address;
	}

}

For example, you can access public, protected and package-private member fields and methods from a different class as shown below. This is possible only if both classes are in the same package. If they are in different packages, Member class can’t access no-modifier members of Account object.

 public class Member {
	private Account account;
	private String joinDt;
	
	public Member() {
		account = new Account("name", 200, "xyz", "city, state");
	}
	
	public String memberAccountDetails() {
		String memDet = account.name;
		memDet = memDet + account.address;
		memDet = memDet + account.company;
		
		return memDet;
	}
} 

Member field amount of Account object can’t be accessed from Member class as it is private.

Method and Constructor Parameters

Data can be passed to methods and constructors. Declaration of the methods and constructors can contain parameters which they expect when they are called. Parameters can be of any data types including primitives such as int, float, etc and any object types such as String, Object, etc.

public class Device {
	private String name;
	private String purpose;
	
	public Device(String nme, String ppose) {
		name = nme;
		purpose = ppose;
	}

	public int doWork(int val, int val2) {
		return val*val2;
	}
}

Passing data to constructor and method.

	    Device device = new Device("calculator", "simple calculations");
	    
	    device.doWork(22,  45);

Methods and constructors can be passed arrays also.

public class Device {
	private String name;
	private String purpose;
	
	public Device(String nme, String ppose) {
		name = nme;
		purpose = ppose;
	}
	public Device(String[] fields) {
		name = fields[0];
		purpose = fields[1];
	}
	public int doWork(int[] vals) {
		return vals[0]*vals[1];
	}
}

Varargs

If there are methods in your application which can take varying number of arguments of a type, either you can use arrays or you can use varargs feature. To declare a method with varargs parameter, you need to specify parameter type, then three dots, then space and parameter name. For example, doWork method below is declared with varargs as parameter.

public class Device {
	private String name;
	private String purpose;
	
	public Device(String nme, String ppose) {
		name = nme;
		purpose = ppose;
	}
	public Device(String[] fields) {
		name = fields[0];
		purpose = fields[1];
	}
	public int doWork(int... val) {
		int result = 1;
		for(int value :  val) {
			result = result*value;
		}
		return result;
	}
}

You can pass any number of same type of arguments to the method which is declared to accept varargs as parameter. You can even pass any array as argument as shown in the example.

	    int result;
	    result = device.doWork(3,  6);
	    System.out.println("two args result "+result);
	    
	    result = device.doWork(2, 3, 4, 2);
	    System.out.println("two args result "+result);
	    
	    int[] values = {2, 3, 5};
	    result = device.doWork(values);
	    System.out.println("two args result "+result);

Output:

two args result 18
two args result 48
two args result 30

Difference between Primitive and Reference Type Parameters

When an argument of primitive type is passed to a method, a copy of the value is passed an argument to it. If the method modifies the parameter, the change won’t be known to outside of the methods.

 	public void modifyVlaue(int val) {
		val = val* 3;
	}
		 Device device = new Device("phone", "voice only");
		 
		 int val = 5;
		 System.out.println("initial value: "+val);
		 
		 device.modifyVlaue(val);
		 System.out.println("vale after method call: "+val);

Change made by the method to the parameter is not visible outside the method.

initial value: 5
vale after method call: 5

Whereas when you pass an object to a method, reference to the object is passed to the method and any changes made to the object by the method will be visible outside.

Here is a method which takes reference type as a parameter.

	public void adjustConfig(Configuration config) {
		config.setSettings("my phone setting");
	}

Here is the program which passes Configuration object to the method.

	    Device device = new Device("phone", "voice only");
	    
	    Configuration config = new Configuration("my tab settings");
	    System.out.println("initial setting: "+config.getSettings());
	    
	    device.adjustConfig(config);
	    System.out.println("settings after method call: "+config.getSettings());

Change to the parameter made in the method is visible outside of the method.

initial setting: my tab settings
settings after method call: my phone setting

Return Value from Method

A method can return to the code which called it after it completes execution by returning a value or due to exception. If a method declaration contains return type other than void, the method should return a value of the type in the end using return statement. Return type void indicates that the method doesn’t return any data.

 	public String getCompany() {
		return company;
	} 
 	public void setSettings(String settings) {
		this.settings = settings;
	} 

If return type of a method is a Class, the method can return an instance of the class or its subclass, but not super class. For example, Tablet is a subclass of Phone and Phone is a subclass of Device. Return type of method getDevice() in Play object is Phone. The method can instantiate Phone or Tablet object and return it. But it can’t return an instance of Device as it is super class of Phone.

 public class Play {
	public Phone getDevice() {
		return new Tablet();
	}
} 

If return type is an interface, the method can return any object which implements the interface.

 public class Play {
	public DeviceInterface getDevice() {
		return new Phone();
	}
} 

Class Members

We have seen declaring member fields and methods in the class and accessing them using an instance object of the class. So far, the way the fields and methods are defined makes them instance level. Java allows you to define member fields and methods as class level, meaning to access the members you don’t need to instantiate an object of the class. To make fields and methods class level members, you need to use static keyword as shown below. Here is a class with static and non static members.

 public class Ticket {
	
	private static int counter;
	private String name;
	
	public static int getCounter() {
		return counter;
	}
	public static void setCounter(int counter) {
		Ticket.counter = counter;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

}
 

Accessing static and non static members.

 		int counter = Ticket.getCounter();
		System.out.println("value init : "+counter);
		counter = counter+1;
		
		Ticket.setCounter(counter);
		System.out.println("value after change : "+Ticket.getCounter());
		
		
		Ticket t = new Ticket();
		t.setName("rail"); 

Output:

 value init : 0
value after change : 1 

Instance member can access class member directly, for example as shown below, non static method can use static and non static member variables. But reverse is not possible, meaning class member can’t access instance member directly. Static members can access static member directly.

 	public String getCounterName() {
		return name+" "+counter;
	} 

You can use static keyword for defining constants in combination with final keyword.

 public static final int CAPACITY = 200;

Initializing Fields

As shown in the examples, instance fields can be initialized in constructors. To initialize class fields, static initialization block can be used. You can define any number of static initialization blocks and anywhere in the body of the class. Compiler combines and places them in the order in which they are defined. The code in the static initialization block gets executed when the class is loaded in to memory.

 	private static int counter;
	
	static {
		counter = 10;
	}

There is another way of initializing static fields, which is using private static methods. Using private static method has advantage over static block. The initialization logic can be reused if it is part of private static method as shown in the example.

 public class Ticket {	
	private static int counter = initializeStaticMembers();
	
	private static int initializeStaticMembers() {
		return 10;
	}
	public static void setCounterToDefault() {
		counter = initializeStaticMembers();
	}
	public static int getCounter() {
		return counter;
	}
	public static void setCounter(int counter) {
		Ticket.counter = counter;
	}
}
 		int counter = Ticket.getCounter();
		System.out.println("value init : "+counter);
		counter = counter+1;
		
		Ticket.setCounter(counter);
		System.out.println("value after change : "+Ticket.getCounter());
		
		Ticket.setCounterToDefault();
		System.out.println("after reset : "+Ticket.getCounter());

Output:

 value init : 10
value after change : 11
after reset : 10

Like static initialization block to initialize static member, you can use non static block to initialize non-static members in addition to constructors. Compiler copies the code of non static block to every constructor. Non static blocks are useful, if you have multiple constructors and they share common code. You need to just define the common code in non-static block and compiler will copy it to all constructor of the class as shown in the example.

 public class Member {
	private Account account;
	private String joinDt;
	
	public Member() {
		account = new Account("name", 200, "xyz", "city, state");
	}
	public Member(String name, int amt) {
		account = new Account(name, amt, "xyz", "city, state");
	}	
	{
		Date d = new Date();
		joinDt = d.toString();
	}
	public String getJoinDt() {
		return joinDt;
	}
}
 		Member mOne = new Member();
		Member mTwo = new Member("rustes", 300);
		System.out.println("Join date fron one : "+mOne.getJoinDt());
		System.out.println("Join date fro two : "+mTwo.getJoinDt());

Output:

 Join date fron one : Mon Apr 08 14:08:05 PST 2018
Join date fro two : Mon Apr 08 14:08:05 PST 2018