You are on page 1of 13

Chapter 5:

Class as a User Defined Data Type

5.0 Introduction

In previous chapters you have seen that whenever a new object is created, always help of
a class data type and a constructor is taken. Thus a class can act like an object-creating
template or pattern maker. As a class can have a number of member data and/or functions, it
can be regarded as a composite user defined data type.

A java programmer creates software objects by taking help of either user-defined


application specific classes or pre-defined library classes. Therefore, java program involves
class definitions and creating objects out of them for computational interactions. A class can be
regarded as a user defined data type template to produce as many desired objects as required.

A class can make use of both instance and function variables of simple data types like
int, float, double, boolean, char, etc. Data values to variables of simple data types are always
passed as call-by-value method. Class type objects, being a composite (a chunk of memory
space having slots to accept different types of data values) data type, data values are passed to
different instance variable-slots and function argument slots as call-by-reference.

At times, a programmer may need to represent a simple data type as an object of its java
defined wrapper class. Such wrapping of a simple data type helps in utilizing the methods
available with the wrapper classes. So java provides wrapper class for each simple data
type. Such type wrapper classes remain defined in the java.lang package, which automatically
gets included with every java program you write. Subsequent examples will make this wrapper
conception more clear.

Java programs can make use of both user defined classes as encapsulated composite data
types as well as wrapper classes for primitive data types.

5.1 Viewing Class as a Composite User Defined Data Type

Just have a look at the template or structure of a general class type:

class < class-name> {

<data-type> instance variable1;


|
|
< data-type > instance variableN;
<return type > method1 ( parameter-list1) {
method1 body;
return .....;
}
void methodX() {
body of methodX;
}
|
|
<return type> methodZ ( parameter-listZ) {
methodZ body;
return ....;
}
}

So class is a collection of member variables of primitive and/or composite data types


and member methods or functions capable of accepting argument(s) of different primitive
and/or class types. Each method can either return a value of specified return data type or
no output value as indicated by void.

A programmer can easily handle objects created out of such a composite class structure by
specifying the class-name as a user defined data type. That is why, a class can also be
regarded as an augmentation of permissible data types.

Suppose, a class named Student with several instance variables and methods has been
defined by a programmer in a java program. S/he can create several student objects simply
by using the statements as shown below.

Student std1 = new Student();


Student std2 = new Student ();
|
|
Student stdN = new Student();

Thus Student acts as a special composite data type referring to the class structure -- Student.
Again suppose that an object of Student composite data type demands a memory space of
600 bytes during run time. For N-number of student-objects (N* 600) bytes of memory
space will be required by the program during run time if all of them are required to interact
simultaneously. Space requirements for objects can be reduced if only one copy for each
member function or method can remain stored in memory space for sharing by interacting
objects of the same class type. Of course, space for all instance variables for each interacting
object is to be provided separately. Fig-5.1 can explain the situation more clearly.

Function codes and global variables for a Class can be stored at a single sharable
memory space and separate space for each interacting object can be allotted sufficient to
store only data values of instance variables and local variables. Thus total run-time memory
requirements can somehow be reduced.

Fig- 5.1 Many Objects Sharing Functions stored at a Common Memory Space

Common Space occupied by Member Functions of the Student


Class

Values of Instance variables of several Objects created out of the same Class
Stored at different Memory Locations

Obj1 Obj2 ObjN

During creation of each individual student object, instance variables are to be initialized
with appropriate values. A constructor is employed to do that job of initialization and
allocates object-space separately.

Student () constructor function, used after the new keyword, calls the default constructor
which initializes the instance variables with null or zero values at appropriate slots. A
programmer can include one or more parameterized constructor(s) to initialize instance
variables with any desired values.

Say, a programmer decides to initialize one student object with specified name [String type]
and age [int type]. Then the constructor is to be defined explicitly within the class, which
will take the form of say ---

Student std1 = new Student(“Ajoy Roy”, 15);

Carefully study the examples of the previous chapters and realize the importance of class
definition as a special user defined data type and inclusion of constructor(s) within the
defined class itself.

5.2 Wrappers of simple data types

