0% found this document useful (0 votes)
2 views

java Unit-1

The document provides an overview of Object-Oriented Methodology (OOM) and its principles, emphasizing the importance of objects, encapsulation, inheritance, polymorphism, and abstraction in software development. It contrasts OOM with procedural programming, highlighting the advantages and disadvantages of both paradigms. Additionally, it discusses the benefits, applications, and key themes of Object-Oriented Programming (OOP), such as modularity, code reusability, and the use of design patterns.

Uploaded by

venkatasai012345
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

java Unit-1

The document provides an overview of Object-Oriented Methodology (OOM) and its principles, emphasizing the importance of objects, encapsulation, inheritance, polymorphism, and abstraction in software development. It contrasts OOM with procedural programming, highlighting the advantages and disadvantages of both paradigms. Additionally, it discusses the benefits, applications, and key themes of Object-Oriented Programming (OOP), such as modularity, code reusability, and the use of design patterns.

Uploaded by

venkatasai012345
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 58

OOPS Through JAVA

Unit-1

Object Oriented Methodology: Introduction:


Object-Oriented Methodology (OOM) is a powerful and widely used approach in software
engineering that fundamentally transforms the way we design, model, and build software
systems. It revolves around the concept of "objects" and their interactions, enabling
developers to create more organized, modular, and maintainable code.
At its core, OOM is based on the idea that software can be modeled after real-world
entities, concepts, and their relationships. It's a departure from older procedural
programming paradigms, which focused on sequences of instructions. In OOM, the
emphasis shifts to organizing data and behavior into self-contained units known as
"objects."
An object is a self-contained instance that encapsulates both data and the methods
(functions or procedures) that operate on that data. These objects are created based on
"classes," which serve as blueprints for objects. A class defines the structure (attributes)
and behavior (methods) that its objects will have. This concept of bundling data and
behavior together into a single entity promotes several key principles:

1.Encapsulation
2.Inheritance:
3.Polymorphism:
4.Abstraction:
5.Modularity and Reusability:
6.Message Passing:

OOM has been instrumental in shaping the development of software systems, from
desktop applications to web services and beyond. Many modern programming
languages, such as Java, C++, Python, and C#, are designed with OOM principles in mind
Advantages and Disadvantages of Procedure Oriented Languages:
Procedural Oriented Languages are programming languages that follow a procedural
paradigm, where the program's logic is organized into a series of procedures or functions.
The procedural paradigm focuses on executing a sequence of steps to achieve a desired
outcome. Here are some advantages and disadvantages of using procedural oriented
languages:
Advantages:
1. Simplicity: Procedural languages are often simpler and easier to learn for
beginners. They typically have a straightforward control flow that involves
executing statements in a linear fashion.
2. Efficiency: Procedural languages tend to be more efficient in terms of memory
usage and execution speed compared to some other programming paradigms,
especially in scenarios where tight control over hardware resources is required.
3. Clear Control Flow: The step-by-step nature of procedural programming makes it
easy to understand the flow of execution. This can be advantageous for programs
that follow a linear sequence of operations.
4. Resource Management: Procedural languages provide more direct control over
memory and resources, allowing developers to manage memory allocation and
deallocation more efficiently.
5. Legacy Systems: Many older systems and applications were built using procedural
languages like C and Pascal. Therefore, understanding procedural programming is
essential for maintaining and updating these legacy systems.
Disadvantages:
1. Limited Abstraction: Procedural languages often lack the level of abstraction
provided by object-oriented or functional languages. This can make it harder to
model complex real-world systems.
2. Code Maintenance: As programs grow in size and complexity, maintaining
procedural code can become challenging. Adding new features or making changes
may require modifying multiple parts of the codebase.
3. Code Reusability: Procedural languages may not promote code reusability as
effectively as other paradigms like object-oriented programming. Functions in
procedural languages can often be tightly coupled to specific tasks.
4. Scalability: Scaling up procedural programs can be cumbersome due to the lack of
modular structure inherent in object-oriented languages. Changes in one part of
the code might lead to unintended consequences in other parts.
5. Readability: As procedural programs become more intricate, their linear structure
can result in code that's harder to read and understand, especially if proper
documentation is lacking.
6. Difficulty in Modeling Real-World Relationships: Procedural programming might
struggle when it comes to modeling complex relationships between entities, as the
emphasis is on procedures rather than objects and their interactions.
7. Lack of Support for Parallelism: Many modern applications require parallelism or
concurrency for optimal performance. Procedural languages might not have built-
in mechanisms to handle this efficiently.

what is Object Oriented?


Using a methodology which enables a system to be modelled as a set of objects which
can be controlled and manipulated in a modular manner. The dictionary meaning of the
object is an article or entity that exists in the real world. The meaning of oriented is
interested in a particular kind of thing or entity.

What is Object Oriented Development?


When we talk about the object oriented development, we are actually considering the
life cycle of software which include analysis, design and implementation of the software.
Object oriented development focuses on identifying and organizing the application
concept instead of the implementation of the software.
Modelling Concept:
In the early period of object oriented development, the software developers were only
emphasizing on the implementation of the software rather than emphasizing on the
analysis and design of the software. With this method, the flaws in the application were
surfaced late during the implementation which is costlier when compared to the flaws
that are surfaced earlier than the implementation.

So, the object oriented development encouraged the software developers to develop
and work on the models of the application before implementing them. A model is an
abstraction of the software, which show what the software will do after final
implementation. So, it becomes easy to identify the flaws and manipulate them at the
time of implementation
Object Oriented Methodology:
The object oriented development process encourages the graphical representation of
the object oriented concept. So, before the software developers start building an
application, they build a model of it.
The model is then analyzed to discover the inadequacy and details are added to it during
implementation. The object oriented methodology is seamless from analysis to design
to implementation. This is because the information that is appended at one stage need
not be lost at the next stage.
Object Oriented Themes:
In Object-Oriented Programming (OOP), "object-oriented themes" refer to recurring
principles, patterns, and concepts that guide the design and development of software
using the object-oriented paradigm. These themes provide a structured approach to
creating modular, maintainable, and efficient code. Here are some key object-oriented
themes:
1. Abstraction:
Focus on Essential Details: Abstract away unnecessary complexities to provide a
clear and simplified representation of real-world entities and their interactions.
Use of Abstract Classes and Interfaces: Define abstract classes and interfaces to
provide common structure and behavior, promoting code reusability and
consistent interfaces.
2. Encapsulation:
Data Hiding: Hide the internal details of objects from outside access, allowing
controlled access to object data through well-defined methods.
Information Hiding: Restrict access to the inner workings of objects, preventing
external code from relying on implementation details.
3. Inheritance and Composition:
Code Reuse: Leverage inheritance to create new classes by extending existing ones,
inheriting their attributes and methods.
Favor Composition over Inheritance: Use composition to build complex objects by
combining simpler objects, allowing for more flexible relationships and modular
design.
4. Polymorphism:
Method Overriding: Override methods in subclasses to provide specialized
implementations while maintaining a common method signature.
Dynamic Binding: Enable dynamic method resolution at runtime, allowing different
objects to respond to method calls in a context-appropriate way.
5. Modularity:
Divide and Conquer: Break down a complex system into smaller, manageable
modules (classes), each responsible for a specific task or functionality.
High Cohesion and Low Coupling: Strive for high cohesion within modules and low
coupling between modules, promoting independence and maintainability.
6. Design Patterns:
Reusable Solutions: Apply well-established design patterns to common software
design problems, enhancing code quality and maintainability.
Examples: Singleton, Factory, Observer, Strategy, Adapter, Composite, and more.

