digitization, transformation, binary

What is JavaBeans?

Spread the love

Table of Contents

What are JavaBeans?

JavaBeans is a software component model for java. The JavaBeans API specifications define beans as -A Java Bean is a reusable component that can be manipulated visually in any bean builder tool.

To work with java bean we need to import java.beans package. Any bean builder tool will be able to manipulate beans. They will provide the ability to introspect them.

JavaBean API defines a set of naming conventions for the methods that a bean defines. If a bean follows these conventions, a builder tool can use the new reflection APIs to determine what properties, methods, and events that bean supports.

The introspector class uses reflection to obtain information about a bean and presents it to the builder tool in the form of a BeanInfo object which contains various FeatureDescriptor objects, describing the properties, methods, and events of the bean.

The JavaBean API contains classes and interfaces intended for the use of the codes who are designing the beans for others.

One interesting feature of JavaBeans API is that there is no Bean class that all beans must extend. The Java beans classes that a bean designer uses are generally auxiliary classes, used not by the bean but by the builder tool that manipulates the bean.

JavaBeans API can be used by coders who are assembling an application using beans. Coders may update it manually or use a builder tool. Coders using bean do not typically have to use the java.beans package. Coders need to know the event model used by the beans. Also, they need to be familiar with the naming convention.

When we ship the bean, we need to bundle it together with those auxiliary classes with all required but additional details. Besides a BuildInfo class, complex beans may also provide a customized class and property descriptor for classes. A customized class is a kind of configuration tool or wizard for beans. It just guides the user through the bean customization.

PropertyEditor class is used to allow users to edit the values of the bean properties of a particular class. Builder tools have built-in property editors for common types Like Strings, Colors, and font. But a bean that has properties of some unusual or custom type may want to provide a PropertyEditor subclass to allow the user to easily specify values for the properties.

 Packaging a bean

To create or prepare a bean, we can use a bean box tool. We need to create a package in a jar file along with the other classes or resources it needs. A single bean can contain many auxiliary files and a single jar file may contain multiple beans.

For this, we need to use the manifest file properly for a jar. The manifest file must define which of the jar file entries are beans. Use partial manifest file option to jar it. To identify a class file as bean, we need to add the following line in the manifest file

Java-Bean:True

To package multilevel class in jar file provide proper structure:

MyTest/beans/Myclass.class
Java-Bean:True

Installing a Bean

A bean can be installed using a beanbox. The Beanbox tool is available with BDK(Bean Development Kit). We need to copy the bean’s jar files into jars/directory within the BDK directory. Alternatively, we can use the Load JAR option from the File menu of beanbox.

Beans class in Java

The Beans class is never meant to be instantiated; its static methods provide miscellaneous JavaBeans features. The instantiate() method creates an instance of a bean. The specified bean name represents either a serialized bean file or a bean class file; it is interpreted relative to the specified ClassLoader object.

The setDesignTime() and isDesignTime() methods are used to set and query a flag that indicates whether beans are being used in an application builder environment. Similarly, setGuiAvailable() and isGuiAvailable() set and query a flag that indicates whether the Java Virtual Machine is running in an environment in which a GUI is available. (untrusted applet code cannot call setDesignTime() or setGuiAvailable().)

The isInstanceOf() method is a replacement for the Java instanceof operator for use with beans. Currently, it behaves just like instanceof, but in the future, it may work with beans that consist of a set of Java objects, each of which provides a different ” view ” of a bean.

Similarly, the getInstanceof() method is a replacement for the Java cast operator. It converts a bean to a superclass or interface type. Currently, it behaves just like a cast, but we should use it for future compatibility with multiclass beans.

The structure of Bean class is given as

public class java.beans.Beans extends java.lang.Object {
// Default Constructor: 
public Beans ()
// Class Methods
public static Object getInstanceOf (Object bean, class targetType);
public static Object instantiate(ClassLoader cls, String beanName)
public static Object instantiate 'u' throws IOException,ClassNotFoundException;
public static boolean isDesignTime();
public static boolean isGuiAvailable();
public static boolean isInstanceOf(Object bean, class targetType);
public static void set DesignTime(boolean isDesign Time) throws SecurityException;
public static void setGuiAvailable (boolean isGuiAvailable) throws SecurityException;
}

VetoableChangeListener in java bean

