Accessing Class Members in Java
Java classes consist of various variables and instance members (or methods). Before accessing class members in Java like variables and instance members, it is essential to declare them. So, let us first understand how to declare variables and methods.
Declaration of Instance Variables
All variables which are defined in a class are known as instance variables as each object of the class will have its own copy of the variables. Hence the data in various objects are unique and are separate from one another.
When declaring variables, there are three Access Level Modifiers. These are:
Modifier | Access Level | |||
Class | Package | Subclass | World | |
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
private | Y | N | N | N |
The public modifier is the default modifier and the easiest access specifier. It is used to specify that the member is visible to all the classes and can be accessed from everywhere. We should declare public members only if such access does not produce undesirable results. These act like secrets which can be known by anybody.
The protected modifier specifies that the member can be accessed by its own members or the members of its sub-class only. These act as family secrets which only the concerned family knows but no outsiders know about it.
The private modifier is the most restrictive access level. It specifies that the members can only be accessed by its own class i.e. the class where it is defined. This is used with those variables or methods that contain information that need not be accessed by an outsider as it could make the program inconsistent. This modifier is the main way by which an object encapsulates itself and hides its data from the outside world. Hence, these act as secrets which we do not tell anybody.
The syntax for declaration is as follows:
Access_modifier data_type var_name;
For example: public int students;
Declaration of Methods:
A method is that part of the program that contains the code regarding the action to be taken or the task to be carried out. A class can contain any number of functions depending on the functionality of that program and each function can be called any number of times during program execution. The syntax to declare a method is as follows:
Access_modifier data_type method_name ([parameter1, parameter2 …])
To execute a method you can invoke or call it from other methods as and when needed.
Accessing Class Members in Java-Instance Variables and Methods using Objects
Instance variables and methods are accessed via objects with the help of a dot (.) operator. The dot operator creates a link between the name of the instance variable and the name of the class with which it is used.
For example if salary class had a variable named basicsal and we wanted to initialize it to 10000, then we would use the following code:
Where, s is the name of the object and basicsal is the instance variable.
Now let us take up an example.
class Employee < String name; int age; float bsal, gsal; public void acceptDetails(String n, int a, int s) < name = n; age = a; bsal = s; >public void showData() < System.out.println("Employee Name = " + name); System.out.println("Employee Age = " + age); System.out.println("Employee Basic Salary = " + bsal); System.out.println("Employee Gross Salary = " + gsal); >void cal() // public by default < gsal = bsal - (bsal*5/100); >public static void main(String args []) < Employee e1 = new Employee(); // object e1 created e1.acceptDetails("Nancy", 28, 12000); e1.cal(); e1.showData(); >>
Primary Sidebar
- Java Features and Advantages
- Java OOP Concepts
- Java Structure of a Program
- Java Understanding JDK, JRE and JVM
- Java Platform Independence
- Java Data Types
- Java Variables and Constants
- Java Operators and Expressions
- Java Object and Class
- Java Accessing Class Members
- Java Constructors
- Java Garbage Collection
- Java Method Overloading
- Java Access Modifiers
- Java Super Keyword in Inheritance
- Java Multilevel Hierarchy
- Java Method Overriding
- Java Dynamic Method Dispatch
- Java Abstract Classes
- Java Final Keyword
- Using JOptionPane Class in Java for User Dialogs
- Java I/O Streams
- Java Reading Console Input
- Writing Console Output in Java
- Java Predefined Streams
- Java Hashtable
- Handling String in Java- using String class
- Java Append Method
Controlling Access to Members of a Class
Access level modifiers determine whether other classes can use a particular field or invoke a particular method. There are two levels of access control:
- At the top level public , or package-private (no explicit modifier).
- At the member level public , private , protected , or package-private (no explicit modifier).
A class may be declared with the modifier public , in which case that class is visible to all classes everywhere. If a class has no modifier (the default, also known as package-private), it is visible only within its own package (packages are named groups of related classes you will learn about them in a later lesson.)
At the member level, you can also use the public modifier or no modifier (package-private) just as with top-level classes, and with the same meaning. For members, there are two additional access modifiers: private and protected . The private modifier specifies that the member can only be accessed in its own class. The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
The following table shows the access to members permitted by each modifier.
Access Levels
Modifier Class Package Subclass World public Y Y Y Y protected Y Y Y N no modifier Y Y N N private Y N N N The first data column indicates whether the class itself has access to the member defined by the access level. As you can see, a class always has access to its own members. The second column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member. The third column indicates whether subclasses of the class declared outside this package have access to the member. The fourth column indicates whether all classes have access to the member.
Access levels affect you in two ways. First, when you use classes that come from another source, such as the classes in the Java platform, access levels determine which members of those classes your own classes can use. Second, when you write a class, you need to decide what access level every member variable and every method in your class should have.
Let’s look at a collection of classes and see how access levels affect visibility. The following figure shows the four classes in this example and how they are related.
Classes and Packages of the Example Used to Illustrate Access Levels
The following table shows where the members of the Alpha class are visible for each of the access modifiers that can be applied to them.
Visibility
Modifier Alpha Beta Alphasub Gamma public Y Y Y Y protected Y Y Y N no modifier Y Y N N private Y N N N If other programmers use your class, you want to ensure that errors from misuse cannot happen. Access levels can help you do this.
- Use the most restrictive access level that makes sense for a particular member. Use private unless you have a good reason not to.
- Avoid public fields except for constants. (Many of the examples in the tutorial use public fields. This may help to illustrate some points concisely, but is not recommended for production code.) Public fields tend to link you to a particular implementation and limit your flexibility in changing your code.
Discovering Class Members
There are two categories of methods provided in Class for accessing fields, methods, and constructors: methods which enumerate these members and methods which search for particular members. Also there are distinct methods for accessing members declared directly on the class versus methods which search the superinterfaces and superclasses for inherited members. The following tables provide a summary of all the member-locating methods and their characteristics.
Class Methods for Locating Fields
Class API List of members? Inherited members? Private members? getDeclaredField() no no yes getField() no yes no getDeclaredFields() yes no yes getFields() yes yes no Class Methods for Locating Methods
Class API List of members? Inherited members? Private members? getDeclaredMethod() no no yes getMethod() no yes no getDeclaredMethods() yes no yes getMethods() yes yes no Class Methods for Locating Constructors
Class API List of members? Inherited members? Private members? getDeclaredConstructor() no N/A 1 yes getConstructor() no N/A 1 no getDeclaredConstructors() yes N/A 1 yes getConstructors() yes N/A 1 no 1 Constructors are not inherited.
Given a class name and an indication of which members are of interest, the ClassSpy example uses the get*s() methods to determine the list of all public elements, including any which are inherited.
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Member; import static java.lang.System.out; enum ClassMember < CONSTRUCTOR, FIELD, METHOD, CLASS, ALL >public class ClassSpy < public static void main(String. args) < try < Classc = Class.forName(args[0]); out.format("Class:%n %s%n%n", c.getCanonicalName()); Package p = c.getPackage(); out.format("Package:%n %s%n%n", (p != null ? p.getName() : "-- No Package --")); for (int i = 1; i < args.length; i++) < switch (ClassMember.valueOf(args[i])) < case CONSTRUCTOR: printMembers(c.getConstructors(), "Constructor"); break; case FIELD: printMembers(c.getFields(), "Fields"); break; case METHOD: printMembers(c.getMethods(), "Methods"); break; case CLASS: printClasses(c); break; case ALL: printMembers(c.getConstructors(), "Constuctors"); printMembers(c.getFields(), "Fields"); printMembers(c.getMethods(), "Methods"); printClasses(c); break; default: assert false; >> // production code should handle these exceptions more gracefully > catch (ClassNotFoundException x) < x.printStackTrace(); >> private static void printMembers(Member[] mbrs, String s) < out.format("%s:%n", s); for (Member mbr : mbrs) < if (mbr instanceof Field) out.format(" %s%n", ((Field)mbr).toGenericString()); else if (mbr instanceof Constructor) out.format(" %s%n", ((Constructor)mbr).toGenericString()); else if (mbr instanceof Method) out.format(" %s%n", ((Method)mbr).toGenericString()); >if (mbrs.length == 0) out.format(" -- No %s --%n", s); out.format("%n"); > private static void printClasses(Class c) < out.format("Classes:%n"); Class[] clss = c.getClasses(); for (Class cls : clss) out.format(" %s%n", cls.getCanonicalName()); if (clss.length == 0) out.format(" -- No member interfaces, classes, or enums --%n"); out.format("%n"); > >
This example is relatively compact; however the printMembers() method is slightly awkward due to the fact that the java.lang.reflect.Member interface has existed since the earliest implementations of reflection and it could not be modified to include the more useful getGenericString() method when generics were introduced. The only alternatives are to test and cast as shown, replace this method with printConstructors() , printFields() , and printMethods() , or to be satisfied with the relatively spare results of Member.getName() .
Samples of the output and their interpretation follows. User input is in italics.
$ java ClassSpy java.lang.ClassCastException CONSTRUCTOR Class: java.lang.ClassCastException Package: java.lang Constructor: public java.lang.ClassCastException() public java.lang.ClassCastException(java.lang.String)
Since constructors are not inherited, the exception chaining mechanism constructors (those with a Throwable parameter) which are defined in the immediate super class RuntimeException and other super classes are not found.
$ java ClassSpy java.nio.channels.ReadableByteChannel METHOD Class: java.nio.channels.ReadableByteChannel Package: java.nio.channels Methods: public abstract int java.nio.channels.ReadableByteChannel.read (java.nio.ByteBuffer) throws java.io.IOException public abstract void java.nio.channels.Channel.close() throws java.io.IOException public abstract boolean java.nio.channels.Channel.isOpen()
The interface java.nio.channels.ReadableByteChannel defines read() . The remaining methods are inherited from a super interface. This code could easily be modified to list only those methods that are actually declared in the class by replacing get*s() with getDeclared*s() .
$ java ClassSpy ClassMember FIELD METHOD Class: ClassMember Package: -- No Package -- Fields: public static final ClassMember ClassMember.CONSTRUCTOR public static final ClassMember ClassMember.FIELD public static final ClassMember ClassMember.METHOD public static final ClassMember ClassMember.CLASS public static final ClassMember ClassMember.ALL Methods: public static ClassMember ClassMember.valueOf(java.lang.String) public static ClassMember[] ClassMember.values() public final int java.lang.Enum.hashCode() public final int java.lang.Enum.compareTo(E) public int java.lang.Enum.compareTo(java.lang.Object) public final java.lang.String java.lang.Enum.name() public final boolean java.lang.Enum.equals(java.lang.Object) public java.lang.String java.lang.Enum.toString() public static T java.lang.Enum.valueOf (java.lang.Class,java.lang.String) public final java.lang.Class java.lang.Enum.getDeclaringClass() public final int java.lang.Enum.ordinal() public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final void java.lang.Object.wait() hrows java.lang.InterruptedException public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll()
In the fields portion of these results, enum constants are listed. While these are technically fields, it might be useful to distinguish them from other fields. This example could be modified to use java.lang.reflect.Field.isEnumConstant() for this purpose. The EnumSpy example in a later section of this trail, Examining Enums, contains a possible implementation.
In the methods section of the output, observe that the method name includes the name of the declaring class. Thus, the toString() method is implemented by Enum , not inherited from Object . The code could be amended to make this more obvious by using Field.getDeclaringClass() . The following fragment illustrates part of a potential solution.