Java Protected Access Not Working - java

In java, there's three levels of access:
Public - Open to the world
Private - Open only to the class
Protected - Open only to the class and its subclasses (inheritance).
So why does the java compiler allow this to happen?
TestBlah.java:
public class TestBlah {
public static void main(String[] args) {
Blah a = new Blah("Blah");
Bloo b = new Bloo("Bloo");
System.out.println(a.getMessage());
System.out.println(b.getMessage()); //Works
System.out.println(a.testing);
System.out.println(b.testing); //Works
}
}
Blah.java:
public class Blah {
protected String message;
public Blah(String msg) {
this.message = msg;
}
protected String getMessage(){
return(this.message);
}
}
Bloo.java:
public class Bloo extends Blah {
public Bloo(String testing) {
super(testing);
}
}

Actually it should be:
Open only to the classes on the same package the class and its subclasses (inheritance)
That's why

Because protected means subclass or other classes in the same package.
And there's actually a fourth "default" level of access, when the modifier is omitted, which provides access to other classes in the same package.
So protected is between default and public access.

To be more specific, you're expecting protected to work as it does in C++.
However, in Java, it has a different meaning. In Java, a protected method is available to the class (obviously), all the other classes in the same package and any subclasses of this class. Classes in other packages will not have access unless they subclass this original class.
See this similar question for more specific information on inheritance markers.
Personally, I almost never use protected. I develop applications rather than frameworks so I'm much more likely to define public methods, private data and, quite often, mark my whole class as final.

There are actually four levels of access: "public", "protected", "private" & default also known as package private or package protected. Default limits accessibility to the package. Default is quite useful and I use it frequently.

You're able to call b.getMessage() because b is of type Bloo, which extends Blah, and getMessage() is protected. Protected, as you mentioned, allows subclasses to access the method.
You've got the following errors, though:
Calling super() with no arguments in the Bloo constructor is an error. The compiler can't find the no-parameter Blah constructor because you defined one with a String parameter.
Calling new Blah() in TestBlah main method is an error for the same reason as above.
Referring to a.testing and b.testing is an error because you didn't define the variable testing for any class.

Related

How can i restrict my clients with selected methods from the class?

Let's say I have 1 complete class with around 20 methods which provide different functionalities.
Now we have multiple clients using this class, but we want them to have restricted access.
For e.g. -
Client 1 - Gets access to method1/m3/m5/m7/m9/m11
Client 2 - Gets access to method2/m4/m6/m8/m10/m12
Is there any way I can restrict this access?
One solution which I thought:
Create 2 new classes extending Parent class and override methods which are not accessible and throw Exception from them.
But then if 3rd client with different requirement, we have to create new subclass for them.
Is there any other way to do this?
Create 2 new classes extending Parent class and override methods which
are not accessible and throw Exception from them. But then if 3rd
client with different requirement, we have to create new subclass for
them.
It is a bad solution because it violates Polymorphism and the Liskov Substitution Principle. This way will make your code less clear.
At first, you should think about your class, are you sure that it isn't overloaded by methods? Are you sure that all of those methods relate to one abstraction? Perhaps, there is a sense to separate methods to different abstractions and classes?
If there is a point in the existence of those methods in the class then you should use different interfaces to different clients. For example, you can make two interfaces for each client
interface InterfaceForClient1 {
public void m1();
public void m3();
public void m5();
public void m7();
public void m9();
public void m11();
}
interface InterfaceForClient2 {
public void m2();
public void m4();
public void m6();
public void m8();
public void m10();
public void m12();
}
And implement them in your class
class MyClass implements InterfaceForClient1, InterfaceForClient2 {
}
After it, clients must use those interfaces instead of the concrete implementation of the class to implement own logic.
You can create an Interface1 which defines methods only for Client1, and an Interface2 which defines methods only for Client2. Then, your class implements Interface1 and Interface2.
When you declare Client1 you can do something like: Interface1 client1.
With this approach, client1 can accesses only methods of this interface.
I hope this will help you.
The other answers already present the idiomatic approach. Another idea is a dynamic proxy decorating the API with an access check.
In essence, you generate a proxy API that has additional checks on method calls to implement a form of Access Control.
Example Implementation:
package com.example;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
#FunctionalInterface
public interface ACL<P, Q> {
boolean allowed(P accessor, Q target, Method method, Object[] args);
class ACLException extends RuntimeException {
ACLException(String message) {
super(message);
}
}
#SuppressWarnings("unchecked")
default Q protect(P accessor, Q delegate, Class<Q> dType) {
if (!dType.isInterface()) {
throw new IllegalArgumentException("Delegate type must be an Interface type");
}
final InvocationHandler handler = (proxy, method, args) -> {
if (allowed(accessor, delegate, method, args)) {
try {
return method.invoke(delegate, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
} else {
throw new ACLException("Access denies as per ACL");
}
};
return (Q) Proxy.newProxyInstance(dType.getClassLoader(), new Class[]{dType}, handler);
}
}
Example Usage:
package com.example;
import java.lang.reflect.Method;
public class Main {
interface API {
void doAlpha(int arg);
void doBeta(String arg);
void doGamma(Object arg);
}
static class MyAPI implements API {
#Override
public void doAlpha(int arg) {
System.out.println("Alpha");
}
#Override
public void doBeta(String arg) {
System.out.println("Beta");
}
#Override
public void doGamma(Object arg) {
System.out.println("Gamma");
}
}
static class AlphaClient {
void use(API api) {
api.doAlpha(100);
api.doBeta("100");
api.doGamma(this);
}
}
public static class MyACL implements ACL<AlphaClient, API> {
#Override
public boolean allowed(AlphaClient accessor, API target, Method method, Object[] args) {
final String callerName = accessor.getClass().getName().toLowerCase();
final String methodName = method.getName().toLowerCase().replace("do", "");
return callerName.contains(methodName);
}
}
public static void main(String[] args) {
final MyACL acl = new MyACL();
final API api = new MyAPI();
final AlphaClient client = new AlphaClient();
final API guardedAPI = acl.protect(client, api, API.class);
client.use(guardedAPI);
}
}
Notes:
The accessor does not have to be the client object itself, it can be a string key or token that helps ACL identify the client.
The ACL implementation here is rudimentary, more interesting ones could be One that reads ACL from some file or One that uses method and client annotations as rules.
If you don't want to define an interface for API class, consider a tool like javassist to directly proxy a class.
Consider other popular Aspect Oriented Programming solutions
You should create one super class with all the methods and then provide Client specific implementations in their corresponding sub classes extending from the super class defined earlier.
If there are methods which are common implementation for all clients, leave their implementations to the super class.
It seems like you are a bit confused about the purpose of Classes and Interfaces. As far as I know, an Interface is a contract defining which functionality a piece of software provides. This is from official java tutorial:
There are a number of situations in software engineering when it is
important for disparate groups of programmers to agree to a "contract"
that spells out how their software interacts. Each group should be
able to write their code without any knowledge of how the other
group's code is written. Generally speaking, interfaces are such
contracts.
Then you can write a Class which implements this Interface/contract, that is, provides the code that actually perform what was specified. The List interface and the ArrayList class are both an example of this.
Interfaces and Classes have access modifiers, but they aren't designed to specify permissions to specific clients. They specify what is visible for other piece of software depending the location where it is defined: Class, Package, Subclass, World. For example, a private method can be accessed only inside the class where it is defined.
From official Java tutorial again:
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).
Maybe you want something more powerful like Access Control List (ACL).
Your question is a little unclear, leading to different possible answers. I'll try to cover some of the possible areas:
Object encapsulation
If your goal is to provide interfaces to different clients that only provide certain functionality or a specific view there are several solutions. Which matches best depends on the purpose of your class:
Refactoring
The question somehow suggests that your class is responsible for different tasks. That might be an indicator, that you could tear it apart into distinct classes that provide the different interfaces.
Original
class AllInOne {
A m1() {}
B m2() {}
C m3() {}
}
client1.useClass(allInOneInstance);
client2.useClass(allInOneInstance);
client3.useClass(allInOneInstance);
Derived
class One {
A m1() {}
}
class Two {
B m2() {}
}
class Three {
C m3() {}
}
client1.useClass(oneInstance);
client2.useClass(twoInstance);
client3.useClass(threeInstance);
Interfaces
If you choose to keep the class together (there might be good reasons for it), you could have the class implement interfaces that model the view required by different clients. By passing instances of the appropriate interface to the clients they will not see the full class interface:
Example
class AllInOne implements I1, I2, I3 {
...
}
interface I1 {
A m1();
}
But be aware that clients will still be able to cast to the full class like ((AllInOne) i1Instance).m2().
Inheritance
This was already outline in other answers. I'll therefore skip this here. I don't think this is a good solution as it might easily break in a lot of scenarios.
Delegation
If casting is a risk to you, you can create classes that only offer the desired interface and delegate to the actual implementation:
Example
class Delegate1 {
private AllInOne allInOne;
public A m1() {
return allInOne.m1();
}
}
Implementing this can be done in various ways and depends on your environment like explicit classes, dynamic proxies , code generation, ...
Framework
If you are using an Application Framework like Spring you might be able to use functionality from this Framework.
Aspects
AOP allows you to intercept method calls and therefor apply some access control logic there.
Security
Please note that all of the above solutions will not give you actual security. Using casts, reflection or other techniques will still allow clients to obtain access to the full functionality.
If you require stronger access limitations there are techniques that I will just briefly outline as they might depend on your environment and are more complex.
Class Loader
Using different class loaders you can make sure that parts of your code have no access to class definitions outsider their scope (used e.g. in tomcat to isolate different deployments).
SecurityManager
Java offers possibilities to implement your own SecurityManager this offers ways to add some extra level of access checking.
Custom build Security
Of course you can add your own access checking logic. Yet I don't think this will be a viable solution for in JVM method access.

Why is the protected method not visible?

Java experts, I would sincerely appreciate any insights!
I have an abstract class in a package with a protected method. I also have a subclass of this class in the same package. Now, when I try to instantiate the subclass from a class outside the package, and invoke the protected method on the subclass' instance, Eclipse is complaining the protected method is not visible.
I thought, protected methods will be visible to all children - in or out of the package - as long as the class visibility does not restrict it - in this case, both the parent and the child class are public. What am I missing? Thanks in advance!
package X;
public abstract class Transformation {
protected OutputSet genOutputSet (List list) {
..
}
}
package X;
public class LookupTransformation extends Transformation {
}
package Y;
import X.*;
public class Test {
public static void main(String[] args) {
List<field> fld_list = new ArrayList();
..
LookupTransformation lkpCDC = new LookupTransformation();
OutputSet o = lkpCDC.genOutputSet(fld_list); // Eclipse errors out here saying genOutputSet from the Type Transformation is not visible. WWWWWWWWHHHHHAAAATTTTTT????
}
}
protected access means genOutputSet can be called by classes inheriting from the class where it's declared or by classes belonging to the same package. This means you can call it from within LookupTransformation.
However, you are trying to call it from an unrelated class - Test - located in a different package, which requires public access.
See additional explanation here.
Your code is not in a subclass (you're in Test), and your code is not in the
same package (you're in Y). So the method is not visible. That's normal.
protected means you may call the method in any derived class. However, Test isn't derived from Transformation. genOutputSet is only visible inside Transformation and LookupTransformation. This doesn't tell anything about the visibility of methods when they are called on an object of the derived class.
The best possible answer I could give would be in the form of this picture that I used to learn it myself:
Protected methods work on subclasses(inherited classes in your case) that are in other packages aswell. You are however calling it from a different class(not subclass). Hope this helps!

How to force putting a object into a handler class

I already post some relevant code in this question:
Specify object type of a returned array list dynamically
Now my question is a little bit more specific.
In fact I am using the following "handler" class to invoke methods of classes which implement the interface IMSSQLStatement:
public class MSSQLHandler {
IMSSQLStatement statement;
public MSSQLHandler(IMSSQLStatement statement) {
this.statement = statement;
}
public void invoke() throws SQLException {
statement.executeStatement();
}
public List<?> getDataList() throws SQLException {
return statement.getDataList();
}
}
The question is now how to force me (or an developer which implements my interface) to put created objects of the implemented class to MSSQLHandler?
Maybe this is bad design but I did not find any information and use cases regarding my problem.
Yes, you can use an abstract class with an explicit constructor, that is automatically called on all subclasses:
public abstract class IMSSQLStatement {
protected IMSSQLHandler handler;
public IMSSQLStatement() {
handler = new IMSSQLHandler(this);
}
}
Edit: (in reference to comment)
If you want that only the handler should be able to call the methods in IMSSQLStatement, both classes should be placed in the same package. Allow only package-private and subclass access, by giving the protected modifier. Although the methods could be called in the subclass itself, it would not be accessible outside, with the exception of the package.
This won't solve your problem completely. The other (real bogus) way around would be reflection.
To use reflection, you should write in your documentation the exact method signature the subclass should use (of course, don't define an abstract method in the superclass), giving it the private modifier. The handler should access these methods through reflection.
Refer some document, that describes how to use reflection. This is complicated, and beyond the scope of SO.

Doing an API, constructor for system private use only and another official, javadoc'ed and public to use. Advise on fix / pattern approach

I guess this is a bad pattern, whats the best approach to fix it?
I mean I would like everybody using a constructor with 2 arguments,but I need to leave default constructor because its implementing a listener which classloads it without args. I would like to hide default constructor to anyone else but the listener handler which uses it, and make the other the unique point to instantiate.
Is there any kind of annotation? any privacy modifier for certain classes (system caller one is not in the same package)?
This seems fine to me. You would do the same thing if you want to instantiate a class differently during unit testing.
Oh, I see you need a constructor that has more access than protected but less than public. Unfortunately that's not possible.
You could put both your class MyClass and the listener MyListener that needs to use the empty constructor in the same package. Then, set the access of the empty constructor to package-level:
package com.stackoverflow.foo;
public class MyClass {
MyClass () { // package-private (no explicit access modifier)
}
public MyClass(int a, int b) { // public
}
}
package com.stackoverflow.foo;
public class MyListener {
private MyClass ref = new MyClass(); // MyListener is on the same package as MyClass, so this is valid
}
This way, you ensure that only classes that are on the same package as MyClass can use the default constructor.

Design decisions: Why and when to make an interface private?

Are private interfaces ever used in design decisions ? If so, what are the reasons and when do you know the need for a private interface?
A top-level interface cannot be private. It can only have public or package access. From the Java Language Specification, section 9.1.1: "Interface Modifiers":
The access modifiers protected and private pertain only to member interfaces whose declarations are directly enclosed by a class declaration (§8.5.1).
A nested interface can be private whenever it and its subclasses, if any, are an implementation detail of its top-level class.
For example, the nested interface CLibrary below is used as an implementation detail of the top-level class. It's used purely to define an API for JNA, communicated by the interface's Class.
public class ProcessController {
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary( "c", CLibrary.class );
int getpid();
}
public static int getPid() {
return CLibrary.INSTANCE.getpid();
}
}
As another example, this private interface defines an API used by private nested classes implementing custom formatting symbols.
public class FooFormatter {
private interface IFormatPart {
/** Formats a part of Foo, or text.
* #param foo Non-null foo object, which may be used as input.
*/
void write( Foo foo ) throws IOException;
}
private class FormatSymbol implements IFormatPart { ... }
private class FormatText implements IFormatPart { ... }
...
}
IMHO You cannot usefully make an interface private.
However I often have two interfaces, one for public use and one for internal use. The internal use interface I make package local if possible e.g.
public interface MyInterface {
public void publicMethod();
}
interface DirectMyInterface extends MyInterface {
public void internalUseOnlyMethod();
}
The internal use methods expose methods I don't want other developers to use and/or I want to be able to change easily. The reason I have the interface at all is that I have several implementations which I want to use internally via an interface.
It has to be package protected if the interface if for internal use.
In general if the interface hasn't any interest outside it's ambit it's a good api design decision to hide it because there's less complexity for the users of the interface and also allows you to refactor it more easily, because when the interface is public and in the API you loss the liberty to change it.
A private interface method is a method that is only accessible within the class or object in which it is defined.
This allows for better organization and maintainability of code, as well as increased security by preventing external access to sensitive data or functionality.

Categories

Resources