VetoableChangeListener interface is an extension of java.util.EventListener and defines the method that a class must implement in order to be notified when a Java bean makes a change to a “constrained” property.

READ  Class SecurityManager in Java

A PropertyChangeEvent is passed to the vetoableChange() method when such a change occurs, and if the VetoableChangeListener wants to prevent the change from occurring, this method should throw a PropertyVetoException.

The structure of the VetoableChangeListener interface is given as

public abstract interface java.beans.VetoableChangeListener extends java.util.EventListener{
// Public Instance Methods
public abstract void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException;
}

PropertyVetoException in java bean

The PropertyVetoException signals that a VetoableChangeListener that received a PropertyChangeEvent for a ” constrained ” property of a bean has vetoed that proposed change.

When this exception is received, the property in question should revert back to its original value, and any VetoableChangeListener objects that have already been notified of the property change must be re – notified to indicate that the property has reverted to its old value.

The VetoableChangeSupport class handles this re-notification automatically and re-throws the PropertyVetoException to notify its caller that the change was rejected.

The structure of PropertyVetoException class is given as

public class java.beans.PropertyVetoException  extends java.lang.Exception{
// Public Constructor (String mess, PropertyChangeEvent evt);
public PropertyVetoException
// Public Instance Methods ();
public PropertyChangeEvent getPropertyChangeEvent();
}

BeanDescriptor in java bean

A BeanDescriptor object is a type of FeatureDescriptor that describes a Java bean. The BeanInfo class for a Java bean optionally creates and initializes a BeanDescriptor object to describe the bean.Typically, only application builders and similar tools use the BeanDescriptor.

To create a BeanDescriptor, we must specify the class of the bean, and optionally, the class of a Customizer for the bean. We can use the methods of FeatureDescriptor to provide additional information about the bean.

The structure of the class BeanDescriptor is given as

public class java.beans.BeanDescriptor extends java.beans.FeatureDescriptor{
// Public Constructors
public BeanDescriptor(Class beanClass);
public BeanDescriptor(Class beanclass, class customizerClass);
1/ Public Instance Methods
public Class getBeanClass();
public Class getCustomizerClass();
}

SimpleBeanInfo in java bean

The SimpleBeanInfo class is a trivial implementation of the Bean BeanInfo interface. The methods of this class all return null or – 1, indicating that no bean information is available. To use this class, we need only to override the method or methods that return the particular type of bean information we want to provide.
In addition, SimpleBeanInfo provides a convenience method, loadImage (), that takes a resource name as an argument and returns an Image object. This method is useful when defining the getIcon() method.

The structure of the class SimpleBeanInfo is given as

public class java.beans.SimpleBeanInfo extends java.lang.Object implements java.beans.BeanInfo
// Default Constructor: 
public SimpleBeanInfo()
// Public Instance Methods 
public BeanInfo[ ] getAdditionalBeanInfo();// From Beaninfo
public BeanDescriptor getBeanDescriptor();// From Beaninfo
public int getDefaultEventIndex();// From BeanInfo
public int getDefaultPropertyIndex Set Descriptors ();// From BeanInfo
public EventSetDescriptor[] getEventSetDescriptors();// From BeanInfo
public Image getIcon(int icon);// From BeanInfo 
public MethodDescriptor[ ] getMethodDescriptors();// From BeanInfo
public PropertyDescriptor[ ] getPropertyDescriptors();// From BeanInfo
public Image loadImage (String resourceName);
}

PropertyEditor in java bean

The PropertyEditor interface defines the methods that must be implemented by a Java beans property editor intended for use within an application builder or similar tool. PropertyEditor is a complex interface as it defines methods to support several different ways of displaying property values to the user, and it also defines methods to support several different ways of allowing the user to edit the property value.

For a property of type z, the author of a Java bean typically implements a property editor of class zEditor. While the editor is implemented by the bean author, it is usually only instantiated or used by application builders or similar tools (or by a Customizer class for a Bean).

In addition to implementing the PropertyEditor interface, a property editor must have a constructor that expects no arguments, so that it can be easily instantiated by an application builder.

Also, it must accept registration and deregistration of PropertyChangeListener objects, and it must send a PropertyChangeEvent to all registered listeners when it changes the value of the property being edited.