Please note that a concrete class [which you normally define with full implementation
codes] can be derived also from a predefined class skeleton called Abstract class. An
abstract class may contain abstract methods also. By abstraction, one means conceptual
description of any entity – like class or its methods -- without showing the inner code
details.
An abstract class stands for a super class that declares the structure of a given abstraction
without providing the actual implementation details of every method. It just gives a
generalized definition, which can be shared by all its subclasses. Each subclass can define
its own implementation details.

The abstract class Number [available within the java.lang package] is such a super
class with the help of which wrapper subclasses can be implemented for any numeric data
types -- byte, short, int, long, float and double. The Number super class has abstract
methods like –

byte byteValue()
double doubleValue()
int intValue()
boolean isNaN()
boolean isInfinite()
float floatValue()
etc....

That is, given any numeric value, doubleValue() method returns it as a double object;
intValue() returns it as an integer object, etc of the respective wrapper classes.

The Number super class has six concrete subclasses – Double, Float, Byte, Short,
Integer, Long, Double, Float, etc. Each subclass stands for a wrapper class that can wrap
(i.e. to cover) any numeric value as its object. For example, any integer string can be
wrapped as an object of wrapper class Integer, any double string can be wrapped as an object
of Double wrapper class, and so on.

Study example-5.1 to make your conception more clear about wrapper class.

// Example-5.1 A numeric string is wrapped as a Double Wrapper object

public class Wrap2Demo


{
public static void main(){
Double d1 = new Double( "31415.17622439"); //d1 becomes an object of
Double
// calling different methods of the wrapper subclass Double

System.out.println (d1 + "is not a number -->:" + d1.isNaN());


System.out.println (d1 + ": is Infinite -->:" + d1.isInfinite());
int d2 = d1.intValue();
System.out.println ("Integer value of d1 is :" + d2);
System.out.println (" Float value of d1 is : " + d1.floatValue());
}
}
If you run this program, the terminal window (Picture 5.1) will display: --

Picture 5.1

If you study example-5.1, you will see that the numeric string “31415.17622439” is
wrapped as a Double type object d1. In the Double wrapper subclass there are methods
like --- isNaN() [i.e. not a number], isInfinite(), intValue(), floatValue(), ..... , etc. Those
methods can be applied once the numeric string is converted as an object of a wrapper class.
That is the beauty of all wrapper subclasses.

Note carefully:: Double or Float ( starting with Capital letters) is a wrapper class type
but double or float is a primitive data type. Integer is a wrapper class but int is a
simple integer type.

Look at another example of wrapper subclass.

*/ Example-5.2 Converting Integer into equivalent binary, octal, hexadecimal

public class Wrap1Demo


{

public static void main() {


int number = 2005;
System.out.println(" binary equivalent of 2005 : " + Integer.toBinaryString(number));
System.out.println(" octal equivalent of 2005 : " + Integer.toOctalString(number));
System.out.println(" hexadecimal equivalent of 2005 : " +
Integer.toHexString(number));
}
}

If you run this program, the Terminal Window will show ----

Binary equivalent of 2005: 11111010101


Octal equivalent of 2005: 3725
Hexadecimal equivalent of 2005: 7d5

Just note that data conversion from one representation to another becomes so easy using
wrapper class methods.

5.2.1 Converting Numbers into numeric Strings and vice versa

Whenever you type any number on your keyboard, a string representation (ASCII code) of
that number goes into your computer. That numeric string is to be converted into equivalent
binary code for mathematical manipulation. Such conversions can be done if the help of
wrapper classes like Integer, Short, Long, Float, Double, etc can be taken. Actually, such
conversions are done by calling the appropriate methods like parseInt(), parseFloat(),
parseDouble(), etc available in the respective wrapper subclasses.

Similarly to convert a binary representation into a decimal string, use the method toString()
can be made. Further discussion and demonstration on such aspects will be made in chapter-
11, when input/output operations through console keyboard and VDU will be explained.

Boolean is a thin wrapper around boolean values --- true or false. Boolean defines
constructors like Boolean (boolean TRUE) or Boolean (String “FALSE”) . Boolean
defines methods like booleanValue(), toString(), etc.

To have a complete knowledge on java.lang and wrapper subclasses – consult the book,
Java 2: The Complete Reference, Third Edition – by P.Naughton and H. Schildt, Tata
McGraw-Hill publication.

5.2 Operations on Primitive Data Types

