UNIT4-IO, Generics, String Handling
UNIT4-IO, Generics, String Handling
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.
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.
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
➢ returns an estimate of the number of bytes that can be read from the current input
stream.
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.
The write() method is used to write the specific number of bytes to the output stream. It
does not return a value
This method writes the b.length bytes from the specified byte array to the output stream.
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.
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
ii) System.in – refers to the standard input stream (e.g., Keyboard by default)
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.
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.
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.
//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
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
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)
Example Program:
class writeDemo
{
public static void main(String args[])
{
int b;
b='A';
System.out.write(b);
System.out.write('\n');
}
}
Output:
A
Syntax:
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.
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)
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.
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
class class_name<T>
{
class variables;
…..
class methods;
}
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.
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");
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
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.,
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.
class Solution<T>
{
T data;
public static T getData(){
return data;
}
}
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();
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
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();
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
➢ 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
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
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.
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> { // … }
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.
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);
//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.
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.
Syntax:
List<? extends Number>
where, ? is a wild card character, extends is a keyword and Number is a class present in
java.lang package.
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
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.
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
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.
String s=new String(“Welcome”) // will create a new string object in normal heap memory
For example,
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;
width=w;
height=h;
depth=d;
class toStringDemo
System.out.println(s);
Output:
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
Here, where is the index of the character that need to obtain from the given string.
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.
4.String Comparison
The String class includes a number of methods that compare strings or substrings within
strings.
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.
class equlasDemo
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:
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.
"Foobar".endsWith("bar")
and
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
String s1=”Hello”;
System.out.println(s1+”equlas”+s2+”→”+s1.equals(s2));
System.out.println(s1+”==”+s2+”→”+(s1==s2));
Output:
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:
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
5.Searching Strings
The String class provides two methods that allow to search a string for a specified character
or substring
Syntax:
int indexOf(int ch)
Syntax:
int lastIndexOf(int ch)
6.Modifying a String
1. substring() method returns a part of the string. It has two forms. The first form is
The second form of substring( ) allows you to specify both the beginning and ending index
of the substring:
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:
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
Constructor Description
StringBuffer() It creates an empty String Builder with the initial capacity of 16.
3) StringBuffer replace() method- replaces the given string from the specified beginIndex
and endIndex.
class StringBufferExample{
sb.replace(1,3,"Java");
System.out.println(sb);//prints HJavalo
Output: HJavalo
class StringBufferdemo{
System.out.println(sb);//prints Hlo
Output: Hlo
class StringBufferdemo1{
sb.reverse();
System.out.println(sb);//prints olleH
Output: olleH
class StringBufferinsertdemo{
System.out.println(sb);//prints HJavaello
Output: HJavaello
StringBuffer append() method:
class StringBufferappend{
Output:
Hello Java