Sunday, January 2, 2011

Chapter 4: Access Modifiers

Access Modifiers are one of the most important topics when it comes to taking the SCJP exam. You can expect a number of questions from these access modifiers. Some questions test several concepts of access control at the same time, so not knowing one small part of access control could blow an entire question. Let us get started...

An Access Modifier is a key word in java that determines what level of access or visibility a particular java variable/method or class has. There are 4 basic access modifiers in java. They are:
1. Public
2. Protected
3. Default and
4. Private

Private is the most restrictive access modifier whereas public is the least restrictive. Default is the access protection you get when you do not specifically mention an access modifier to be used for a java object.

Java programming does not run by just a single piece of class that has the whole functionality. You have hundreds of classes that interact with one another, passing data between them and returning output to the user of the system. So it is very important for members of one class to access members of another. Here members may refer to variables, methods and even classes. So, this is where the access modifiers come into picture. The modifier associated with every member of the class determines what level of visibility that member has.

Let us say you have a Class A and you are trying to access a method from inside Class B. If the modifier for the method inside class B is restricted (say private) then the compiler will punch you in the face and tell you that what you are doing is wrong. Because, class A is not even supposed to know about the private members of class B and you cant possibly use them.

You need to understand two different access issues:

• Whether method code in one class can access a member of another class
• Whether a subclass can inherit a member of its superclass

The first type of access is when a method in one class tries to access a method or a variable of another class, using the dot operator (.) to invoke a method or retrieve a variable

Ex:
public class Dad {
public String getName() {
return “Vijayakumar”;
}
}

public class Son {
public void findDaddy() {
Dad obj = new Dad();
System.out.println(“The name of Sons Daddy is : “ + obj.getName();
}
}

Do you think the above code will work? Yes it will. That is because both the Dad and Son classes are public and so the Son class can happily access the Dad class and most importantly, the method getName() inside the Dad class is also public which means the Son can happily access that method too.

Let us say the getName() method was private, then the Son wouldn’t be able to access this getName() method and the compiler would have spit out error messages.

Public Members:
If a variable or method is declared public, it means that it can be accessed by anyone or any other class (irrespective of which package they are in). Of course, it is mandatory that the class inside which the public method is placed is visible in the first place for the method or variable to be visible. You can check out the code example in the previous paragraph for an example. The method from Dad class is visible and available for usage inside the son class.
For a subclass, if a member of its superclass is declared public, the subclass inherits that member regardless of whether both classes are in the same package.

Ex:

package pack1;
public class Parent {
public String getName() {
return “Parent”;
}
}

Package pack2;
Import pack1.Parent;
Public class Child extends Parent{
Public String getParentsName() {
return getName();
}
}

If you see the example above, the child class is able to access the parent class’s method getName() even without instantiating an object of the parent because it inherits the Parent class and all its method as part of the inheritance (extends) feature.

Private Members:

Members marked private can’t be accessed by code in any class other than the class in which the private member was declared. Let’s make a small change to the Parent class from an earlier example.

package pack1;
public class Parent {
private String getName() {
return “Parent”;
}
}

Now the getName() method is private and is not visible from within the Child class and the same piece of code would throw up the below compilation error when you try to compile the class.

cannot find symbol
symbol : method getName()

This error method looks as if the method getName() does not exist at all. Of course the method exists but unfortunately it is declared private and hence no class (except the class that has the exact code written into it) can access it. This includes a child class that extends the parent class that has the method.

Note: You can write a method inside the child class that has the same name as the private method in the parent. This does not account as Overriding because the parent class method is not even visible and hence it is just another method and is not considered overriding.

Tip: Though you may feel that public is better because all other classes can access your methods, that is seldom the case because a code that is visible to all other classes is not secure and that is not the best way to write your code. It is always best to provide just the appropriate level of access to methods and variables instead of having all of them public.

Protected and Default Members:

The protected and default access control levels are almost identical, but with one critical difference. A default member may be accessed only if the class accessing the member belongs to the same package, whereas a protected member can be accessed (through inheritance) by a subclass even if the subclass is in a different package.

Take a look at the following two classes:

package certification;
public class ClassOne {
void testIt() { // No modifier means method has default access
System.out.println("ClassOne");
}
}

In another source code file you have the following:

package otherCertification;
import certification.ClassOne;
class ClassTwo {
static public void main(String[] args) {
ClassOne o = new ClassOne();
o.testIt();
}
}

As you can see, the testIt() method in the first file has default (think: package-level) access. Notice also that class ClassTwo is in a different package from the ClassOne class. When you compile the ClassTwo.java file you will get an error like below:

No method matching testIt() found in class
certification.ClassOne.o.testIt();

From the preceding results, you can see that ClassOne can’t use the ClassTwo's method testIt() because testIt() has default access, and ClassOne is not in the same package as ClassTwo. So ClassOne can’t see it, the compiler complains.

Default and protected behavior differs only when we talk about subclasses. If the protected keyword is used to define a member, any subclass of the class declaring the member can access it through inheritance. It doesn’t matter if the superclass and subclass are in different packages, the protected superclass member is still visible to the subclass. This is in contrast to the default behavior, which doesn’t allow a subclass to access a superclass member unless the subclass is in the same package as the superclass. (See the example above)
Whereas default access doesn’t extend any special consideration to subclasses, the protected modifier respects the parent-child relationship, even when the child class moves away (and joins a new package). So, when you think of default access, think of package restrictions. No exceptions at all. But when you think protected, think package + kids. A class with a protected member is marking that member as having package-level access for all classes, but with a special exception for subclasses outside the package.

Tip: Remember that Default and Protected access is the same as long as inheritance is not involved.

Local Variables and Access Modifiers

Can access modifiers be applied to local variables? A BIG NO!
There is never a case where an access modifier can be applied to a local variable, so watch out for code like the following:
class Test {
void doTest() {
private int x = 7; //Not Possible
this.doSomethingElse(x);
}
}
The above code will not compile or run. Dont think that the private keyword is legal inside the method doTest().

You can be certain that any local variable declared with an access modifier will not compile. In fact, there is only one modifier that can ever be applied to local variables—final.

Let us refresh all that we have seen in this chapter in a table form.

Access Modifiers – Access to Class Members
Visibility Public Protected Default Private
From Within the Same Class Yes Yes Yes Yes
From any class in the Same Package Yes Yes Yes No
From a sub-class inside the Same Package Yes Yes Yes No
From a sub-class outside the Package Yes Yes (Only through Inheritance) No No
From a non sub-class outside the Package Yes No No No
Previous Chapter: Chapter 3 - Enums

Next Chapter: Chapter 5 - Other Modifiers (NonAccess Modifiers)

5 comments:

  1. One very interesting and important concept which is missed here is:
    Protected keyword allows visibility to subclasses outside the package "Only through Inheritance". This means NOT ONLY the class in the other package should be a sub-class of the parent class containing the Protected member, BUT ALSO it should ACCESS that member via "inheritance", which means that if the sub-class tries to create an instance of the parent class and access the Protected member, then it would NOT WORK.
    The sub-class has to use "inheritance", i.e. access the member as if it belongs within the class.

    EXAMPLE:

    package com.test;

    public class DummyParent {
    protected String getName() {
    return "Vijayakumar";
    }
    }


    package com.otherTest;

    import com.test.DummyParent;

    public class OtherDummySon extends DummyParent {
    public void findDaddy() {
    DummyParent obj = new DummyParent();
    System.out.println("The name of Sons Daddy is : " + obj.getName()); // COMPILER ERROR
    System.out.println("The name of Sons Daddy is : " + getName()); // WORKS FINE - THROUGH INHERITENCE
    }
    }

    ReplyDelete
  2. I agree, knowledge of access modifier is must in Java. I have recently blogged on private access modifier and best practices around it. let me know how do you find it.

    ReplyDelete
  3. That's one good article..

    ReplyDelete
  4. Notice also that class OtherClass is in a different package from the AccessClass. Can I know what is this OtherClass where to find this under the Protected and Default Members' headings.

    ReplyDelete
    Replies
    1. It was a typo Tangar. The term OtherClass and AccessClass refer to the first and second classes in our examples. I have renamed the words so you can understand it easily. Check it out now and let me know if you have any frther queries.

      Anand

      Delete

© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers