0% found this document useful (0 votes)
130 views48 pages

UNIT4-IO, Generics, String Handling

Anna University Regulation 2021 Unit 4- I/O, Generics, String Handling CS3391/OOPS B.Tech IT/II Year/III Semester Reference: NPTEL/ Programming in Java javatpoint.com Herbert Schildt, Java The Complete Reference Herbert Schildt, Introducing JavaFX 8 Programming

Uploaded by

Sakkaravarthi S
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
130 views48 pages

UNIT4-IO, Generics, String Handling

Anna University Regulation 2021 Unit 4- I/O, Generics, String Handling CS3391/OOPS B.Tech IT/II Year/III Semester Reference: NPTEL/ Programming in Java javatpoint.com Herbert Schildt, Java The Complete Reference Herbert Schildt, Introducing JavaFX 8 Programming

Uploaded by

Sakkaravarthi S
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 48

RAMCO INSTITUTE OF TECHNOLOGY

Department of Information Technology


Academic Year: 2023 – 2024 (Odd Semester)

CS3391 & Object-Oriented Programming

Unit IV – I/O, GENERICS, STRING HANDLING 9

I/O Basics- Reading and Writing Console I/O-Reading and Writing Files. Generics: Generic
Programming- Generic classes-Generic Methods- Bounded Types- Restrictions and Limitations.
Strings: Basic String class, methods and String Buffer class.

I/O BASICS:

Java I/O (Input and Output) is used to process the input and produce the output. Java uses
the concept of a stream to make I/O operation fast.

Stream: Flow of data from source to destination sequentially is called Stream. During
program execution, the input flows from file or keyboard or mouse to program and output data
flows from program to screen or memory etc. This type of data flows from input device to program
and from program to output device is called Stream.

Java Program perform I/O through Stream. Java has two types of streams called input
stream and output stream. An input stream refers to flow of data from data source (the source
may be a keyboard or mouse or memory or disk or network) to program, whereas output stream
refers to flow of data from program to destination (the destination may be Screen or Printer or
Memory or Disk, or Network).
The java provides java.io package which contains a large number of stream classes to
process all types of data.

➢ Byte Stream classes- provides support for handling I/O operations on bytes.
➢ Character Stream classes- provides support for handling I/O operations on
characters.

Taxonomy of Java stream classes

Byte Streams: provide a convenient means for handling input and output of bytes. For example,
Byte Streams are used for reading or writing binary data. Byte Stream class is classified into two
classes namely Input Stream class and Output Stream class.

Character Streams: Character Streams provide a convenient means for handling input and output
of characters. Character streams use Unicode and hence it can be internationalized. Character
Stream class is classified into two classes namely Reader class and Writer class.

Byte Stream: Input Stream class

Input Stream class is an abstract class which contain several subclasses to handle different
I/O devices. It is used for reading the data in the form of bytes from a file or memory etc. This
class contains number of methods to process input. Here errors may occur, hence it throws
IOException.
Hierarchical Structure of InputStream class

Methods Available in InputStream class


1. public abstract int read() throws IOException
➢ read() method- reads the next byte of data from input stream and returns the input
byte read as an int in the range of 0 to 255. Returns -1 if “end of stream” condition is
detected

➢ throws an IOException if it encounters an I/O error

2. public int read(byte[] b) throws IOException


➢ Reads the bytes from input stream and stores every byte in the buffer array. This
method returns the total number of bytes stored in the buffer array. If there is no
byte in the input stream, it returns -1 as the stream is at the end of the file.

3. public int read(byte[] b, int offset, int length) throws IOException


➢ It reads up to len bytes of data from the input stream. It returns the total number of
bytes stored in the buffer. Here the “offset” is start offset in buffer array b where the
data is written, and the “length” represents the maximum number of bytes to read.

4. public int available() throws IOException

➢ returns an estimate of the number of bytes that can be read from the current input
stream.

5. public void close() throws IOException

➢ The close() method is used to close the current input stream.


Byte Stream: Output Stream class

Output Stream class is an abstract class which contain several subclasses to handle different
I/O devices. It is used for writing the data in the form of bytes to a file or memory etc. This class
contains number of methods to process output. Here errors may occur, hence it throws
IOException.

Hierarchical Structure of Output Stream class

Methods Available in Output Stream class


1. public abstract void write(int b) throws IOException

The write() method is used to write the specific number of bytes to the output stream. It
does not return a value

2. Public void write(byte[ ] b) throws IOException

This method writes the b.length bytes from the specified byte array to the output stream.

3. Public void write(byte[ ] b ,int off ,int len) throws IOException


It writes upto len bytes of data to the output stream. Here the “off” is the start offset in buffer
array b, and the “len” represents the maximum number of bytes to be written in the output
stream.

4. public void flush() throws IOException

It flushes the current output stream and forces any buffered output to be written out.

Character Streams: Character Streams provide a convenient means for handling input and output
of characters. Character streams use Unicode and hence it can be internationalized. Character
Stream class is classified into two classes namely Reader class and Writer class.

Hierarchical Structure of Character based I/O & Character Streams

Character Stream classes is used to read and write characters and supports a number of input-
output related methods.
➢ Reader Stream classes are used to read characters from files.
➢ Writer Stream classes are used to write characters into files.
List of important tasks and their classes

The Predefined Streams:


System is a predefined class available in java.lang package. System class contains three
predefined stream variables namely in, out, and err. These fields are declared as public, static and
final within System class.

i) System.out – refers to the standard output stream ( Console by default)

ii) System.in – refers to the standard input stream (e.g., Keyboard by default)

iii) System.err – refers to the standard error stream (Console by default)

Reading and Writing Console I/O

Reading Console Input:

➢ In java, console input is accomplished by reading from System.in. To obtain a character-


based stream that is attached to the console, wrap System.in in a BufferedReader object.
BufferedReader supports a buffered input stream. A commonly used constructor is as
follows,

BufferedReader(Reader inputReader)
➢ Here, inputReader is the stream that is linked to the instance of BufferedReader that is
being created. Reader is an abstract class. one of its concrete subclasses is
InputStreamReader, which converts bytes to characters.

➢ To obtain an InputStreamReader object that is linked to System.in, the following


constructor is used

InputStreamReader(InputStream inputstream)
Because System.in refers to an object of type InputStream, it can be used for inputstream.
The following lines of code creates a BufferedReader that is connected to the keyboard.

InputStreamReader isr =new InputStreamReader(System.in);


BufferedReader br = new BufferedReader(isr);

After execution of above statements, br is a character-based stream that is linked to the


console through System.in

Reading Characters (from Console using BufferedReader)

The read() method is used to read a character from a BufferedReader.


Syntax:
int read() throws IOException

Each time that read( ) is called, it reads a character from the input stream and returns it as
an integer value. It returns –1 when an attempt is made to read at the end of the stream.

Example Java Program:

//Use a BufferedReader to read characters from the console


class BRRead
{
public static void main(String args[]) throws IOException
{
char c;
InputStreamReader isr =new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);

System.out.println(“Enter characters, ‘q’ to quit.”);

//read characters
do
{
c= (char) br.read();
System.out.println(c);
}while(c!=’q’);
}
}

Output:
Enter characters, ‘q’ to quit
123abcq
1
2
3
a
b
c
q

Reading Strings (from Console using BufferedReader)


The readLine() method which is a member of the BufferedReader class, is used to read a
string from keyboard. Its general form is

Syntax:
String readLine() throws IOException
Example Program:
//Read a string from console using a BufferedReader
import java.io.*;
class BRReadLine
{
public static void main(String args[]) throws IOException
{
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter 'stop' to quit.");
do
{
str=br.readLine();
System.out.println(str);
}while(!str.equals("stops"));
}
}

Output:

D:\javaprograms>java BRReadLine

Enter lines of text.


Enter 'stop' to quit.
hai
hai
stop
stop

Writing Console output:

The print() and println() method available in PrintStream class is used for console output.
The PrintStream class is an ouputstream derived from OutputStream class, implements the
write() method.

Syntax:
void write(int byteval)

This method writes the byte specified by byteval.

Example Program:
class writeDemo
{
public static void main(String args[])
{
int b;
b='A';
System.out.write(b);
System.out.write('\n');
}
}

Output:
A

The PrinterWriter class:


PrinterWriter is one of the character-based class used for console output.

Syntax:

PrintWriter(OutputStream outputstream, boolean flushingOn)

Here, outputStream is an object of type OutputStream, and flushingOn controls whether


Java flushes the output stream every time a println( ) method is called. If flushingOn is true,
flushing automatically takes place. If false, flushing is not automatic.

Java Program to handle console output using a PrintWriter class


import java.io.*;
public class PrintWriterDemo
{
public static void main(String args[])
{
PrintWriter pw = new PrintWriter(System.out, true);
pw.println(“This is a string”);
int i = -7;
pw.println(i);
double d= 4.5e-7;
pw.println(d);
}
}
OUTPUT:
This is a string
-7
4.5 E-7

PrinterWriter class supports the print() and println() methods. If an argument type is not a
simple type, the PrintWriter methods call the Object’s toString() method and then display
the result.

Example Java program: Getting input using DataInputStream class:


import java.io.*;
class InterestCalculator
{
public static void main(String args[])throws IOException
{
float principalAmount;
float rateofInterest;
int numberofYears=0;
DataInputStream in=new DataInputStream(System.in);
String tempString;
System.out.println("Enter Principal Amount:");
System.out.flush();
tempString=in.readLine();
principalAmount=Float.valueOf(tempString);
System.out.println("Enter Rate of Interest:");
System.out.flush();
tempString = in.readLine();
rateofInterest=Float.valueOf(tempString);
System.out.println("Enter Number of Years:");
System.out.flush();
tempString = in.readLine();
numberofYears=Integer.parseInt(tempString);
//calculate the interest
float interestTotal=(principalAmount*rateofInterest*numberofYears)/100;
System.out.println("Total Interest="+interestTotal);
}
}
Output:
D:\javaprograms>java InterestCalculator
Enter Principal Amount:
2000
Enter Rate of Interest:
2
Enter Number of Years:
2
Total Interest=80.0

Reading and Writing Files:

A file is a designated location where associated information is stored. Java provides a number of
classes and methods that can be used to create, read and write files. There are four major
classes in java for File handling namely
1. File
2. FileInputStream
3. FileOutputStream
4. RandomAccessFile
File class: is used to open a file in java. The following constructors can be used to create File
objects.
1. File myFile=new File(fileName)
2. File myFile=new File(pathName,fileName)
3. File myFile=new File(myDir,fileName)

File Input Stream class:


FileInputStream class is used for reading data from the files.
Syntax:
FileInputStream(String fileName)throws FileNotFoundException
Here, fileName specifies the name of the file to open

File Output Stream class:


FileOutputStream is used for writing data into the file.
Syntax:
FileOutputStream(String fileName) throws FileNotFoundException
Example program:Reading a File using FileInputStream
import java.io.FileInputStream;
class IOTest{
public void readFile(){
try {
//creating FileInputStream object.
FileInputStream fis = new FileInputStream("F:\\New folder\\data1.txt");
int i;
//read file.
while((i=fis.read())!=-1){
System.out.print((char)i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

public class FileInputStreamExample {


public static void main(String args[]){
//creating IOTest object.
IOTest obj = new IOTest();
//method call.
obj.readFile();
}
}

Output: java FileInputStreamExample


Welcome to Java programming

Example program: Writing a File using FileOutputStream


import java.io.FileOutputStream;
class IOTest{
String str = "Welcome to Programming World";
public void writeFile(){
try {
//Creating FileOutputStream object.
//It will create a new file before writing if not exist.
FileOutputStream fos =new FileOutputStream("F:\\New folder\\data2.txt");
byte b[]=str.getBytes();
fos.write(b);
fos.flush();
//Close file after write operation.
fos.close();
System.out.println("Contents written successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class FileOutPutStreamExample {
public static void main(String args[]){
//Creating IOTest object.
IOTest obj = new IOTest();
//method call
obj.writeFile();
}
}
Output: java FileOutPutStreamExample
Contents written succesfully

Reading the data from one file and writing it into another file:

import java.io.FileInputStream;
import java.io.FileOutputStream;
class IOTest{
public void readFile(){
try {
//Creating FileInputStream object.
FileInputStream fis = new FileInputStream("F:\\New folder\\data1.txt");
//Creating FileOutputStream object.
FileOutputStream fos = new FileOutputStream("F:\\New folder\\data7.txt");
int i;

//read file.
while((i=fis.read())!=-1){
fos.write(i);
}
System.out.println("Content writen successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ReadWriteExample {
public static void main(String args[]){
//creating IOTest object.
IOTest obj = new IOTest();
//method call.
obj.readFile();
}
}
Output: java ReadWriteExample
Content written succesfully.

File class methods:

Method Name Description Return Type

canRead() It tests whether the file is readable or not. Boolean


Method Name Description Return Type

canWrite() It tests whether the file is writable or not. Boolean

createNewFile() It creates an empty file. Boolean

delete() It deletes a file. Boolean

exists() It tests whether the file exists or not. Boolean

length() Returns the size of the file in bytes. Long

getName() Returns the name of the file. String

list() Returns an array of the files in the directory. String[]

mkdir() Creates a new directory. Boolean

getAbsolutePath() Returns the absolute pathname of the file. String

Example program:

import java.io.*;
class FileTest
{
public static void main(String args[]) throws IOException
{
File fileToCheck;
if(args.length>0)
{
for(int i=0;i<args.length;i++)
{
fileToCheck = new File(args[i]);
getPaths(fileToCheck);
getInfo(fileToCheck);
}
}
else
{
System.out.println("Usage:Java File test");
}
}
public static void getPaths(File f) throws IOException
{
System.out.println("Name:"+f.getName());
System.out.println("Path:"+f.getPath());
System.out.println("Parent:"+f.getParent());
}
public static void getInfo(File f) throws IOException
{
if(f.exists())
{
System.out.print("File exists");
System.out.println(f.canRead()? "and is readable":"");
System.out.println(f.canWrite()? "and is Writable":"");
System.out.println("File is last modified:"+f.lastModified());
System.out.println("File is"+f.length()+"bytes");
}
else
{
System.err.println("File does not exist.");
}
}
}
Output:
D:\javaprograms>java FileTest ram.txt
Name:ram.txt
Path:ram.txt
Parent:null
File existsand is readable
and is Writable
File is last modified:1690776882000
File is7bytes

Generics: Generic Programming:

Generics means parameterized types. Parameterized types are important because


it allows programmer to create classes, interfaces, and methods in which the type of data
upon which they operate is specified as a parameter. A class, interface, or method that
operates on a parameterized type is called generic, as in generic class or generic method.

A general definition of a Generic class is as follows:

class class_name<T>
{
class variables;
…..
class methods;
}

Syntax to create objects of Generic class:

generic_class_name <T> obj = new generic_class_name <T> ();

Where generic_class_name is the name of the generic class, <T> is the data type such as Integer,
String, user-defined data types, etc., passed as a parameter to the generic class and new is the
keyword used to create an object or instance of the generic class.

For example, for Integer object the declaration will be:


class_name <Integer> obj = new class_name<Integer>;

Similarly, for the String object, the declaration will be:

class_name <String> str_Obj = new class_name<String>;


An example java program for the Generic class:

class MyGenericClass<T>
{
T obj;
void add(T obj)
{
this.obj=obj;
}
T get()
{
return obj;
}
}

class GenericDemo
{
public static void main(String args[])
{
MyGenericClass<Integer> m_int=new MyGenericClass<Integer>();
m_int.add(2);
MyGenericClass<String>mstr=new MyGenericClass<String>();
mstr.add("SoftwaretestingHelp");

System.out.println("Member of MyGenericClass<Integer>:" + m_int.get());


System.out.println("Member of MyGenericClass<String>:" + mstr.get());
}
}
Output:
D:\javaprograms>javac GenericDemo.java
D:\javaprograms>java GenericDemo
Member of MyGenericClass<Integer> : 2
Member of MyGenericClass<String> : SoftwaretestingHelp
In the above program, a class MyGenericClass is a generic class. It has two methods i.e. add
and get. The method add initializes the generic object while the get methods return the object. In
the main method, two objects of type Integer and String are declared and both objects are
initialized with their respective initial values using the add method and then output the content of
these objects using the get method.

Advantages of Generic Programming:

1.Type Safety

Generics ensure Type Safety. This means that type checking is done at compile time rather
than at the run time. Thus there is no chance of getting “ClassCastException” during runtime as
correct types will be used.

import java.util.*;
class Main
{
public static void main(String[] args)
{
List mylist = new ArrayList();
mylist.add(10);
mylist.add("10");
System.out.println(mylist);
List<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add("10");// compile-time error
System.out.println(list);
}
}

Two lists—one containing generics and the other without generics—are provided in the
above program. The non-generic list lacks type safety because any element, including integers,
strings, and other types, can be added, but only the types allowed in the generic expression can be
added to the generic list. A compile-time error occurs while attempting to add an element of a
different type to the generic list. In the above program the compile-time error is flashed at the
line: list.add(“10”)
2.Code Reusability

Using generics, no need to write separate code for each data type, a single class can be
created and used for all data types

3. No need for type casting


Consider the following code,
List mylist = new ArrayList();
mylist.add("Java");
String mystr = (String) list.get(0); //typecasting required

When normal list is used, there is a need to typecast the element to its appropriate type.
Whereas in the generic list, type casting is not required. For e.g.,

List<String> list = new ArrayList<String>();


list.add("Java");
String mystr = list.get(0); // typecasting not required

Generic Classes:

A Generic class is implemented exactly like a non-generic class. The only difference is
Generic class contains type parameter (for Example T) which is specified within <> angular
brackets. There can be more than one type of parameter separated by a comma. The class which
accepts one or more type parameter is known as parameterized classes or parameterized types.
A generic class indicates that the data items or methods within it can be generalized using
the type parameter T to indicate that any type, such as an integer, character, string, double, or any
other user-defined type, may be added as a parameter in place of T.

syntax for declaring a generic class:


class class-name<type-param-list > { // … }

syntax for declaring a reference to a generic class and instance creation:

class-name<type-arg-list > var-name =new class-name<type-arg-list >(cons-arg-list);

A Generic class with Single Type Parameter:

class Solution<T>
{
T data;
public static T getData(){
return data;
}
}

A Generic class with two type Parameter:

public class Pair<K, V> {


private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey(){ return key; }
public V getValue() { return value; }
}

Example Java Program: A Simple Generic class with single parameter

// A Simple generic class.


//Here T is a type parameter that
// will be replaced by a real type
// When an object of type Gen is created

class Gen<T>
{
T ob; //declare an object of type T
//Pass the constructor a reference to
//an object of type T.
Gen(T o)
{
ob=o;
}
//Return ob
T getob()
{
return ob;
}
//show type of T
void showType()
{
System.out.println(“Type of T is”+ob.getClass().getName());
}
}
//Demonstrate the generic class
class GenDemo
{
public static void main(String args[])
{
//Create a Gen reference for Integers.
Gen<Integer> iOb;
//Create a Gen<Integer> object and assign its reference to iOb.
//Notice the use of autoboxing to encapsulate the value 88 within an Integer object.

iOb=new Gen<Interger>(88);
//show the type of data used by iOb.
iOb.showType();

//Get the value in iOb.Notice that no cast is needed


int v=iOb.getob();
System.out.println(“value:”+v);
System.out.println();
//Create a Gen object for Strings
Gen<String> strOb=new Gen<String>(“Generics Test”);
// show the type of data used by strOb
strOb.showType();
//Get the value of strOb. Again, notice that no cast is needed
String str=strOb.getob();
System.out.println(“value:”+str);
}
}

Output:
D:\javaprograms>java GenDemo
Type of T is: java.lang.Integer
value:88
Type of T is: java.lang.String
value:Generics Test

Example Java Program: A Simple Generic class with Two Type Parameters

//A Simple generic class with two type parameters: T and V

class TwoGen<T,V>
{
T ob1;
V ob2;
//Pass the constructor a reference to an object of Type T and an object of V.
TwoGen(T o1,V o2)
{
ob1=o1;
ob2=o2;
}
//show types of T and V.
void showTypes()
{
System.out.println(“Type of T is”+ob1.getclass().getName());
System.out.println(“Type of V is”+ob2.getclass().getName());
}

T getob1()
{
return ob1;
}
T getob2()
{
return ob2;
}
}
//Demonstrate TwoGen
class SimpGen
{
public static void main(String args[])
{
TwoGen<Integer,String> tgObj = new TwoGen<Integer,String>(88,”Generics”);
//Show the types
tgObj.showTypes();

//Obtain and Show values

int val=tgObj.getob1();
System.out.println(“value:”+v);
String str=tgObj.getob2();
System.out.println(“value:”+str);
}
}
Output:

D:\javaprograms>java SimpGen
Type of T isjava.lang.Integer
Type of V isjava.lang.String
value:88
value:Generics

Generic Methods:

A Generic method is a method that can accept argument of different types. The scope of
arguments is limited to the method where it is declared and allows static as well as non-static
methods

Properties of Generic Method:

➢ Generic Method have a type parameter specified within <> angular bracket before
the return type of the method declaration

➢ Generic methods can have different type parameters separated by commas in the
method signature

Benefits of Generic Method:

➢ Allow for more flexible and reusable code


➢ Type-Safety

Syntax of a Generic Method:

public <T> void methodName(T parameter)


{
// method body
}
Here, the <T> indicates that the method is generic and the type parameter T can be replaced with
any type when the method is called. The void keyword indicates that the method does not return a
value.

The following program shows the implementation of the Generic method “printGenericArray”.
Here two calls are made to the Generic method, first time with <Integer> type and then with
<String> type.
Generic Method: Example Program

public class GenericMethoddemo {


public static < T > void printGenericArray(T[] items) {
for ( T item : items){
System.out.print(item + " ");
}
System.out.println();
}
public static void main( String args[] )
{
Integer[] int_Array = { 1, 3, 5, 7, 9, 11 };
Character[] char_Array = { 'J', 'A', 'V', 'A', 'T','U','T','O','R','I','A', 'L','S' };

System.out.println( "Integer Array contents:" );


printGenericArray(int_Array );

System.out.println( "Character Array contents:" );


printGenericArray(char_Array );
}
}

Output:
D:\javaprograms>java GenericMethoddemo
Integer Array contents:
1 3 5 7 9 11
Character Array contents:
JAVATUTORIALS

Generic Constructors:

Constructors can be generic even if the constructed class is not generic. These constructors
at least have one parameter, which is of generic type.

Example Program: Generic Constructor


//Use a generic constructor
class GenCons
{
private double val;
<T extends Number> GenCons(T arg)
{
val=arg.doubleValue();
}
void showval()
{
System.out.println("val:"+val);
}
}
class GenConsDemo
{
public static void main(String args[])
{
GenCons test=new GenCons(100);
GenCons test2=new GenCons(123.5F);

test.showval();
test2.showval();
}
}

Output:
D:\javaprograms>javac GenConsDemo.java

D:\javaprograms>java GenConsDemo
val:100.0
val:123.5

Generic Interfaces:

In Java, a generic interface is an interface that can work with different types of data (classes)
without specifying the actual type until it is used. It allows to create flexible and reusable
code that can be adapted to different data types without duplicating the interface's code.

Syntax:
interface interface-name<type-param-list> { // … }

Here, type-param-list is a comma-separated list of type parameters. When a generic interface


is implemented, must specify the type arguments, as shown below

class class-name<type-param-list> implements interface-name<type-arg-list>


{
//….
}
Example Program:
// Define a generics interface
interface Box<T>
{
T getValue();
void setValue(T value);
}

// Create a class that implements the generics interface


class MyBox<T> implements Box<T>
{
private T value;
@Override
public T getValue() {
return value;
}
@Override
public void setValue(T value) {
this.value = value;
}
}
public class GenericsInterfaceDemo
{
public static void main(String[] args)
{
// Create a Box for Integer values
Box<Integer> intBox = new MyBox<Integer>();
intBox.setValue(42);
System.out.println("Integer Value: " + intBox.getValue());

// Create a Box for String values


Box<String> stringBox = new MyBox<>();
stringBox.setValue("Hello, Generics!");
System.out.println("String Value: " + stringBox.getValue());
}
}
Output:
D:\javaprograms>java GenericsInterfaceDemo
Integer Value:42
String Value: Hello, Generics!
Bounded Types:

Bounde type typically refers to a feature that allows to restrict the range of types that can
be used as type parameters in a generic class or method. Bounded types helps to provide
additional compile-time safety and constraints on the types that can be used, making the code
more predictable and less error-prone.
Upper Bounded Type: upper bounded type, specifies that the type parameter, must be a
subtype of a particular class or interface. This means that any concrete type passed as a type
argument must be the specified class or a subclass of it. The upper bounded type is denoted using
the extends keyword.
Syntax for upper bound type:
<T extends superclass>
This specifies that T can only be replaced by superclass or subclasses of superclass. Thus,
superclass defines an inclusive, upper limit.

Example Program: Upper bound type

//The type argument for T must be either Number


// or a class derived from Number.
class Stats<T extends Number>
{
T[] nums; //array of Number or subclass

// Pass the constructor a reference to an array of type Number or subclass.


Stats(T[] o)
{
nums=o;
}
//Return type double in all cases.
double average()
{
double sum=0.0;
for(int i=0;i<nums.length;i++)
{
sum=sum+nums[i].doubleValue();
}
return sum/nums.length;
}
}
//Demonstrate Stats.

class BoundsDemo
{
public static void main(String args[])
{
Integer inum[]={1,2,3,4,5};
Stats<Integer> iob = new Stats<Integer>(inum);
double v=iob.average();
System.out.println("iob average is"+v);

Double dnums[]={1.1,2.2,3.3,4.4,5.5};
Stats<Double> dob = new Stats<Double>(dnums);
double w=dob.average();
System.out.println("dob average is"+w);

//This won't compile because String is not a subclass of Number.


//String strs[]={"1,"2","3","4","5"};
//Stats<String> strob=new Stats<String>(strs);

//double x=strob.average();
//System.out.println("strob average is"+v);
}
}
Output:
D:\javaprograms>javac BoundsDemo.java
D:\javaprograms>java BoundsDemo
iob average is3.0
dob average is3.3

Lower Bounded Type: lower bounded type specifies that the type parameter must be a supertype
of a particular class or interface. This feature allows to work with types that are broader in scope
than the specified class. The lower bounded type is denoted using the super keyword.

Syntax for lower bound type:


<? super subclass >
The lower bound is denoted by the wildcard character ? followed by the keyword super and the
lower bound type.

Example Program: Lower Bounded type


import java.util.Arrays;
import java.util.List;
public class LowerBoundWildcard
{
public static void addNumbers(List<? super Integer> list)
{
for(Object n:list)
{
System.out.println(n);
}
}
public static void main(String[] args) {
List<Integer> l1=Arrays.asList(1,2,3);
System.out.println("displaying the Integer values");
addNumbers(l1);
List<Number> l2=Arrays.asList(1.0,2.0,3.0);
System.out.println("displaying the Number values");
addNumbers(l2);
}
}
Output:
displaying Integer values
1
2
3
displaying Number values
1.0
2.0
3.0

Wildcard in Java Generics:

The ?(question mark) symbol represents the wild card element. It means any type. Wild
card can be used as a type of a parameter, field, return type or local variable. However, it is not
allowed to use a wildcard as a type argument for a generic method invocation, a generic class
instance creation, or a super type.

Upper Bounded Wildcards:

The purpose of upper bounded wildcards is to decrease the restrictions on a variable. It


restricts the unknown type to be a specific type or a subtype of that type. It is used by declaring
wildcard character ("?") followed by the extends (in case of, class) or implements (in case of,
interface) keyword, followed by its upper bound.

Syntax:
List<? extends Number>
where, ? is a wild card character, extends is a keyword and Number is a class present in
java.lang package.

Example of Upper Bound Wildcard:


import java.util.ArrayList;
public class UpperBoundWildcard {
private static Double add(ArrayList<? extends Number> num) {
double sum=0.0;

for(Number n:num)
{
sum = sum+n.doubleValue();
}
return sum;
}
public static void main(String[] args)
{
ArrayList<Integer> l1=new ArrayList<Integer>();
l1.add(10);
l1.add(20);
System.out.println("displaying the sum= "+add(l1));
ArrayList<Double> l2=new ArrayList<Double>();
l2.add(30.0);
l2.add(40.0);
System.out.println("displaying the sum= "+add(l2));
}
}
Output:
displaying the sum=30.0
displaying the sum=70.0

Restrictions and Limitations:


1. Type Parameters can’t be instantiated
It is not possible to create an instance of a type parameter. For example,
//Can’t create an instance of T
class Gen<T>
{
T ob;
Gen()
{
ob=new T(); //Illegal
}
}

2. Restrictions on Static Members


No static member can use a type parameter declared by the enclosing class. For example
both of the static members of this class are illegal.
class Wrong<T>
{
//Wrong, no static variables of type T.
static T ob;
//Wrong, no static method can use T
static T getob()
{
return ob;
}
}
However, static generic methods declaration are allowed and can define their own type
parameters
3. Generic Array Restrictions:
There are two important generics restrictions that apply to arrays.
i). An Array whose element type is a type parameter then it cannot be instantiated
ii). An array of type-specific generic references cannot be created.

i). An Array whose element type is a type parameter then it cannot be instantiated
For Example, T vals[]; //ok
It’s valid to declare a reference to an array of type T
But, cannot instantiate an array of T, as this commented-out line attempts:
//vals=new T[10]; //can’t create an array of T.

ii). An array of type-specific generic references cannot be created.


For example,
// Gen<Integer> gens[]=new Gen<Integer>[10]; //Wrong! won’t compile
However, it is allowed to create an array of references to a generic type using a wildcard
Gen<?> gens[]=new Gen<?>[10]; //ok

4. Generic Exception Restrictions:


A generic class cannot extend Throwable which means that generic exception classes
cannot be created.

Strings: Basic String class


In general, string is a sequence of characters. But in Java, string is an object that represents
a sequence of characters. The java.lang.String class is used to create a string object. The Java
String is immutable which means it cannot be changed.

String Constructors:
i) The String class supports several constructors. To create an empty String, the default
constructor will be invoked. For example,
String s = new String();
will create an instance of String with no characters in it.
ii) To create a string initialized by an array of characters, the following constructor can be
used.
String(char chars[])
For example,
char chars[]={‘a’, ‘b’, ‘c’};
String s=new String(chars); //This constructor initializes s with the string
“abc”

iii) Java String provide constructor to specify a subrange of a character array as an initializer
String(char chars[],int startIndex, int numChars)
Here, startIndex specifies the index at which the subrange begins and numChars specifies
the number of characters to use.
For example,
char chars[]={‘a’,’b’,’c’,’d’,’e’,’f’};
String s=new String(chars,2,3); // This constructor initializes s with the characters cde
iV) Java allows to construct a String object that contains the same character sequence as another
String object using the following constructor.
String(String strObj)
For example:
//Construct one String from another
class MakeString
{
public static void main(String args[])
{
char c[]={‘J’,’a’,’v’,’a’};
String s1=new String(c);
String s2=new String(s1);
System.out.println(s1);
System.out.println(s2);
}
}
Output:
java
java

Creation of String object:


There are two ways to create String object:
i) By string literal
ii) By new keyword
i) By string literal
Java String literal is created by using double quotes. For example, String s=”Welcome”.
Each time when creating a string literal, the JVM checks the "string constant pool" first. If the string
already exists in the pool, a reference to the pooled instance is returned. If the string doesn't exist in
the pool, a new string instance is created and placed in the pool. For example:

String s1=”Welcome”;
String s2=”Welcome”;
In the above example, only one object will be created. Firstly, JVM will not find any string
object with the value "Welcome" in string constant pool that is why it will create a new object.
After that it will find the string with the value "Welcome" in the pool, it will not create a new object
but will return the reference to the same instance.

ii) By new keyword

String s=new String(“Welcome”) // will create a new string object in normal heap memory

String class methods in Java:


1. String Length:
The length of a string is the number of characters that it contains. The length() method is
used to compute the length of the string.

Syntax: int length();

For example,

char chars[]={‘a’, ’b’, ‘c’};

String s=new String(chars);

System.out.println(s.length());

2. String Concatenation:
Java does not allow operators to be applied to String objects except the + operator which
concatenates two strings producing a String object as the result.
String age=”9”;
String s= “He is”+age+”years old”;
System.out.println(s);
This code displays the string “He is 9 years old”.
toString() method:
toString() method is used to determine the string representation for objects of classes that
created

For Example:

class Box

double width;

double height;

double depth;

Box(double w, double h, double d)

width=w;

height=h;

depth=d;

public String toString()

return “Dimensions are”+width+”by”+depth+”by”+height+”.”;

class toStringDemo

public static void main(String args[])


{

Box b=new Box(10,12,14);

String s=”Box b:”+b; //Concatenate Box object

System.out.println(b); //convert Box to string

System.out.println(s);

Output:

Dimensions are 10.0 by 14.0 by 12.0

In the above program, Box’s toString() method is automatically invoked When a Box object
is used in a concatenation expression or in a call to println().

3.Character Extraction:

The String class provides a number of ways in which characters can be extracted
from a String object

i) charAt()- This method is used to extract a single character from a String.

Syntax: char charAt(int where)

Here, where is the index of the character that need to obtain from the given string.

For example: char ch;

ch=”abc”.charAt(1); // assigns the value b to ch.

ii) getChars()- This method is used to extract more than one character at a time

Syntax: void getChars(int sourceStart, int sourceEnd, char target[], int targetStart)

Here, sourceStart specifies the index of the beginning of the substring and sourceEnd
specifies an index that is one past the end of the desired substring. Thus the substring
contains the characters from sourceStart through sourceEnd-1. The array that will receive
the characters is specified by target. The index within target at which the substring will be
copied is passed in targetStart.
Example Program:

class getCharsDemo
{
public static void main(String args[])
{
String s=”This is a demo of the getChars method”;
int start=10;
int end=14;
char buf[]=new char[end-start];
s.getChars(start,end,buf,0);
System.out.println(buf);
}
}
Output:

demo

iii) toCharArray( )- to convert all the characters in a String object into a character array. It
returns an array of characters for the entire string.

Syntax: char[] toCharArray()

4.String Comparison

The String class includes a number of methods that compare strings or substrings within
strings.

i) equals(): method is used to compare two strings for equality.

Syntax: boolean equals(Object str)

Here, str is the String object being compared with the invoking String object. It returns true if
the strings contain the same characters in the same order, and false otherwise. The comparison
is case-sensitive.

ii) equalsIgnoreCase(): is used to perform a comparison that ignores case differences, it


considers A-Z to be the same as a-z.

Syntax: boolean equalsIgnoreCase(String str)


Here, str is the String object being compared with the invoking String object. It, too, returns true
if the strings contain the same characters in the same order,and false otherwise.

Example Program: to demonstrates equals() and equalsIgnoreCase()

class equlasDemo

public static void main(String args[])

String s1=”Hello”;

String s2=”Hello”;

String s3=”Good-bye”;

String s4=”HELLO”;

System.out.println(s1+”equals”+s2+”→”+s1.equals(s2));

System.out.println(s1+”equals”+s3+”→”+s1.equals(s3));

System.out.println(s1+”equals”+s4+”→”+s1.equals(s4));

System.out.println(s1+”equalsIgnoreCase”+s4+”→”+s1.equalsIgnoreCase(s4))
;

Output:

Hello equals Hello -> true

Hello equals Good-bye -> false

Hello equals HELLO -> false

Hello equalsIgnoreCase HELLO -> true

iii) startsWith() and endsWith()

The startsWith( ) method determines whether a given String begins with a specified
string. Conversely, endsWith( ) determines whether the String in question ends with a
specified string.

boolean startsWith(String str)

boolean endsWith(String str)


Here, str is the String being tested. If the string matches, true is returned. Otherwise,
false is returned. For example,

"Foobar".endsWith("bar")

and

"Foobar".startsWith("Foo") are both true.