The PropertyEditorSupport class is a trivial implementation of PropertyEditor, suitable for subclassing, or for supporting a list of PropertyChangelistener objects.

The structure of the class PropertyEditor is given as

public abstract interface java.beans.PropertyEditor{
// Public Instance Methods 
public abstract void addPropertyChangeListener(PropertyChangeListener listener);
public abstract String getAsText();
public abstract Component getCustomEditor();
public abstract String getJavaInitializationString();
public abstract String[] getTags();
public abstract Object getValue();
public abstract boolean isPaintable();
public abstract void paintValue(Graphics gfx, Rectangle box);
public abstract void removePropertyChangeListener(PropertyChangeListener listener); 
public abstract void setAsText(String text) throws IllegalArgumentException;
public abstract void setValue(Object value);
public abstract boolean supportsCustomEditor();
}

PropertyDescriptor in java bean

A PropertyDescriptor object is a type of FeatureDescriptor that describes a single property of a Java bean. The BeanInfo class for a Java bean optionally creates and initializes PropertyDescriptor objects to describe the properties that the bean supports.

Typically, only application builders and similar tools use the get and is methods to obtain this property description information.

We create a PropertyDescriptor by specifying the name of the property and the Class object for the bean. If we have not followed the standard “design patterns” for accessor method naming, we may also specify the accessor methods for the property.

Once a PropertyDescriptor is created, the setBound() and setConstrained() methods allow us to specify whether the property is bound and/or constrained.

setPropertyEditorClass() allows us to specify a specific property editor that should be used to edit the value of this property (this is useful, for example, when the property is an enumerated type with a specific list of supported values).

The methods of the FeatureDescriptor superclass allow additional information about the property to be specified.

The structure of the class PropertyDescriptor is given as

public class java.beans.PropertyDescriptor extends java.beans.FeatureDescriptor
// Public Constructors 
public PropertyDescriptor(String propertyName, Class beanClass) throws IntrospectionException; 
public PropertyDescriptor(String propertyName, Class beanClass, String getterName,public Property Descriptor ' u ' String setterName) throws IntrospectionException;
public PropertyDescriptor (String propertyName, Method getter, Method setter) throws IntrospectionException;
// Public Instance Methods
public class getPropertyEditorClass();
public class getPropertyType();
public Method getReadMethod()
public Method getWriteMethod(); 
public boolean isBound ();
public boolean isConstrained ();
public void setBound(boolean bound);
public void setConstrained(boolean constrained);
public void setPropertyEditorclass(Class propertyEditorclass);

PropertyChangeListener in java bean

PropertyChangeListener interface is an extension of java.util.EventListener and defines the method that a class must implement in order to be notified when property changes occur. A PropertyChangeEvent is sent out to all registered PropertyChangeListener objects whenever a bean changes one of its ” bound ” properties, or whenever a PropertyEditor or Customizer changes the value of a property.

READ  Class PropertyResourceBundle in Java

The structure of the interface PropertyChangeListener is given as

public abstract interface java.beans.PropertyChangeListener extends java.util.EventListener{
// Public Instance Methods
public abstract void propertyChange(PropertyChangeEvent evt);
}

PropertyChangeEvent in java bean

The PropertyChange Event class is a subclass of java.util.EventObject. An event of this type is sent to interested PropertyChangeListener objects whenever a Java bean changes a “bound” property, or whenever a PropertyEditor or Customizer changes a property value.

A PropertyChangeEvent is also sent to registered VetoableChangeListener objects when a bean attempts to change the value of a ” constrained ”  property.

When creating a PropertyChangeEvent, we normally specify the bean that generated the event, the programmatic (locale-independent) name of the property that changed, and the old and new values of the property.

If the values cannot be determined, null should be passed instead. If the event is a notification that more than one property value changed, the name should also be null.

While Java beans must generate and send PropertyChangeEvent objects, it is typically only application builders and similar tools that are interested in receiving them.

The structure of the class PropertyChangeEvent is given as

public class java.beans.PropertyChangeEvent extends java.util.EventObject{
// Public Constructor
public PropertyChangeEvent(Object source, String propertyName, Object oldValue, Object newValue); 
// Public Instance Methods
public Object getNewValue();
public Object getoldValue();
public Object getPropagationId();
public String getPropertyName();
public void setPropagationId (Object propagationId);
}

ParameterDescriptor in java bean

A ParameterDescriptor object is a type of FeatureDescriptor that describes an argument or parameter to a method of a Java bean. The BeanInfo class for a Java bean optionally creates ParameterDescriptor objects that describe the parameters of the methods that the bean exports.

While the BeanInfo class creates and initializes ParameterDescriptor objects, it is typically only application builders and similar tools that use these objects to obtain information about method parameters supported by the bean.

The ParameterDescriptor class is a trivial subclass of FeatureDescriptor and does not provide any new methods. Thus, we should use the methods of FeatureDescriptor to provide information about method parameters.

The structure of the class ParameterDescriptor is given as

public class java.beans.ParameterDescriptor extends java.beans.FeatureDescriptor{
// Default Constructor: 
public ParameterDescriptor();
}

MethodDescriptor in java bean

A MethodDescriptor object is a type of FeatureDescriptor that describes a method supported by a Java bean. The BeanInfo class for a Java bean optionally creates MethodDescriptor objects that describe the methods the bean exports. While a BeanInfo class creates and initializes MethodDescriptor objects, it is typically only application builders and similar tools that use these objects to obtain information about the methods supported by a bean.
To create a MethodDescriptor, we must specify the java.lang.reflect.Method object for the method, and optionally specify an array of ParameterDescriptor objects that describe the parameters of the method. Once we have created a MethodDescriptor object, we can use FeatureDescriptor methods to provide additional information about each method.

The structure of the class MethodDescriptor is given as

public class java.beans.MethodDescriptor extends java.beans.FeatureDescriptor
// Public Constructors
public MethodDescriptor(Method method);
public MethodDescriptor(Method method, ParameterDescriptor [ ] parameterDescriptors);
// Public Instance Methods
public Method getMethod ();
public ParameterDescriptor [ ] getParameterDescriptors ();
}

EventSetDescriptor in java bean

An EventSetDescriptor object is a type of FeatureDescriptor that describes a single set of events supported by a Java bean. A “set” of events corresponds to the one or more methods supported by a single EventListener interface.

The BeanInfo class for a Java bean optionally creates EventSetDescriptor objects to describe the event sets the bean supports. Typically, only application builders and similar tools use the ‘get’ and ‘is’ methods of EventSetDescriptor objects to obtain the event – set description information.

To create an EventSetDescriptor object, we must specify the class of the bean that supports the event set, the base name of the event set, the class of the EventListener interface that corresponds to the event set, and the methods within this interface that are invoked when particular events within the set occur.

Optionally, we may also specify the methods of the bean class that are used to add and remove EventListener objects. The various constructors allow us to specify methods by name, as java.lang.reflect.Method objects, or as MethodDescriptor objects.

Once we have created an EventSetDescriptor, we can use setUnicast() to specify whether it represents a unicast event and setInDefaultEventSet () to specify whether the event set should be treated as the default event set by builder applications.

The methods of the FeatureDescriptor superclass allow additional information about the property to be specified.

The structure of the class EventSetDescriptor is given as

public class java.beans.EventSetDescriptor extends java.beans.FeatureDescriptor{
// Public Constructors
public EventSetDescriptor(Class sourceclass, String eventSetName, Class listenerType,public EventSetDescriptor 'u' String listenerMethodName) throws IntrospectionException;
public EventSetDescriptor(Class sourceClass, String eventSetName, Class listenertype,public EventSetDescriptor 'u' string [] listenerMethodNames, String addListenerMethodName public EventSetDescriptor 'u' String removeListenerMethodName) throws Introspectionexception;
public EventSetDescriptor (String eventSetName, Class listenerType,Method [ ] listenerMethods,public EventSetDescriptor 'u' Method addListenerMethod, Method removeListener Method)
public EventSetDescriptor 'u' throws IntrospectionException;
public EventSetDescriptor(String eventSetName, Class listenerType,public EventSetDescriptor 'u' MethodDescriptor[] listenerMethodDescriptors,Method addListenerMethod,public EventSetDescriptor ' u ' Method removeListenerMethod) throws IntrospectionException;
// Public Instance Methods
public Method getAddListenerMethod();
public MethodDescriptor[] getListenerMethodDescriptors ();
public Method[] getListenerMethods();
public Class getListenerType();
public Method getRemoveListenerMethod();
public boolean isInDefaultEventSet();
public boolean isUnicast();
public void setInDefaultEventSet(boolean inDefaultEventSet);
public void setUnicast(boolean unicast);
}

Class VetoableChangeSupport in java bean

VetoableChangeSupport is a convenience class that maintains a list of registered VetoableChangeListener objects and provides a fireVetoableChange() method for sending a PropertyChangeEvent to all registered listeners.

If any of the registered listeners veto the proposed change, fireVetoableChange() send out another PropertyChangeEvent notifying previously notified listeners that the property has changed back to its original value. Because of the extra complexity of correctly handling vetoable changes, and because of some tricky thread synchronization issues involved in maintaining the list of listeners, it is recommended that all Java beans that support “constrained” events create a VetoableChangeSupport object to which they can delegate the tasks of maintaining the list of listeners and of firing events.

The structure of the class VetoableChangeSupport is given as

public class java.beans.VetoableChangeSupport extends java.lang.Object implements java.io.Serializable {
// Public Constructor
public VetoableChangeSupport(Object sourceBean);
// Public Instance Methods
public synchronized void addVetoableChangeListener(VetoableChangeListener listener);
public void fireVetoableChange(String propertyName, Object oldValue,Object newValue)
public void fireVetoableChange'u'throws PropertyVetoException;
public synchronized void removeVetoableChangeListener(VetoableChangeListener listener);
}

Class PropertyChangeSupport in java bean

The PropertyChangeSupport class is a convenience class that maintains a list of registered PropertyChangeListener objects and provides the firePropertyChange() method for sending a PropertyChangeEvent object to all registered listeners. Because there are some tricky thread synchronization issues involved in doing this correctly, it is recommended that all Java beans that support “bound” properties either extend this class or, more commonly, create an instance of this class to which they can delegate the task of maintaining the list of listeners.

READ  Common Error classes in Java

The structure of the class PropertyChangeSupport is given as

public class java.beans.PropertyChangeSupport extends java.lang.Object implements java,io.Serializable {
// Public Constructor
public PropertyChangeSupport(Object sourceBean);
// Public Instance Methods
public synchronized void addPropertyChangeListener(PropertyChangeListener listener);
public void firePropertyChange(String propertyName, Object oldValue, Object newValue);
public synchronized void removePropertyChangeListener(PropertyChangeListener listener);
}

Class PropertyEditorManager in java bean

The PropertyEditorManager class is never meant to be instantiated; it defines static methods for registering and
looking up PropertyEditor classes for a specified property type.

A Java bean may specify a particular PropertyEditor class for a given property by specifying it in a PropertyDescriptor object for the property. If it does not do this, the PropertyEditorManager is used to
register and lookup editors. A bean or an application builder tool may call the registerEditor() method to register a PropertyEditor for properties of a specified type. Application builders and bean Customizer classes may call the
findEditor() method to obtain a PropertyEditor for a given property type.

If no editor has been registered for a given type, the PropertyEditorManager attempts to locate one. For a type x, it
looks for a class xEditor first in the same package as x, and then in each package listed in the property editor search path.

The structure of the class PropertyEditorManager is given as

public class java.beans.PropertyEditorManager extends java.lang.Object {
// Default Constructor: 
public PropertyEditorManager();
// Class Methods
public static PropertyEditor findEditor(Class targetType);
public static String[] getEditorSearchPath();
public static void registerEditor(Class targetType, Class editorClass);
public static void setEditorSearchPath(String[] path);
}

Class Introspector in java bean

The Introspector is a class that is never instantiated. Its static getBeanInfo() methods provide a way to obtain information about a Java bean, and are typically only invoked by application builders or similar tools.

getBeanInfo() first looks for a BeanInfo class for the specified Java bean class. For a class named x, it looks for a BeanInfo class named xBeanInfo, first in the current package, and then in each of the packages in the BeanInfo search path.

If no BeanInfo class is found, or if the BeanInfo class found does not provide complete information about the bean properties, events, and methods, getBeanInfo() “introspects” on the bean class by using the java.lang.reflect package to fill in the missing information. When explicit information is provided by a BeanInfo class, getBeanInfo() treats it as definitive.

When determining information through introspection, however, it examines each of the bean’s superclasses in turn, looking for a BeanInfo class at that level or using
introspection. When calling getBeanInfo(), we may optionally specify a second class argument that specifies a superclass for which, and above which, getBeanInfo() does not introspect.

The structure of the class Introspector is given as

public class java.beans.Introspector extends java.lang.Object {
// No Constructor
// Class Methods
public static String decapitalize(String name);
public static BeanInfo getBeanInfo(Class beanClass) throws IntrospectionException;
public static BeanInfo getBeanInfo(Class beanClass, Class stopClass) throws IntrospectionException;
public static String[] getBeanInfoSearchPath();
public static void setBeanInfoSearchPath(String[] path);
}

Class BeanInfo in java bean

The BeanInfo interface defines the methods that a class must implement in order to export information about a Java bean. The Introspector class knows how to obtain all the basic information required for a bean. A bean that wants to be more “programmer-friendly” may provide a class that implements this interface, however, in order to provide additional information about itself (such as an icon and description strings for each of its properties, events, and methods). Note that a bean developer defines a class that implements the methods of this interface. Typically only builder applications and similar tools actually invoke the methods defined here.

The methods getBeanDescriptor(), getEventSetDescriptors(),getPropertyDescriptors(), and getMethodDescriptors() should return appropriate descriptor objects for the bean, or null, if the bean does not provide explicit bean, event set, property, or method descriptor objects. The getDefaultEventIndex() and getDefaultPropertyIndex()
methods return values that specify the “default” event and property–i.e., that are most likely to be of interest to a programmer using the bean. These methods should return -1 if there are no defaults.

The getIcon() method should return an image object suitable for representing the bean in a palette or menu of available beans. The argument passed to this method is one of the four constants defined by the class; it specifies the type and size of the icon requested. If the requested icon cannot be provided, getIcon() should
return null.

A BeanInfo class is allowed to return null or -1 if it cannot provide the requested information. In this case, the Introspector class provides basic values for the omitted information from its own introspection of the bean. See SimpleBeanInfo for a trivial implementation of this interface, suitable for convenient
subclassing.

The structure of the class BeanInfo is given as

public abstract interface java.beans.BeanInfo{
// Constants
public static final int ICON_COLOR_16x16;
public static final int ICON_COLOR_32x32;
public static final int ICON_MONO_16x16;
public static final int ICON_MONO_32x32;
// Public Instance Methods
public abstract BeanInfo[] getAdditionalBeanInfo();
public abstract BeanDescriptor getBeanDescriptor();
public abstract int getDefaultEventIndex();
public abstract int getDefaultPropertyIndex();
public abstract EventSetDescriptor[] getEventSetDescriptors();
public abstract Image getIcon(int iconKind);
public abstract MethodDescriptor[] getMethodDescriptors();
public abstract PropertyDescriptor[] getPropertyDescriptors();
}

FeatureDescriptor in java bean

The FeatureDescriptor class is the base class for MethodDescriptor and PropertyDescriptor, as well as other classes used by the JavaBeans introspection mechanism. It provides basic information about a feature (method, property, event, etc.) of a bean. Typically, the methods that begin with get and is are used by application builders or other tools to query the features of a bean. The set methods, on the other hand, maybe used by bean authors to define information about the bean.

setName() specifies the locale-independent, programmatic name of the feature.setDisplayName() specifies a localized, human-readable name. setShortDescription() specifies a short localized string (about 40 characters) that describes the feature. Both the short description and the localized name default to the value of the programmatic name.

setExpert() and setHidden() allow us to indicate that the feature is for use only by experts, or for use only by the builder tool, and should be hidden from users of the builder. Finally, the setValue() method allows us to associate an arbitrary named value with the feature.

The structure of the class FeatureDescriptor is given as

public class java.beans.FeatureDescriptor extends java.lang.Object {
// Public Constructor
public FeatureDescriptor();
// Public Instance Methods
public Enumeration attributeNames();
public String getDisplayName();
public String getName();
public String getShortDescription();
public Object getValue(String attributeName);
public boolean isExpert();
public boolean isHidden();
public void setDisplayName(String displayName);
public void setExpert(boolean expert);
public void setHidden(boolean hidden);
public void setName(String name);
public void setShortDescription(String text);
public void setValue(String attributeName, Object value);
}

in java bean

The structure of the class is given as


in java bean

The structure of the class is given as



Spread the love

Leave a Comment

Your email address will not be published. Required fields are marked *