7. UML (Unified Modeling Language):


Visual Representation: Use UML diagrams to model and communicate the
structure, relationships, and behavior of software systems.
Class Diagrams, Sequence Diagrams, State Diagrams: Common UML diagrams used
in object-oriented design.
8. Testing and Test-Driven Development (TDD):
Unit Testing: Write tests to ensure that individual units (classes/methods) of code
work as expected.
TDD: Develop code by writing tests first, then writing code to satisfy those tests,
ensuring a focus on functionality and modularity.
9. Agile Development:
Iteration and Collaboration: Embrace agile methodologies to develop software
incrementally, allowing for continuous feedback and adapting to changing
requirements.

By applying these object-oriented themes, developers can create software systems that
are flexible, modular, and closely aligned with real-world concepts, leading to more
efficient development and higher-quality code.
Benefits and Application of OOPS:
Object-Oriented Programming (OOP) offers a wide range of benefits and has applications
across various domains in software development. Here are the key benefits and
applications of OOP:
Benefits:
1. Modularity and Reusability: OOP encourages the creation of modular code by
organizing it into classes and objects. These modules can be reused across different
parts of an application or in different projects, leading to reduced development
time and improved efficiency.
2. Code Organization: OOP promotes a more organized and structured approach to
coding. Classes encapsulate data and methods related to a specific entity, making
the codebase easier to manage, understand, and maintain.
3. Abstraction: Abstraction allows developers to model real-world entities and
concepts by defining their essential characteristics while hiding unnecessary
details. This results in more intuitive and readable code.
4. Encapsulation: Encapsulation ensures that the internal details of an object's
implementation are hidden from external code. This protects the integrity of the
data and allows controlled access through well-defined interfaces.
5. Inheritance: Inheritance enables code reuse by allowing new classes to inherit
properties and behaviors from existing classes. This promotes a hierarchical
organization of classes and encourages the creation of specialized classes from
general ones.
6. Polymorphism: Polymorphism enables the same method or interface to be used
for different data types, promoting flexibility and adaptability in software design. It
simplifies code maintenance and enhances extensibility.
7. Ease of Maintenance: OOP's modular and structured nature makes it easier to
locate and fix bugs or make updates to specific parts of the code without affecting
other areas.
8. Collaborative Development: OOP supports collaborative development by allowing
developers to work on different classes and objects concurrently without
interfering with each other's work.
9. Scalability: OOP provides a foundation for building scalable applications. As the
codebase grows, OOP principles make it easier to manage complexity and extend
functionality.
Applications:
1. Software Development: OOP is widely used in building various types of software
applications, including desktop applications, web applications, mobile apps, and
more.
2. Game Development: OOP is particularly useful in game development, where
objects can represent game characters, items, environments, and interactive
elements.
3. Graphic User Interfaces (GUIs): OOP is well-suited for creating GUIs due to its
ability to model and manage visual components as objects.
4. Database Management Systems: OOP can be applied to develop database
applications, where objects can represent database connections, queries, and data
entities.
5. Simulation and Modeling: OOP can be used to model and simulate complex
systems, such as physics simulations, financial models, and scientific experiments.
6. Embedded Systems: OOP principles can be applied to develop software for
embedded systems, where objects represent hardware components and their
interactions.
7. Web Development: While the web development landscape has evolved to include
more functional and modular approaches, OOP can still play a role in backend
development and complex application architecture.
8. Artificial Intelligence and Machine Learning: OOP can be applied in building
software for AI and ML applications, where objects can represent algorithms,
models, and data structures.
9. Business Applications: OOP is suitable for building business applications like
enterprise resource planning (ERP) systems, customer relationship management
(CRM) systems, and more.

Principles of OOPS:
OOPS Paradigm:
 OOP is an approach to program organization and development, which attempts to
eliminate some of the drawbacks of conventional programming methods by
incorporating the best of structured programming features with several new
concepts.
 OOP allows us to decompose a problem into number of entities called objects and
then build data and methods (functions) around these entities.
 The data of an object can be accessed only by the methods associated with the
object.
Some of the Object-Oriented Paradigm are:
 Emphasis is on data rather than procedure.
 Programs are divided into objects.
 Data Structures are designed such that they Characterize the objects.
 Methods that operate on the data of an object are tied together in the data
structure.
 Data is hidden and can not be accessed by external functions.
 Objects may communicate with each other through methods.

Classes and Methods


A class is a user-defined data type. It consists of data members and member functions,
which can be accessed and used by creating an instance of that class. It represents the set
of properties or methods that are common to all objects of one type. A class is like a
blueprint for an object. A method is a procedure associated with a class and defines the
behavior of the objects that are created from the class.
Object:
It is a basic unit of Object-Oriented Programming and represents the real-life entities. An
Object is an instance of a Class. When a class is defined, no memory is allocated but when
it is instantiated (i.e. an object is created) memory is allocated. An object has an identity,
state, and behavior. Each object contains data and code to manipulate the data. Objects
can interact without having to know details of each other’s data or code, it is sufficient to
know the type of message accepted and type of response returned by the objects.

Abstraction
Abstraction can be defined as hiding internal implementation and showing only the
required features or set of services that are offered. This is the most essential part of
Object-Oriented programming. For example, people do not think of a car as a set of tens
of thousands of individual parts. They think of it as a well-defined object with its own
unique behavior. This abstraction allows people to use a car to drive to the grocery store
without being overwhelmed by the complexity of the individual parts. They can ignore
the details of how the engine, transmission, and braking systems work. Instead, they are
free to utilize the object as a whole.

Encapsulation
Encapsulation is the mechanism that binds together code and the data it manipulates,
and keeps both safe from outside interference and misuse. One way to think about
encapsulation is as a protective wrapper that prevents the code and data from being
arbitrarily accessed by other code defined outside the wrapper. Access to the code and
data inside the wrapper is tightly controlled through a well-defined interface.

Inheritance
Inheritance is the process by which one object acquires the properties of another object.
This is important because it supports the concept of hierarchical classification. The idea
behind inheritance is that you can create new classes that are built upon existing classes.
When you inherit from an existing class, you can reuse methods and fields of the parent
class. Moreover, you can add new methods and fields in your current class also. which is
also known as a parent-child relationship.

Dynamic Binding:
In dynamic binding, the code to be executed in response to the function call is decided at
runtime. Dynamic binding means that the code associated with a given procedure call is
not known until the time of the call at run time. Dynamic Method Binding One of the main
advantages of inheritance. This feature is known as subtype polymorphism.

Message Passing:
It is a form of communication used in object-oriented programming as well as parallel
programming. Objects communicate with one another by sending and receiving
information to each other. A message for an object is a request for execution of a
procedure and therefore will invoke a function in the receiving object that generates the
desired results. Message passing involves specifying the name of the object, the name of
the function, and the information to be sent.
Object oriented thinking:
A way of viewing world – Agents:
 OOP uses an approach of treating a real world agent as an object.
 Object-oriented programming organizes a program around its data (that is,
objects) and a set of well-defined interfaces to that data.
 An object-oriented program can be characterized as data controlling access to
code by switching the controlling entity to data.

Responsibility:
 primary motivation is the need for a platform-independent (that is, architecture-
neutral) language that could be used to create software to be embedded in various
consumer electronic devices, such as microwave ovens and remote controls.
 Objects with clear responsibilities
 Each class should have a clear responsibility.
 If you can't state the purpose of a class in a single, clear sentence, then perhaps
your class structure needs some thought.
Messages:
In oops, Message passing is a way for objects to communicate with in a program. One
object can send a message to another object with specific data. Then other objects
performs the requested action based on the information provided in the message.

Methods:
 A method is a group of instructions that is given a name and can be called up at
any point in a program simply by quoting that name.
 Drawing a Triangle require draw of three straight lines. This instruction three times
to draw a simple triangle.
 We can define a method to call this instruction three times and draw the
triangle(i.e. create a method drawLine( ) to draw lines and this method is called
repeatedly to achieve the needed task)
 The idea of methods appears in all programming languages, although sometimes
it goes under the name functions and sometimes under the name procedures.
 The name methods is a throw-back to the language C++, from which Java was
developed.
 In C++, there is an object called a class which can contain methods. However,
everything in Java is enclosed within a class .so the functions within it are called
methods
Classes and instances:
Class:
 Class is blue print or an idea of an Object
 From One class any number of Instances can be created
 It is an encapsulation of attributes and methods
syntax of CLASS:
class <ClassName>
{
attributes/variables;
Constructors();
methods();
}

Instance:
Instance is an Object of a class which is an entity with its own attribute values and
methods.
Creating an Instance:

ClassName refVariable;
refVariable = new Constructor();
or
ClassName refVariable = new Constructor();
class hierarchies:
The class hierarchy is tree like. In fact, not only is the hierarchy tree-like, Java provides a
universal superclass called Object that is defined to be the root of the entire class
hierarchy. Every class that is defined in a Java program implicitly extends the class Object.
Inheritance
 Inheritance allows to reuse classes by deriving a new class from an existing one
 The existing class is called the parent class, or superclass, or base class
 The derived class is called the child class or subclass.
 The child class inherits characteristics of the parent class (i.e the child class inherits
the methods and data defined for the parent class
 Inheritance relationships are often shown graphically in a class diagram, with the
arrow pointing to the parent class
EX:
Consider two classes: Computer and Laptop
• A laptop is a kind of computer: therefore, a subclass
Method binding:
 The Objects are used to call methods.
 Method Binding is an object that can be used to call an arbitrary public method,
on an instance that is acquired by evaluatng the leading portion of a method
binding expression via a value binding.
 It is legal for a class to have two or more methods with the same name.
 Java has to be able to uniquely associate the invocation of a method with its
definition relying on the number and types of arguments.
 Therefore the same-named methods must be distinguished:
 by the number of arguments, or
 by the types of arguments
 Overloading and inheritance are two ways to implement polymorphism

Method Overriding:
 There may be some occasions when we want an object to respond to the same
method but have different behaviour when that method is called.
 That means, we should override the method defined in the superclass. This is
possible by defining a method in a sub class that has the same name, same
arguments and same return type as a method in the superclass.
 Then when that method is called, the method defined in the sub class is invoked
and executed instead of the one in the superclass. This is known as overriding.

Exceptions:
 Exception is an abnormal condition that arises in the code sequence.
 Exceptions occur during compile time or run time.
 “throwable” is the super class in exception hierarchy.
 Compile time errors occurs due to incorrect syntax.
 Run-time errors happen when
 User enters incorrect input
 Resource is not available (ex. file)
 Logic error (bug) that was not fixed
Exception classes
 In Java, exceptions are objects. When you throw an exception, you throw an
object. You can't throw just any object as an exception, however -- only those
objects whose classes descend from Throwable.
 Throwable serves as the base class for an entire family of classes, declared in
java.lang, that your program can instantiate and throw.
 Throwable has two direct subclasses, Exception and Error.
 Exceptions are thrown to signal abnormal conditions that can often be handled by
some catcher, though it's possible they may not be caught and therefore could
result in a dead thread.
 Errors are usually thrown for more serious problems, such as OutOfMemoryError,
that may not be so easy to handle. In general, code you write should throw only
exceptions, not errors.
 Errors are usually thrown by the methods of the Java API, or by the Java virtual
machine itself.
History of Java:
Java was conceived by James Gosling, Patrick Naughton, Chris Warth, Ed Frank, and Mike
Sheridan at Sun Microsystems, Inc. in 1991. It took 18 months to develop the first working
version. This language was initially called “Oak,” but was renamed “Java” in 1995.
Between the initial implementation of Oak in the fall of 1992 and the public
announcement of Java in the spring of 1995, many more people contributed to the design
and evolution of the language. Bill Joy, Arthur van Hoff, Jonathan Payne, Frank Yellin, and
Tim Lindholm were key contributors to the maturing of the original prototype.
The primary motivation was the need for a platform-independent (that is, architecture-
neutral) language that could be used to create software to be embedded in various
consumer electronic devices, such as microwave ovens and remote controls.
The trouble with C and C++ (and most other languages at the time) is that they are
designed to be compiled for a specific target. Although it is possible to compile a C++
program for just about any type of CPU, to do so requires a full C++ compiler targeted for
that CPU. The problem is that compilers are expensive and time consuming to create. An
easier—and more cost-efficient—solution was needed. In an attempt to find such a
solution, Gosling and others began work on a portable, platform-independent

Java buzzwords or Features of Java Programming Language:


The Java programming language is a high-level language that can be characterized by all
of the following buzzwords:
1. Simple
2. Object-oriented
3. Distributed
4. Interpreted
5. Robust
6. Secure
7. Architecture-neutral
8. Portable
9. High performance
10. Multithreaded
11. Dynamic
Simple
 Java was designed to be easy for a professional programmer to learn and use
effectively.
 It’s simple and easy to learn if you already know the basic concepts of Object-
Oriented Programming.
 Best of all, if you are an experienced C++ programmer, moving to Java will require
very little effort. Because Java inherits the C/C++ syntax and many of the object-
oriented features of C++, most programmers have little trouble learning Java.
 Java has removed many complicated and rarely-used features, for example,
explicit pointers, operator overloading, etc.
Object Oriented
 Java is a true object-oriented programming language.
 Almost the “Everything is an Object” paradigm. All program code and data reside
within objects and classes.
 The object model in Java is simple and easy to extend.
 One of the central issues in software development is how to reuse code. Object-
oriented programming provides great flexibility, modularity, clarity, and reusability
through encapsulation, inheritance, and polymorphism.
Distributed
 Java is designed for the distributed environment of the Internet because it handles
TCP/IP protocols.
 In fact, accessing a resource using a URL is not much different from accessing a file.
 Java is designed to create distributed applications on networks.
 Java applications can access remote objects on the Internet as easily as they can
do in the local system.
 Java also supports Remote Method Invocation (RMI). This feature enables a
program to invoke methods across a network.
Compiled and Interpreted
Usually, a computer language is either compiled or interpreted. Java combines both this
approach and makes it a two-stage system.
 Compiled: Java enables the creation of cross-platform programs by compiling them
into an intermediate representation called Java Bytecode.
 Interpreted: Bytecode is then interpreted, which generates machine code that can
be directly executed by the machine that provides a Java Virtual machine.
Robust

 It provides many features that make the program execute reliably in a variety of
environments.
 Java is a strictly typed language. It checks code both at compile time and runtime.
 Java compilers can detect many problems that would first show up at execution
time in other languages
 Java takes care of all memory management problems with garbage collection.
 Java, with the help of exception handling, captures all types of serious errors and
eliminates any risk of crashing the system.
Secure
Java implements several security mechanisms to protect your system against harm
caused by stray programs.

Architecture Neutral
 Java language and Java Virtual Machine helped in achieving the goal of “write once;
run anywhere, any time, forever.”
 Changes and upgrades in operating systems, processors and system resources will
not force any changes in Java Programs.
Portable
 Java is portable because of the Java Virtual Machine (JVM). The JVM is an abstract
computing machine that provides a runtime environment for Java programs to
execute.
 The JVM provides a consistent environment for Java programs to run on,
regardless of the underlying hardware and operating system. This means that a
Java program can be written on one device and run on any other device with a JVM
installed, without any changes or modifications.
High Performance
 Java performance is high because of the use of bytecode.
 the Java bytecode was carefully designed so that it would be easy to translate
directly into native machine code for very high performance by using a just-in-time
compiler.
Multithreaded
Java was designed to meet the real-world requirement of creating interactive, networked
programs. To accomplish this, Java supports multithreaded programming, which allows
you to write programs that do many things simultaneously.

Dynamic
Java programs carry with them substantial amounts of run-time type information that is
used to verify and resolve accesses to objects at run time. This makes it possible to
dynamically link code in a safe and expedient manner. This is crucial to the robustness of
the Java environment, in which small fragments of bytecode may be dynamically updated
on a running system.

Data types:

The Primitive Types:


Java defines eight primitive types of data: byte, short, int, long, char, float, double, and
boolean. The primitive types are also commonly referred to as simple types, and both
terms will be used in this book. These can be put in four groups:
 Integers- This group includes byte, short, int, and long, which are for wholevalued
signed numbers.
 Floating-point numbers- This group includes float and double, which represent
numbers with fractional precision.
 Characters- This group includes char, which represents symbols in a character set,
like letters and numbers.
 Boolean- This group includes boolean, which is a special type for representing
true/false values.
Integers:
Java defines four integer types: byte, short, int, and long. All of these are signed, positive
and negative values. Java does not support unsigned, positive-only integers. Many other
computer languages support both signed and unsigned integers. The width and ranges of
these integer types vary widely, as shown in this table:

byte
The smallest integer type is byte. This is a signed 8-bit type that has a range from –128 to
127. Variables of type byte are especially useful when you’re working with a stream of
data from a network or file
Byte variables are declared by use of the byte keyword. For example, the following
declares two byte variables called b and c:
byte b, c;

short
short is a signed 16-bit type. It has a range from –32,768 to 32,767. It is probably the least
used Java type. Here are some examples of short variable declarations:
short s;
short t;
int
The most commonly used integer type is int. It is a signed 32-bit type that has a range
from
–2,147,483,648 to 2,147,483,647. In addition to other uses, variables of type int are
commonly employed to control loops and to index arrays. Although you might think that
using a byte or short would be more efficient than using an int in situations in which the
larger range of an int is not needed, this may not be the case. The reason is that when
byte and short values are used in an expression, they are promoted to int when the
expression is evaluated. (Type promotion is described later in this chapter.) Therefore, int
is often the best choice when an integer is needed
long
long is a signed 64-bit type and is useful for those occasions where an int type is not large
enough to hold the desired value. The range of a long is quite large. This makes it useful
when big, whole numbers are needed. For example,
long days;
long seconds;

Floating-Point Types
Floating-point numbers, also known as real numbers, are used when evaluating
expressions that require fractional precision. For example, calculations such as square
root, or transcendentals such as sine and cosine, result in a value whose precision requires
a floating point type.
There are two kinds of floating-point types, float and double, which represent single- and
double-precision numbers, respectively. Their width and ranges are shown here:

float
The type float specifies a single-precision value that uses 32 bits of storage. Single
precision is faster on some processors and takes half as much space as double precision,
but will become imprecise when the values are either very large or very small. Variables
of type float are useful when you need a fractional component, but don’t require a large
degree of precision. For example, float can be useful when representing dollars and cents.
Here are some example float variable declarations:
float hightemp, lowtemp;
double
Double precision, as denoted by the double keyword, uses 64 bits to store a value. Double
precision is actually faster than single precision on some modern processors that have
been optimized for high-speed mathematical calculations. All transcendental math
functions, such as sin( ), cos( ), and sqrt( ), return double values. When you need to
maintain accuracy over many iterative calculations, or are manipulating large-valued
numbers, double is the best choice.
double pi, r, a;

Characters
In Java, the data type used to store characters is char. A key point to understand is that
Java uses Unicode to represent characters. Unicode defines a fully international character
set that can represent all of the characters found in all human languages.
At the time of Java’s creation, Unicode required 16 bits. Thus, in Java char is a 16-bit type.
The range of a char is 0 to 65,535. There are no negative chars. The standard set of
characters known as ASCII still ranges from 0 to 127 as always, and the extended 8-bit
character set, ISO-Latin-1, ranges from 0 to 255.
char ch1, ch2;
ch1 = 88; // code for X
ch2 = 'Y';

boolean
Java has a primitive type, called boolean, for logical values. It can have only one of two
possible values, true or false. This is the type returned by all relational operators, as in the
case of a < b. boolean is also the type required by the conditional expressions that govern
the control statements such as if and for.
boolean b;
b = false;
Variables:
The variable is the basic unit of storage in a Java program. A variable is defined by the
combination of an identifier, a type, and an optional initializer.
Declaring a Variable
In Java, all variables must be declared before they can be used. The basic form of a
variable
declaration is shown here:
type identifier [ = value ][, identifier [= value ] …];

Here, type is one of Java’s atomic types, or the name of a class or interface.The identifier
is the name of the variable. You can initialize the variable by specifying an equal sign and
a value. Keep in mind that the initialization expression must result in a value of the same
(or compatible) type as that specified for the variable. To declare more than one variable
of the specified type, use a comma-separated list.
Here are several examples of variable declarations of various types. Note that some
include an initialization.

int a, b, c; // declares three ints, a, b, and c.


int d = 3, e, f = 5; // declares three more ints, initializing // d and f.
byte z = 22; // initializes z.
double pi = 3.14159; // declares an approximation of pi.
char x = 'x'; // the variable x has the value 'x'

Dynamic Initialization
Although the preceding examples have used only constants as initializers, Java allows
variables to be initialized dynamically, using any expression valid at the time the variable
is declared.
For example, here is a short program that computes the length of the hypotenuse of a
right triangle given the lengths of its two opposing sides:
// Demonstrate dynamic initialization.
class DynInit {
public static void main(String[] args) {
double a = 3.0, b = 4.0;
// c is dynamically initialized
double c = Math.sqrt(a * a + b * b);
System.out.println("Hypotenuse is " + c);
}
}

Here, three local variables—a, b, and c—are declared. The first two, a and b, are initialized
by constants. However, c is initialized dynamically to the length of the hypotenuse (using
the Pythagorean theorem). The program uses another of Java’s built-in methods, sqrt( ),
which is a member of the Math class, to compute the square root of its argument.

The Scope and Lifetime of Variables:


Java allows variables to be declared within any block, a block is begun with an opening
curly brace and ended by a closing curly brace. A block defines a scope. Thus, each time
you start a new block, you are creating a new scope. A scope determines what objects are
visible to other parts of your program. It also determines the lifetime of those objects.

// Demonstrate block scope.


class Scope {
public static void main(String[] args) {
int x; // known to all code within main
x = 10;
if(x == 10) { // start new scope
int y = 20; // known only to this block
// x and y both known here.
System.out.println("x and y: " + x + " " + y);
x = y * 2;
}
// y = 100; // Error! y not known here
// x is still known here.
System.out.println("x is " + x);
}
}

Type conversion and casting:


Type Casting:
It is fairly common to assign a value of one type to a variable of another type. If the two
types are compatible, then Java will perform the conversion automatically. For example,
it is always possible to assign an int value to a long variable. However, not all types are
compatible, and thus, not all type conversions are implicitly allowed. For instance, there
is no automatic conversion defined from double to byte. Fortunately, it is still possible to
obtain a conversion between incompatible types. To do so, you must use a cast, which
performs an explicit conversion between incompatible types. Let’s look at both automatic
type conversions and casting.
Java’s Automatic Conversions:
When one type of data is assigned to another type of variable, an automatic type
conversion will take
place if the following two conditions are met:
• The two types are compatible.
• The destination type is larger than the source type.
When these two conditions are met, a widening conversion takes place. For example, the
int type is always large enough to hold all valid byte values, so no explicit cast statement
is required.
For widening conversions, the numeric types, including integer and floating-point types,
are compatible with each other. However, there are no automatic conversions from the
numeric types to char or boolean. Also, char and boolean are not compatible with each
other.
As mentioned earlier, Java also performs an automatic type conversion when storing a
literal integer constant into variables of type byte, short, long, or char.
Casting Incompatible Types:
Although the automatic type conversions are helpful, they will not fulfill all needs. For
example, what if you want to assign an int value to a byte variable? This conversion will
not be performed automatically, because a byte is smaller than an int. This kind of
conversion is sometimes called a narrowing conversion, since you are explicitly making
the value narrower so that it will fit into the target type. To create a conversion between
two incompatible types, you must use a cast. A cast is simply an explicit type conversion.
It has this general form:
(target-type) value
Here, target-type specifies the desired type to convert the specified value to. For example,
the following fragment casts an int to a byte. If the integer’s value is larger than the range
of a byte, it will be reduced modulo (the remainder of an integer division by the) byte’s
range.
int a;
byte b;
// …
b = (byte) a;
A different type of conversion will occur when a floating-point value is assigned to an
integer type: truncation. As you know, integers do not have fractional components. Thus,
when a floating-point value is assigned to an integer type, the fractional component is
lost.
For example, if the value 1.23 is assigned to an integer, the resulting value will simply be
1. The 0.23 will have been truncated. Of course, if the size of the whole number
component is too large to fit into the target integer type, then that value will be reduced
modulo the target type’s range.

The following program demonstrates some type conversions that require casts:
// Demonstrate casts.
class Conversion {
public static void main(String args[]) {
byte b;
int i = 257;
double d = 323.142;
System.out.println("\nConversion of int to byte.");
b = (byte) i;
System.out.println("i and b " + i + " " + b);
System.out.println("\nConversion of double to int.");
i = (int) d;
System.out.println("d and i " + d + " " + i);
System.out.println("\nConversion of double to byte.");
b = (byte) d;
System.out.println("d and b " + d + " " + b);
}
}

This program generates the following output:


Conversion of int to byte.
i and b 257 1
Conversion of double to int.
d and i 323.142 323
Conversion of double to byte.
d and b 323.142 67
Let’s look at each conversion. When the value 257 is cast into a byte variable, the result
is the remainder of the division of 257 by 256 (the range of a byte), which is 1 in this case.
When the d is converted to an int, its fractional component is lost. When d is converted
to a byte, its fractional component is lost, and the value is reduced modulo 256, which in
this case is 67.

Automatic Type Promotion in Expressions:


In addition to assignments, there is another place where certain type conversions may
occur: in expressions. To see why, consider the following. In an expression, the precision
required of an intermediate value will sometimes exceed the range of either operand. For
example, examine the following expression:
byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;
The result of the intermediate term a * b easily exceeds the range of either of its byte
operands. To handle this kind of problem, Java automatically promotes each byte, short,
or char operand to int when evaluating an expression. This means that the subexpression
a*b is performed using integers—not bytes. Thus, 2,000, the result of the intermediate
expression, 50 * 40, is legal even though a and b are both specified as type byte.
As useful as the automatic promotions are, they can cause confusing compile-time errors.
For example, this seemingly correct code causes a problem:
byte b = 50;
b = b * 2; // Error! Cannot assign an int to a byte!
The code is attempting to store 50 * 2, a perfectly valid byte value, back into a byte
variable. However, because the operands were automatically promoted to int when the
expression was evaluated, the result has also been promoted to int. Thus, the result of
the expression is now of type int, which cannot be assigned to a byte without the use of
a cast.
This is true even if, as in this particular case, the value being assigned would still fit in the
target type.In cases where you understand the consequences of overflow, you should use
an explicit cast, such as
byte b = 50;
b = (byte)(b * 2);
which yields the correct value of 100.

The Type Promotion Rules:


Java defines several type promotion rules that apply to expressions. They are as follows:
First, all byte, short, and char values are promoted to int, as just described. Then, if one
operand is a long, the whole expression is promoted to long. If one operand is a float, the
entire expression is promoted to float. If any of the operands are double, the result is
double.
The following program demonstrates how each value in the expression gets promoted to
match the second argument to each binary operator:
class Promote {
public static void main(String args[]) {
byte b = 42;
char c = 'a';
short s = 1024;
int i = 50000;
float f = 5.67f;
double d = .1234;
double result = (f * b) + (i / c) - (d * s);
System.out.println((f * b) + " + " + (i / c) + " - " + (d * s));
System.out.println("result = " + result);
}
}
Let’s look closely at the type promotions that occur in this line from the program:
double result = (f * b) + (i / c) - (d * s);
In the first subexpression, f * b, b is promoted to a float and the result of the
subexpression is float. Next, in the subexpression i/c, c is promoted to int, and the result
is of type int. Then, in d * s, the value of s is promoted to double, and the type of the
subexpression is double.
Finally, these three intermediate values, float, int, and double, are considered. The
outcome of float plus an int is a float. Then the resultant float minus the last double is
promoted to double, which is the type for the final result of the expression
Arrays:
An array is a group of like-typed variables that are referred to by a common name. Arrays
of any type can be created and may have one or more dimensions. A specific element in
an array is accessed by its index. Arrays offer a convenient means of grouping related
information.
One-Dimensional Arrays:
A one-dimensional array is, essentially, a list of like-typed variables. To create an array,
you first must create an array variable of the desired type. The general form of a one-
dimensional array declaration is
type[ ] var-name;
Here, type declares the element type (also called the base type) of the array. The element
type determines the data type of each element that comprises the array. Thus, the
element type for the array determines what type of data the array will hold. For example,
the following declares an array named month_days with the type “array of int”:
int[ ] month_days;
Although this declaration establishes the fact that month_days is an array variable, no
array actually exists. To link month_days with an actual, physical array of integers, you
must allocate one using new and assign it to month_days. new is a special operator that
allocates memory. The general form of new as it applies to one-dimensional arrays
appears as follows:
array-var = new type [size];
Here, type specifies the type of data being allocated, size specifies the number of
elements in the array, and array-var is the array variable that is linked to the array. That
is, to use new to allocate an array, you must specify the type and number of elements to
allocate. The elements in the array allocated by new will automatically be initialized to
zero (for numeric types), false(for boolean), or null (for reference types, which are
described in a later chapter). This example allocates a 12-element array of integers and
links them to month_days:
month_days = new int[12];
After this statement executes, month_days will refer to an array of 12 integers. Further,
all elements in the array will be initialized to zero
Once you have allocated an array, you can access a specific element in the array by
specifying its index within square brackets. All array indexes start at zero. For example,
this statement assigns the value 28 to the second element of month_days:
month_days[1] = 28;

An array initializer is a list of comma-separated expressions surrounded by curly braces.


The commas separate the values of the array elements. The array will automatically be
created large enough to hold the number of elements you specify in the array initializer.
There is no need to use new. For example, the following code creates an initialized array
of integers:
class AutoArray {
public static void main(String[] args) {
int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
System.out.println("April has " + month_days[3] + " days.");
}
}
Multidimensional Arrays:
In Java, multidimensional arrays are implemented as arrays of arrays. To declare a
multidimensional array variable, specify each additional index using another set of square
brackets. For example, the following declares a two-dimensional array variable called
twoD:
int[][] twoD = new int[4][5];
This allocates a 4 by 5 array and assigns it to twoD. Internally, this matrix is implemented
as an array of arrays of int.

The following program numbers each element in the array from left to right, top to
bottom, and then displays these values:
// Demonstrate a two-dimensional array.
class TwoDArray {
public static void main(String[] args) {
int[][] twoD= new int[4][5];
int i, j, k = 0;
for(i=0; i<4; i++)
for(j=0; j<5; j++) {
twoD[i][j] = k;
k++;
}
for(i=0; i<4; i++) {
for(j=0; j<5; j++)
System.out.print(twoD[i][j] + " ");
System.out.println();
}
}
}

This program generates the following output:


01234
56789
10 11 12 13 14
15 16 17 18 19

When you allocate memory for a multidimensional array, you need only specify the
memory for the first (leftmost) dimension. You can allocate the remaining dimensions
separately.

For example, this following code allocates memory for the first dimension of twoD when
it is declared. It allocates the second dimension separately.
int[][] twoD = new int[4][];
twoD[0] = new int[5];
twoD[1] = new int[5];
twoD[2] = new int[5];
twoD[3] = new int[5];

While there is no advantage to individually allocating the second dimension arrays in this
situation, there may be in others.
For example, the following program creates a two-dimensional array in which the sizes of
the second dimension are unequal:
// Manually allocate differing size second dimensions.
class TwoDAgain {
public static void main(String[] args) {
int[][] twoD = new int[4][];
twoD[0] = new int[1];
twoD[1] = new int[2];
twoD[2] = new int[3];
twoD[3] = new int[4];
int i, j, k = 0;
for(i=0; i<4; i++)
for(j=0; j<i+1; j++) {
twoD[i][j] = k;
k++;
}
for(i=0; i<4; i++) {
for(j=0; j<i+1; j++)
System.out.print(twoD[i][j] + " ");
System.out.println();
}
}
}

This program generates the following output:


0
12
345
6789
The array created by this program looks like this

The use of uneven (or irregular) multidimensional arrays may not be appropriate for many
applications, because it runs contrary to what people expect to find when a
multidimensional array is encountered. However, irregular arrays can be used effectively
in some situations.

Operators:
Java provides a rich operator environment. Most of its operators can be divided into the
following four groups: arithmetic, bitwise, relational, and logical. Java also defines some
additional operators that handle certain special situations.
Arithmetic Operators
Arithmetic operators are used in mathematical expressions in the same way that they are
used in algebra.
The following table lists the arithmetic operators:
The operands of the arithmetic operators must be of a numeric type. You cannot use them
on boolean types, but you can use them on char types, since the char type in Java is,
essentially, a subset of int.
The Basic Arithmetic Operators
The basic arithmetic operations—addition, subtraction, multiplication, and division—all
behave as you would expect for all numeric types. The unary minus operator negates its
single operand. The unary plus operator simply returns the value of its operand.
Remember that when the division operator is applied to an integer type, there will be no
fractional component attached to the result.

The Modulus Operator


The modulus operator, %, returns the remainder of a division operation. It can be applied
to floating-point types as well as integer types.
int x = 42;
int y;
y= x % 10; // value of y is 2

Java provides special operators that can be used to combine an arithmetic operation with
an assignment. As you probably know, statements like the following are quite common in
programming:
a = a + 4;
In Java, you can rewrite this statement as shown here:
a += 4;
This version uses the += compound assignment operator. Both statements perform the
same action: they increase the value of a by 4.
Here is another example,
a = a % 2;
which can be expressed as
a %= 2;
In this case, the %= obtains the remainder of a /2 and puts that result back into a. There
are compound assignment operators for all of the arithmetic, binary operators.
Thus, any statement of the form
var = var op expression;
can be rewritten as
var op= expression;

Increment and Decrement operators


The ++ and the – – are Java’s increment and decrement operators. The increment
operator increases its operand by one. The decrement operator decreases its operand by
one. For example, this statement:
x = x + 1;
can be rewritten like this by use of the increment operator:
x++;
Similarly, this statement:
x = x - 1;
is equivalent to
x--;
These operators are unique in that they can appear both in postfix form, where they
follow the operand as just shown, and prefix form, where they precede the operand.
In the prefix form, the operand is incremented or decremented before the value is
obtained for use in the expression. In postfix form, the previous value is obtained for use
in the expression, and then the operand is modified.
For example:
x = 42;
y = ++x;
In this case, y is set to 43 as you would expect, because the increment occurs before x is
assigned to y. Thus, the line y = ++x; is the equivalent of these two statements:
x = x + 1;
y = x;
However, when written like this,
x = 42;
y = x++;
the value of x is obtained before the increment operator is executed, so the value of y is
42. Of course, in both cases x is set to 43. Here, the line y = x++; is the equivalent of these
two
statements:
y = x;
x = x + 1;

The Bitwise Operators


Java defines several bitwise operators that can be applied to the integer types: long, int,
short, char, and byte. These operators act upon the individual bits of their operands. They
are summarized in the following table:
Relational Operators
The relational operators determine the relationship that one operand has to the other.
Specifically, they determine equality and ordering. The relational operators are shown
here:

The outcome of these operations is a boolean value. The relational operators are most
frequently used in the expressions that control the if statement and the various loop
statements.
The Assignment Operator
You have been using the assignment operator since Chapter 2. Now it is time to take a
formal look at it. The assignment operator is the single equal sign, =. The assignment
operator works
in Java much as it does in any other computer language. It has this general form:
var = expression;
Here, the type of var must be compatible with the type of expression
int x, y, z;
x = y = z = 100; // set x, y, and z to 100

The ? Operator
Java includes a special ternary (three-way) operator that can replace certain types of if-
then-else statements. The ? has this general form: expression1 ? expression2 :
expression3 Here, expression1 can be any expression that evaluates to a boolean value.
If expression1 is true, then expression2 is evaluated; otherwise, expression3 is evaluated.
The result of the ? operation is that of the expression evaluated. Both expression2 and
expression3 are required to return the same (or compatible) type, which can’t be void.

Operator Precedence:
Table 4-1 shows the order of precedence for Java operators, from highest to lowest.
Operators in the same row are equal in precedence. In binary operations, the order of
evaluation is left to right (except for assignment, which evaluates right to left). Although
they are technically separators, the [ ], ( ), and . can also act like operators. In that capacity,
they would have the highest precedence. Also, notice the arrow operator (->). It is used
in lambda expressions.
Using Parentheses
Parentheses raise the precedence of the operations that are inside them. This is often
necessary to obtain the result you desire. For example, consider the following expression:
a+b/3 // compute b/3 first and adds result to ‘a’
(a+b)/3 // compute a+b first and result can divisible by 3

Control Statements:
A programming language uses control statements to cause the flow of execution to
advance and branch based on changes to the state of a program. Java’s program control
statements can be put into the following categories: selection, iteration, and jump.

 Selection statements allow your program to choose different paths of execution


based upon the outcome of an expression or the state of a variable.
 Iteration statements enable program execution to repeat one or more statements
(that is, iteration statements form loops).
 Jump statements allow your program to execute in a nonlinear fashion. All of
Java’s control statements are examined here.
Java’s Selection Statements
Java supports two selection statements: if and switch. These statements allow you to
control the flow of your program’s execution based upon conditions known only during
run time.

if
The if statement is Java’s conditional branch statement. It can be used to route program
execution through two different paths.
Here is the general form of the if statement:

if (condition) statement1;
else statement2;

Here, each statement may be a single statement or a compound statement enclosed in


curly braces (that is, a block). The condition is any expression that returns a boolean value.
The else clause is optional.
The if works like this: If the condition is true, then statement1 is executed. Otherwise,
statement2 (if it exists) is executed. In no case will both statements be executed.
For example, consider the following:
int a, b;
//...
if(a < b) a = 0;
else b = 0;

Here, if a is less than b, then a is set to zero. Otherwise, b is set to zero. In no case are
they both set to zero.
Nested ifs
A nested if is an if statement that is the target of another if or else. Nested ifs are very
common in programming. When you nest ifs, the main thing to remember is that an else
statement always refers to the nearest if statement that is within the same block as the
else and that is not already associated with an else. Here is an example:
if(i == 10) {
if(j < 20) a = b;
if(k > 100) c = d; // this if is
else a = c; // associated with this else
}
else a = d; // this else refers to if(i == 10)
The if-else-if Ladder
A common programming construct that is based upon a sequence of nested ifs is the if-
elseif ladder. It looks like this:
if(condition)
statement;
else if(condition)
statement;
else if(condition)
statement;
.
.
.
else
statement;
The if statements are executed from the top down. As soon as one of the conditions
controlling the if is true, the statement associated with that if is executed, and the rest of
the ladder is bypassed. If none of the conditions is true, then the final else statement will
be executed. The final else acts as a default condition; that is, if all other conditional tests
fail, then the last else statement is performed. If there is no final else and all other
conditions are false, then no action will take place.
// Demonstrate if-else-if statements.
class IfElse {
public static void main(String[] args) {
int month = 4; // April
String season;
if(month == 12 || month == 1 || month == 2)
season = "Winter";
else if(month == 3 || month == 4 || month == 5)
season = "Spring";
else if(month == 6 || month == 7 || month == 8)
season = "Summer";
else if(month == 9 || month == 10 || month == 11)
season = "Autumn";
else
season = "Bogus Month";
System.out.println("April is in the " + season + ".");
}
}

Here is the output produced by the program:


April is in the Spring.
switch:
The switch statement is Java’s multiway branch statement. It provides an easy way to
dispatch execution to different parts of your code based on the value of an expression.
As such, it often provides a better alternative than a large series of if-else-if statements.

Here, the traditional form of the switch is examined. Here is the general form of a
traditional switch statement:

switch (expression) {
case value1:
// statement sequence
break;
case value2:
// statement sequence
break;
.
.
.

For versions of Java prior to JDK 7, expression must resolve to type byte, short, int, char,
or an enumeration. Today, expression can also be of type String. Each value specified in
the case statements must be a unique constant expression (such as a literal value).
Duplicate case values are not allowed. The type of each value must be compatible with
the type of expression.
The traditional switch statement works like this: The value of the expression is compared
with each of the values in the case statements. If a match is found, the code sequence
following that case statement is executed. If none of the constants matches the value of
the expression, then the default statement is executed. However, the default statement
is optional. If no case matches and no default is present, then no further action is taken.
The break statement is used inside the switch to terminate a statement sequence. When
a break statement is encountered, execution branches to the first line of code that follows
the entire switch statement. This has the effect of “jumping out” of the switch.

Here is a simple example that uses a switch statement:


// A simple example of the switch.
class SampleSwitch {
public static void main(String[] args) {
for(int i=0; i<6; i++)
switch(i) {
case 0:
System.out.println("i is zero.");
break;
case 1:
System.out.println("i is one.");
break;
case 2:
System.out.println("i is two.");
break;
case 3:
System.out.println("i is three.");
break;
default:
System.out.println("i is greater than 3.");
}
}
}

The output produced by this program is shown here:


i is zero.
i is one.
i is two.
i is three.
i is greater than 3.
i is greater than 3.

The break statement is optional. If you omit the break, execution will continue on into
the next case. It is sometimes desirable to have multiple cases without break statements
between them. For example, consider the following program:
// In a switch, break statements are optional.
class MissingBreak {
public static void main(String[] args) {
for(int i=0; i<12; i++)
switch(i) {
case 0:
case 1:
case 2:
case 3:
case 4:
System.out.println("i is less than 5");
break;
case 5:
case 6:
case 7:
case 8:
case 9:
System.out.println("i is less than 10");
break;
default:
System.out.println("i is 10 or more");
}
}
}
This program generates the following output:
i is less than 5
i is less than 5
i is less than 5
i is less than 5
i is less than 5
i is less than 10
i is less than 10
i is less than 10
i is less than 10
i is less than 10
i is 10 or more
i is 10 or more
As you can see, execution falls through each case until a break statement (or the end of
the switch) is reached.
Nested switch Statements
You can use a switch as part of the statement sequence of an outer switch. This is called
a nested switch. Since a switch statement defines its own block, no conflicts arise
between the case constants in the inner switch and those in the outer switch. For
example,

switch(count) {
case 1:
switch(target) { // nested switch
case 0:
System.out.println("target is zero");
break;
case 1: // no conflicts with outer switch
System.out.println("target is one");
break;
}
break;
case 2: // ...

Here, the case 1: statement in the inner switch does not conflict with the case 1:
statement in the outer switch. The count variable is compared only with the list of cases
at the outer level. If count is 1, then target is compared with the inner list cases.

Iteration Statements:
Java’s iteration statements are for, while, and do-while. These statements create what
we commonly call loops.
while
The while loop is Java’s most fundamental loop statement. It repeats a statement or block
while its controlling expression is true. Here is its general form:
while(condition) {
// body of loop
}
The condition can be any Boolean expression. The body of the loop will be executed as
long as the conditional expression is true. When condition becomes false, control passes
to the next line of code immediately following the loop. The curly braces are unnecessary
if only a single statement is being repeated.

// Demonstrate the while loop.


class While {
public static void main(String[] args) {
int n = 10;
while(n > 0) {
System.out.println("tick " + n);
n--;
}
}
}

When you run this program, it will “tick” ten times:


tick 10
tick 9
tick 8
tick 7
tick 6
tick 5
tick 4
tick 3
tick 2
tick 1

The body of the while (or any other of Java’s loops) can be empty. This is because a null
statement (one that consists only of a semicolon) is syntactically valid in Java. For
example,

consider the following program:


// The target of a loop can be empty.
class NoBody {
public static void main(String[] args) {
int i, j;
i = 100;
j = 200;
// find midpoint between i and j
while(++i < --j); // no body in this loop
System.out.println("Midpoint is " + i);
}
}

This program finds the midpoint between i and j. It generates the following output:
Midpoint is 150
do while
The do-while loop always executes its body at least once, because its conditional
expression is at the bottom of the loop. Its general form is

do {
// body of loop
} while (condition);

Each iteration of the do-while loop first executes the body of the loop and then evaluates
the conditional expression. If this expression is true, the loop will repeat. Otherwise, the
loop terminates. As with all of Java’s loops, condition must be a Boolean expression.

// Demonstrate the do-while loop.


class DoWhile {
public static void main(String[] args) {
int n = 10;
do {
System.out.println("tick " + n);
n--;
} while(n > 0);
}
}
For
Here is the general form of the traditional for statement:
for(initialization; condition; iteration) {
// body
}
If only one statement is being repeated, there is no need for the curly braces. The for loop
operates as follows. When the loop first starts, the initialization portion of the loop is
executed. Generally, this is an expression that sets the value of the loop control variable,
which acts as a counter that controls the loop. It is important to understand that the
initialization expression is executed only once. Next, condition is evaluated. This must be
a Boolean expression. This is usually an expression that increments or decrements the
loop control variable.

Here is a version of the “tick” program that uses a for loop:


// Demonstrate the for loop.
class ForTick {
public static void main(String[] args) {
int n;
for(n=10; n>0; n--)
System.out.println("tick " + n);
}
}

Using the Comma


There will be times when you will want to include more than one statement in the
initialization and iteration portions of the for loop.
// Using the comma.
class Comma {
public static void main(String[] args) {
int a, b;
for(a=1, b=4; a<b; a++, b--) {
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
}

Jump Statements
Java supports three jump statements: break, continue, and return. These statements
transfer control to another part of your program.

Using break
In Java, the break statement has three uses. First, as you have seen, it terminates a
statement sequence in a switch statement. Second, it can be used to exit a loop. Third, it
can be used as a “civilized” form of goto.

Using break to Exit a Loop


By using break, you can force immediate termination of a loop, bypassing the conditional
expression and any remaining code in the body of the loop. When a break statement is
encountered inside a loop, the loop is terminated and program control resumes at the
next statement following the loop. Here is a simple example:
// Using break to exit a loop.
class BreakLoop {
public static void main(String[] args) {
for(int i=0; i<100; i++) {
if(i == 10) break; // terminate loop if i is 10
System.out.println("i: " + i);
}
System.out.println("Loop complete.");
}
}

This program generates the following output:


i: 0
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
Loop complete.
As you can see, although the for loop is designed to run from 0 to 99, the break statement
causes it to terminate early, when i equals 10.
Using break as a Form of Goto
The ‘break’ gives you the benefits of a goto without its problems. The general form of the
labeled break statement is shown here:
break label;
Most often, label is the name of a label that identifies a block of code. This can be a stand-
alone block of code but it can also be a block that is the target of another statement.
When this form of break executes, control is transferred out of the named block. The
labeled block must enclose the break statement, but it does not need to be the
immediately enclosing block.
A label is any valid Java identifier followed by a colon. Once you have labeled a block, you
can then use this label as the target of a break statement.

// Using break as a civilized form of goto.


class Break {
public static void main(String[] args) {
boolean t = true;
first: {
second: {
third: {
System.out.println("Before the break.");
if(t) break second; // break out of second block
System.out.println("This won't execute");
}
System.out.println("This won't execute");
}
System.out.println("This is after second block.");
}
}
}

Running this program generates the following output:


Before the break.
This is after second block.

Using continue
Sometimes it is useful to force an early iteration of a loop. That is, you might want to
continue running the loop but stop processing the remainder of the code in its body for
this particular iteration. The continue statement performs such an action. In while and
do-while loops, a continue statement causes control to be transferred directly to the
conditional expression that controls the loop.

// Demonstrate continue.
class Continue {
public static void main(String[] args) {
for(int i=0; i<10; i++) {
System.out.print(i + " ");
if (i%2 == 0) continue;
System.out.println(" ");
}
}
}
This code uses the % operator to check if i is even. If it is, the loop continues without
printing a newline. Here is the output from this program:
01
23
45
67
89

return
The last control statement is return. The return statement is used to explicitly return from
a method. That is, it causes program control to transfer back to the caller of the method.
As such, it is categorized as a jump statement.
At any time in a method, the return statement can be used to cause execution to branch
back to the caller of the method. Thus, the return statement immediately terminates the
method in which it is executed.

// Demonstrate return.
class Return {
public static void main(String[] args) {
boolean t = true;
System.out.println("Before the return.");
if(t) return; // return to caller
System.out.println("This won't execute.");
}
}

The output from this program is shown here:


Before the return.

As you can see, the final println( ) statement is not executed. As soon as return is
executed, control passes back to the caller.

You might also like