Whenever you declare any variable as int, float or double, that variable becomes
capable of accepting only numeric data. Java allows following operations on numeric data

+, -, *, /, %[Modulus],

++[increment], --[decrement],

+= [Addition Assignment], -= [Subtraction Assignment], *= [multiplication


assignment], /= [division assignment], %= [modulus assignment].

Char type in java is, essentially a subset of int. Therefore, all the above mentioned
operations can be performed on data declared as char type also.

5.3.1 Increment/Decrement Operator

Increment/decrement operator can be used in Prefix [++x or - - y] as well as in


Postfix [x++ or y- -] mode.
Prefix indicates “ First increase/decrease the value by 1 and then Use” it, whereas
Postfix indicates “ First Use and then increase/decrease the value by 1”.

// Example 5.3 Prefix/Postfix Increment/Decrement

public class IncreDecreDemo


{
public static void main() {
int a =10;
int b = 15;
System.out.println ("a =" + a + " b ="+ b);
System.out.println (" ++a =" + ++a);
System.out.println (" First Incremented a + b = " + (a + b));
System.out.println (" Second Incremented a +b = " + (++a + b));
}
}

If you run this program, the terminal window will show the output as given below --

a =10 b =15
++a =11
First Incremented a + b = 26
Second Incremented a + b = 27

5.3.2 Characters in Java

Java uses Unicode [16 bit code] to represent English characters like a, b, ....,
X, Y, Z, 1, 2, ...., 9, 0 etc. Unicode keeps provision of extra 8-bits that may be utilized to
accommodate codification of any language of any country. Therefore, Java characters are
16-bit long -- covering a range of values from 0 to 65536. The ASCII characters are 8-bit
long [ranging from 0 to 255 only]. Since characters, in a computer, are represented by integer
values, whatever operations are possible on integer data type can also be performed on char
data type.

Example 5.4 Use of Char Type as Integer

public class CharDemo {

public static void main() {

char ch1, ch2;


ch1 = 65;
System.out.println (" 65 represents the character: " + ch1);
ch2 = ++ch1;
System.out.println (" Next character will be: " + ch2);
}
}

The execution of this program will show the output as –


65 represent the character: A
Next character will be: B

5.3.3 Bitwise Operations

Java allows bitwise operations on int, short, char, and byte type data variables.

The bitwise operations are -- ~ [NOT], & [AND], | [OR], ^ [exclusive OR], >> [right
Shift], >>> [zero filled right Shift], << [left Shift], &= [AND assignment], |= [OR assignment],
^= [exclusive OR assignment], >>= [right Shift assignment], >>>= [zero filled right Shit
assignment] and <<= [left Shift assignment].

// Examples 5.5 BITWISE operations

public class BitOpDemo {

public static void main() {

int a = 6; // binary 0110


int b =9; // binary 1001
int c = a | b; // OR operation
int d = a & b; // AND operation
int e = a ^ b; // XOR operation
int f = ~a & b; // Complement and then AND
int g = a << 2; // left shift by 2 positions
System.out.println (" BitOR result " + c);
System.out.println (" BitAND result " + d);
System.out.println (" BitXOR result " + e);
System.out.println (" ~a & b " +f);
System.out.println (" 2 position left shift result" + g);
}
}

Verify the results you obtain after execution (as shown below) --

BitOR result 15
BitAND result 0
BitXOR result 15
~a & b 9
2 position left shift result 24
5.3.4 Relational Operations

Relational operations can be performed on numeric operands like integer, floating-


type and character types only. The outcomes of such operations give Boolean values—true
or false.
Such operations are very often used in control statements like if, if-else, etc. The
relation operators are –

= = [equal to], != [not equal to], > [greater than], < [less than], > = [greater than or
equal to], < = [less than or equal to].

Relational operators are used to compare two values. Such comparison gives
relationship between different operands or expressions. The LHS portion can be compared
with that of the RHS portion and the result returns either TRUE or FALSE according to the
relationship existing between them.

// Example-5.6 Relational Operations

public class RelatanOpDemo {

public static void main() {


int a = 15, b = 20, c =25;
System.out.println (" a > b returns: " + (a >b));
System.out.println (" a < b returns: " + (a <b));
System.out.println (" a = = c returns: " + (a = = c));
System.out.println (" b! = c returns : " + (b != c));
System.out.println (" c >= b returns: " + (c >= b));
System.out.println (" c <= a returns: " + (c <= a));
}
}

