Download presentation
Presentation is loading. Please wait.
1
Chapter 7: Cloning and RTTI
Java Programming - Advanced Topics
2
Objectives In this chapter you will:
Clone objects so that the result is a deep, rather than shallow, copy Use the interface Cloneable to control whether instances of a class you define ca be cloned Use the interface Cloneable to control whether instances of subclasses of your class must be, can optionally be, or cannot be cloned Determine the result of applying assignment and instanceof operators to operands of any type
3
Objectives In this chapter you will:
Investigate the class name Class, with which you can get information about a class at run time Understand why some casts between class types are safe, whereas others throw an exception, and learn how to handle this exception Use the Reflection API to get run-time information about fields, methods, and primitive types Call a method or a constructor for a class with the Reflection API
4
Cloning Objects To copy objects of reference types, you must clone the objects Cloning involves calling the method clone, which is available for all objects of reference types, including instances of classes and arrays
5
Cloning Objects
6
Cloning Objects For the reference types, you usually want to make a deep copy rather than a shallow copy of an object A shallow copy duplicates the data members of an object regardless of whether some members are object references A shallow copy makes no attempt to make duplicates of the referenced objects
7
Cloning Objects A deep copy duplicates the objects referred to by object references, and inserts a new object reference for the duplicate object into the copy The method Object.clone performs a shallow copy The Java platform includes a core interface called Cloneable for the specific purpose of indicating whether objects are cloneable
8
Making Objects Cloneable
Whether cloning works depends upon whether the class is defined to implement the core interface Cloneable If you call clone for a class that does not implement Cloneable, the exception CloneNotSupportedException is thrown The definition of clone in the Object class lists CloneNotSupportedException in its throws clause
9
Making Objects Cloneable
When you override Object.clone in your class, you have the option of removing CloneNotSupportedException from the throws clause of clone method If you call clone for an instance of a class that uses the default method Object.clone, you must take one of the following actions: Wrap a try block around the call of clone and catch the possible CloneNotSupportedException Add the CloneNotSupportedException exception to the throws clause for the method that calls clone
10
Making Objects Cloneable
The Cloneable interface is an example of a marker interface Marker interfaces have no methods The sole purpose of a marker interface is to attach a piece of type information to a class When you define a class, you can use Cloneable like an on-off switch
11
Overriding the Default Clone Method
For objects related by an inheritance hierarchy to be cloned correctly, each class in the hierarchy that has object reference fields must override clone Here are some guidelines for implementing clone: If classes outside the package are to be allowed to use the implementation of the clone method, declare the method with access specifier public When implementing clone, it is not necessary to program it to deal with fields of the primitive types
12
Overriding the Default Clone Method
Here are some guidelines for implementing clone continued: Define the clone method to copy objects for all fields that are reference objects. The only exceptions to this rule are object references for immutable objects To make sure every superclass in the hierarchy has a chance to copy the fields it defines, start your definition of clone with the following statement: super.clone( );
13
Proper Clone Method Has a Number of Notable Features
The return type is Object, because it overrides Object.clone It calls super.clone to clone the fields in the superclass Next, IntArray.clone calls the clone method for the fields a, which is an array
14
Defining Cloneable Classes
When deciding whether to implement the Cloneable interface, consider the impact on subclasses for which the class is the superclass, as well as on unrelated classes that use the class Here are five approaches you can provide: 1. All objects of the class can be cloned. The simplest option is to support cloning fully, by: Defining the class with implements Cloneable Inheriting or overriding the default clone method
15
Defining Cloneable Classes
2. Objects of the class are cloneable only if all contained objects are also cloneable Define the class with implements Cloneable Implement clone. For the fields of reference types, call the clone method of those classes 3. Objects of the class are not cloneable, but a subclass can extend the class in such a way that its objects are cloneable Omit implements Cloneable from the class definition Override or inherit the clone method
16
Defining Cloneable Classes
Although this class does not allow cloning, a subclass can implement Cloneable, inherit or override the clone method, and become fully cloneable 4. No object of the class or any class that extends the class can be cloned Omit implements Cloneable from the class definition Implement a clone method that always throws a CloneNotSupportedException object
17
Defining Cloneable Classes
5. The class is an abstract class and all subclasses are required to provide a clone method that does not throw CloneNotSupportedException Optionally add implements Cloneable for clarity Define a clone method and declare it to be abstract Omit CloneNotSupportedException from the throws clause of clone
18
Run-Time Type Information
Many programs are driven by a graphical user interface (GUI) or run in a distributed environment You may find that your class has to deal with objects for which the type is not known Use of RTTI is to access members of classes that you cannot know about when you develop your class RTTI can also be helpful in debugging the code RTTI also helps to make up for the lack of parameterized types in the Java programming language
19
Determining the Type of Objects
Built into Java is an operator, instanceof, that you can use to ask if an object is an instance of a particular class or any of its subclasses This operator is useful in situations such as the following: You are writing a method that receives an object reference, of a type such as BankAccount Syntax object_reference instanceof class_name object_reference instanceof interface_name
20
Determining the Type of Objects
Dissection The operator instanceof returns a Boolean value You can also use instanceof to ask whether the class of the object implements a particular interface The instanceof operator does not work for the primitive types If the object is an instance of a class that extends the class or implements the interfaces specified by the rightmost argument, the value returned by instanceof is true
21
Accessing Information About Classes at Run-Time
For every class and every instance of a class that a program uses, the JVM creates an object with the type Class Java creates the Class object automatically and stores in it sever facts about the class, so that you can access the information at run time You do not create Class objects, and no constructor for the class Class is available After you have a reference to a Class object, you can send messages to it to ask questions about the class that the object describes
22
Methods to Access the Class Object for a Class or an Object
Use the Object.getClass method for any object If you know the name of a class or interface, you can use a class variable that the Java programming language adds to every class automatically If you know the full name of the class or interface, call the class method Class.forName, passing the fully qualified name of the class as a String argument
23
Accessing Information About Classes at Run-Time
Purpose - The Class class provides run-time information about Java classes Methods Class forName (String classname) ClassLoader getClassLoader( ) String getName( ) Class getSuperclass( ) boolean isArray( ) boolean isInstance( Object object) boolean isInterface( ) Object newInstance( )
24
Casting Between Types Whenever you cast between types, the operation may not be safe Safe means that no information can be lost or corrupted as a result of the cast The JVM ensures that only safe casts are performed Casting from a type with a narrower range of values to one with a wider range of values, such as from a float to a double or from a subclass to its superclass, is always safe
25
Casting Between Types An unsafe cast can be from a wider type to a narrower type or between classes For example, casting from long to short or from String to Exception is unsafe In the case of primitive types, the compiler allows explicit casting as a way for indicating that a particular cast may not be safe and are aware of the potential problems You can convert from double to a float if you cast explicitly Even explicit casting has limits
26
Using the Reflection API
The Reflection API supports an activity called introspection, which essentially asks a class to describe itself The Reflection API gives an object the ability to reflect upon itself and discover its contents The package java.lang.reflect defines a number of classes that together give a complete description of an object Three classes represent the building blocks of classes: Constructor, Method, and Field
27
Using the Reflection API
Purpose - Each instance of the Constructor class provides information about one constructor of a class, and provides a way for the calling program to create an object using the constructor Methods Class [ ] getParameterTypes( ) Object newInstance( Object[ ] args ) Purpose - Each instance of the Method class provides information about one method of a class, and provides a way for the calling program to call the method
28
Using the Reflection API
Methods Class[ ] getParameterTypes( ) Class getReturnType( ) Object invoke ( Object object, Object[] args ) Purpose - Each instance of the Field class provides information about one field of a class, and provides the calling program a way to get and set the value of the field. The field may be a class variable or an instance variable
29
Using the Reflection API
Methods Class getType() The getType method returns an object reference for the Class object of the field Object get( Object object ) void set( Object object, Object value ) Purpose - The class that implements this interface provides identifying information about a member of a class
30
Using the Reflection API
The type of most arguments and of many return values of the methods in the Reflection API classes is Object The classes Constructor, Method, and Field implement an interface called Member Methods Class getDeclaringClass() The getDeclaringClass method returns an object reference for the Class object of the class in which the member is defined
31
Using the Reflection API
Methods continued String getName() int getModifiers() Two additional classes complete the suite of Reflection API classes: Array and Modifier Purpose - The Array class provides methods to manipulate a Field object as an array. The Field class only has methods for getting and setting individual values. Use this class with the Field class when the field is an array. To determine whether a Field object is an array, call the Class.isArray method and pass the value returned by Field.getType
32
Using the Reflection API
Methods Object get(Object object, int position ) void set(Object object, int position ) int getLength() - The getLength method returns the number of elements in the array Object newInstance(Class type, int length) - the newInstance method creates a new array to hold the specified number of elements of the specified type, and returns an object reference for the new array
33
Using the Reflection API
Methods continued Object newInstance( Class type, int[] dimensions) Purpose - The Modifier class contains a number of constants that represent the access specifiers and qualifiers that can be applied to members How can you access the Class object for a primitive type when you cannot invoke a method such as getClass for a primitive type? Each wrapper class for a primitive type has a field called TYPE that is a reference to the Class object for its corresponding primitive type
34
Using the Reflection API
The field TYPE of wrapper classes is a public, static, and final field For example, Integer.TYPE is a reference to the Class object for int What about methods that do not return a value and have return type void? The package java.lang contains a wrapper class named Void for the primitive type void To provide run-time type information about void, the class java.lang.Void was added to the core classes at the same time as the Reflection API
35
Calling Methods With the Reflection API
Two ways to execute a method or a constructor: Call the method by name or create an object with the new keyword in the usual way Use a Method object or a Constructor object To call a method with the Reflection API, use the following instance method of the Method class: Object invoke(Object object, Object[] args) If the called method does not return a value, invoke returns an object reference of type Void
36
Calling Methods With the Reflection API
To create an instance of a class with the Reflection API, use the following instance method of the Constructor class: Object newInstance( Object[] args ) The only argument of newInstance is an array that contains the arguments for the constructor The method Constructor.newInstance has one great advantage over the method Class.newInstance: You can pass arguments to the constructor
37
Chapter Summary The Object class defines a method that you should use to copy objects: Object clone() All objects of reference type, including arrays, can use this method By default it performs a shallow copy Usually a deep copy is preferable because it duplicates contained objects, creates new object reference for the duplicates, and inserts the new object references into the copy of the containing object
38
Chapter Summary If your classes contain fields that have reference types, you should override the clone method to perform a deep copy, with the proviso that a shallow copy is adequate for immutable, contained objects To be cloneable, an object must be an instance of a class that implements the interface Cloneable You can define classes that are cloneable or not cloneable You can force subclasses of your classes to be cloneable, or prevent them from being cloneable
39
Chapter Summary Run-time type information of (RTTI) is particularly important in the Java platform The simplest form of RTTI involves using the instanceof operator: object_reference instanceof class_or_interface_name For every class known to the JVM, an object of type Class exists Even the primitive types have Class objects; you access them by using the object reference TYPE that is a field of each wrapper class for the primitive types
40
Chapter Summary For more extensive run-time type information, the Java platform provides the Reflection API You can create instances of classes three ways 1. Use the new operator in the usual fashion 2. If you can use the no-argument constructor, call the following method of the Class class: Object newInstance() 3. To use any constructor, first get the Constructor object for the constructor by calling: Constructor getConstructor( Class[ ] argtypes)
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.