iv) equals() Versus ==

equals() method is used to compare the characters inside a String object. The ==
operator compares two object references to see whether they refer to the same instance.

//equals() Vs ==
class EqualsNotEqualTo

public static void main(String args[])

String s1=”Hello”;

String s2=new String(s1);

System.out.println(s1+”equlas”+s2+”→”+s1.equals(s2));

System.out.println(s1+”==”+s2+”→”+(s1==s2));

Output:

Hello equals Hello → true

Hello == Hello→false

v) compareTo()- method compares the given string with the current string lexicographically. It
returns a positive number, negative number, or 0. It compares strings on the basis of the Unicode
value of each character in the strings.

Syntax:

int compareTo(String str)

Here, str is the String being compared with the invoking String. The result of the comparison
is returned and is interpreted as below
Value Meaning

Less than zero The invoking string is less than str.

Greater than zero The invoking string is greater than str.

Zero The two strings are equal

5.Searching Strings

The String class provides two methods that allow to search a string for a specified character
or substring

i) indexOf()- searches for the first occurrence of a character or substring

Syntax:
int indexOf(int ch)

ii) lastIndexOf()-searches for the last occurrence of a character or substring.

Syntax:
int lastIndexOf(int ch)

//Demonstrate indexOf() and lastIndexOf()


class indexOfDemo
{
public static void main(String args[])
{
String s=”Now is the time for all good men”+”to come to the aid of their country.”;
System.out.println(s);
System.out.println(“indexOf(t)=”+s.indexOf(‘t’));
System.out.println(“lastindexOf(t)=”+s.lastindexOf(‘t’));
}
}
Output:
Now is the time for all good men ”+”to come to the aid of their country.
index(t)=7
lastIndexOf(t)=65

6.Modifying a String

1. substring() method returns a part of the string. It has two forms. The first form is

syntax: String substring(int startIndex)


Here startIndex specifies the index at which the substring will begin. This form returns a
copy of the substring that begins at startIndex and runs to the end of the invoking string.

The second form of substring( ) allows you to specify both the beginning and ending index
of the substring:

String substring(int startIndex, int endIndex)

Here, startIndex specifies the beginning index, and endIndex specifies the stopping point.
The string returned contains all the characters from the beginning index, up to, but not
including, the ending index.

Example Program:

public class SubstringExample2


{
public static void main(String[] args)
{
String s1="Javatpoint";
String substr = s1.substring(0); // Starts with 0 and goes to end
System.out.println(substr);
String substr2 = s1.substring(5,10); // Starts from 5 and goes to 10
System.out.println(substr2);
}
}
Output:
javatpoint
point
2. concat() method is used to concatenate the two strings .

syntax: String concat(String str)


This method creates a new object that contains the invoking string with the contents of str
appended to the end. concat( ) performs the same function as +.
For example, String s1 = "one";
String s2 = s1.concat("two");
puts the string "onetwo" into s2. It generates the same result as the following sequence:
String s1 = "one";
String s2 = s1 + "two";

3. replace() method replaces all occurences of one character in the invoking string with
another.
Syntax: String replace(char original, char replacement)
Here, original specifies the character to be replaced by the character specified by
replacement. The resulting string is returned.
For example,
String s = "Hello".replace('l', 'w'); // puts the string "Hewwo" into s.

4. trim() method returns a copy of the invoking string from which any leading and trailing

spaces have been removed.

Syntax: String trim()

String Buffer class:


Java String Buffer class is used to create mutable (modifiable) String objects. The String
Buffer class in Java is the same as String class except it is mutable i.e. it can be changed.

Constructor Description

StringBuffer() It creates an empty String Builder with the initial capacity of 16.

StringBuffer(String str) It creates a String Buffer with the specified string.


StringBuffer(int capacity) It creates an empty String Buffer with the specified capacity as
length.

Methods available in String Buffer class:


1) StringBuffer append() method- concatenates the given argument with this string
2) StringBuffer insert() method- inserts the given string with this string at the given
position.

3) StringBuffer replace() method- replaces the given string from the specified beginIndex
and endIndex.

4) StringBuffer delete() method-deletes the string from the specified beginIndex to


endIndex.

5) StringBuffer reverse()- method reverses the current string.

StringBuffer replace() method:

class StringBufferExample{

public static void main(String args[]){

StringBuffer sb=new StringBuffer("Hello");

sb.replace(1,3,"Java");

System.out.println(sb);//prints HJavalo

Output: HJavalo

StringBuffer delete() method:

class StringBufferdemo{

public static void main(String args[]){

StringBuffer sb=new StringBuffer("Hello");


sb.delete(1,3);

System.out.println(sb);//prints Hlo

Output: Hlo

StringBuffer reverse() method:

class StringBufferdemo1{

public static void main(String args[]){

StringBuffer sb=new StringBuffer("Hello");

sb.reverse();

System.out.println(sb);//prints olleH

Output: olleH

StringBuffer insert() method:

class StringBufferinsertdemo{

public static void main(String args[]){

StringBuffer sb=new StringBuffer("Hello ");

sb.insert(1,"Java");//now original string is changed

System.out.println(sb);//prints HJavaello

Output: HJavaello
StringBuffer append() method:

class StringBufferappend{

public static void main(String args[]){

StringBuffer sb=new StringBuffer("Hello ");

sb.append("Java");//now original string is changed

System.out.println(sb);//prints Hello Java

Output:

Hello Java

You might also like