The output of this program will look like what is shown below –

a > b returns : false


a < b returns : true
a = = c returns : false
b != c returns : true
c > = b returns : true
c < = a returns : false

5.3.5 Logical Operations on Boolean Variables


The logical operations can be performed on boolean variables only. The logical
operations are –

& [AND], | [OR], ^ [XOR],


! [unary NOT],

&= [AND assignment], | = [OR assignment], ^ = [XOR assignment],


= = [Equal to], ! = [Not equal to],

?: [ Ternary if-then-else].

// Example-5.7 Logical Operations

public class LogicOpDemo {

public static void main() {


boolean a = true;
boolean b = false;
boolean c = a | b; // logical OR
boolean d = a & b; // logical AND
boolean e = a ^ b; // logical XOR
boolean f = !a; // logical NOT
System.out.println (" a | b = " + c);
System.out.println (" a & b = " + d);
System.out.println (" a ^ b = " + e);
System.out.println (" !a = " + f);
}

After running the program you will get the output ---

a | b = true
a & b = false
a ^ b = true
!a = false

The assignment operator is =

variable = expression ;
The type of the LHS variable must be compatible with the type of the expression placed
on the RHS of the assignment operator =.

The?: operator

?: operator is a special decision making operator which can control the flow of
instructions execution in a program. It will be discussed in details in chapter-6. However, to
have an idea about the ?: operator use -- its general form is shown below.

expression1 ? expression2 : expression3

– where expression1 must evaluate a boolean value. Actually if-then-else control


statement is replaced by a ternary (meaning three-way) operator which is represented by the
?: symbol. Please wait for further details until we reach chapter-6.

We will now see how expressions can be written using different operands and the
operators mentioned above.

5.3 Expressions

An expression is composed of variables, constants and operators [arithmetic/ logical]


or any combination of them and returns a value when evaluated.

For example -- (a/b –c *d), (x-y), are arithmetic expressions but (a >b) is a logical
expression. Expressions are often evaluated with assignment statement of the form

a = x –y; where the evaluated value of ( x-y) will be placed in the location
indicated by the variable a.

Note:: Every java statement must be terminated with a semi-colon.

5.4.1 Mixed Mode operations

Now suppose, the value of x is set to 3 and that of y to 6.5. So x becomes an integer
and y is set to float/double type. So the expression is of mixed type. What will be the data
type of the output a?
Java will automatically convert x to float/double type and compute the result. This
automatic conversion is known as implicit conversion.

As java provides type casting, the output of the result can be set to any specific type
using the form -- (type) expression; and the conversion then will be regarded as explicit.

// Example- 5.8 Use of Explicit Conversion


public class TypeCastDemo {
public static void main() {

// instance variables
int x = 3;
double a, y = 6.8;
a = x-y; // implicit conversion of x
System.out.println (" Integer part of a is =" + (int) a); //explicit conversion of a
}

If you run this program, you will find the output as

Integer part of a = -3

--- which confirms that the double type variable ‘a ‘ has been explicitly converted into
integer type.

5.4.1 Special Assignment Statements

We have already mentioned about Addition Assignment, Subtraction Assignment, etc.


We will see here how they can be used to write expressions in a short form.

x = x + y; .... can be written as x += y;


x = x –y; .... can be written as x - = y;
x = x * y; .... can be written as x * = y;
x = x / y; .... can be written as x / = y;
x = x % y; .... can be written as x %= y;

Such assignment statements help reducing the length of a source code.

5.4 Conclusions

This chapter gives an overview of the class as a user-defined (composite) data type,
which can be used in a program like any primitive data type. The special advantage is
-- you can create objects from a class type as many times as you need to solve a
problem using computer.

You can also borrow or reuse java’s library classes and use them in your program
to reduce software development time and complexity.

All primitive data type variables can be treated as objects of wrapper subclasses.
Such object wrapping helps calling methods supported by the wrapper classes. Use and
importance of wrapper class methods have been demonstrated citing suitable examples.
All Operations that are possible on primitive data types have been clearly stated
and demonstrated giving suitable examples wherever possible.

You might also like