How do you access protected Java method in thirdparty library? - java

Assume that you must access a protected method of a Java object that you receive somewhere in your code. What is your solution?
I know one approach: You can employ reflection and call setAccessible(true) on the Method object.
Any other idea?

As per the Java access modifiers, besides extending the object (which you can't if you receive the object) is to access it from an object in the same package as the object you received. So your option is to create a wrapper class in the same package which retrieves the attribute via the protected method for you.

You can subclass the method, create a public method that calls the protected method and returns the result.
If you can't do that (if the class is final), then setAccessible is pretty much your only way.

One other option is to create a class that extends that 3rd party class that has the protected method that you are interested in.
public class ThirdPartyClass
{
protected void foo(){}
}
and
public MyClass extends ThirdPartyClass
{
public void callFoo()
{
foo();
}
}

You can also extend the class, override the method, and make the overridden method be public. Then have it just call super.method().

The other way is to extend the Class (if possible) and get access to the protected method via inheritance. If you do not create the Object this is not possible, as you would need it at compile time and you would need to create the Object yourself.
A dodgy solution could be to use composition. So you create a class in the same package e.g. OtherObjectWrapper. As it's in the same package you could call the Object's protected method through a public API you expose. This is not recommended though, as you don't own the package which you are adding a Class too and you can make your code very brittle e.g.
package com.foo;
public class OtherObjectWrapper {
private com.foo.OtherObject wrappedObject;
public OtherObjectWrapper(com.foo.OtherObject wrappedObject) {
this.wrappedObject = wrappedObject;
}
public void callTheProtectedMethod() {
wrappedObject.callTheProtectedMethod();
}
}
Consider what the the API designer thinking when they marked the method as protected? Maybe they didn't have a clue what they were doing and it should be public, or worse still, it should be package private or private outright. Or maybe they did and they determined only code in the same package or through inheritance should have access to the protected method. If it's protected it may well be for a reason, so be wary as you may tie your codes behaviour to behaviours which may change and break your code. Also look at who owns the third party Object and whether there is a better API for accessing the protected method's functionality.

If you can put the calling class in the same package you will have access to the method.
This and inheriting from that class are the only non-reflective ways to access a protected method.

As already said, subclassing is normally the standard way to access that method.
Other approaches (wrapper in same package, reflection) should generally not used, since if you can't extend the class (due to being final) there often are good reasons accessing that method is made hard.
If the library is of any decent quality you definitely shouldn't have to use any other means besides subclassing to access a protected method or not access that method at all.

If a class is not final, you can use an anonymous class to call its protected method:
new ClassWithProtectedMethod() {
#Override
protected void method() {
super.method();
}
}.method();
Note, making method() public is unnecessary (since the new anonymous class is in the same package).

Related

Unable to access protected final synchronized method in a class

This may be a silly question as I am new to android programming. I have imported a .aar library in my android project where I am trying to access a protected final synchronized method in one of the class present in that library. However, I am able to refer other methods present in the class which are not synchronized/final. When I open the source of the library from which I created the .aar file, I am able to see the method but unable to use it after importing it.
Can you please tell what is going wrong here?
Importing has nothing to do with accessibility and visibility of fields and methods of the imported class, it is just a shortcut for not typing the full class name every time you use the class.
To access an imported method or field of a certain class, the modifier preceding them should be marked as public.
Since the method you tried to access is marked as protected, the method can be accessed only if you are trying to access it within the subclass that extended class BaseActivity, or if you are accessing it from the class of the same package.
The solution is to extend the BaseActivity and either use the method within your customized method like this:
public class SomeOtherActivity extends BaseActivity{
public void someOtherMethod(Runnable task, long delayMillis){
super.queueEvent(task,delayMills);
}
}
This way the method you declared provides a public interface to other developers that wants to use your specific version of method that queues events.
However, this is not done through polymorphism nor with composition, so you might have to make sure that you really need this method or if there's another existing solution, since there's a reason that the original method is marked as final and protected which might cause other problems if not dealt with care.
Introduction to access modifiers can be found here:
The Java tutorials - Controlling Access to Members of a Class
On the other hand, this problem has nothing to do with "synchronized" and "final"
Introduction for the keyword synchronized can be found here:
The Java tutorials - Synchronized Methods
Introduction for the keyword final can be found here:
The Java tutorials - Final Classes and Methods
When you say "use" do you mean call/invoke or override?
A. protected methods are only visible to the package and subclasses
B. final methods cannot be overridden
With A and B the only thing you can do with that method is call it in your subclass.
Protected methods can be called only by classes that extend the main class.
To bypass this error that you are getting, you can create a class that extends your BaseActivity class and then a public method that calls the private one.
Something like this:
class MyBaseActivity extends BaseActivity {
public final synchronized void myQueueEvent(Runnable task, long delayMillis) {
super.queueEvent(task, delayMillis);
}
}
Now you can use it by calling: MyBaseActivity.myQueueEvent(...);

How to declare a method that can be used only inside another method in a java interface?

How to declare a method that can be used only inside another method in a java interface?
public interface VendingMachine_ADT {
public void selectDrink(Drink d);
public void MoneyEntered(Coin c);
public void DrinkSelectedandMoneyEntered();
public void cancel();//i want this method inside selectDrink();
}
Although you can, with come coercion, achieve this in C++ (which somewhat legitimises this question), you cannot do this in Java.
All methods in a Java interface are necessarily public. Really the concept of a private method localised to a particular function is more to do with the implementation of that interface rather than the interface itself.
So you'd need to enforce your restriction in an implementation of selectDrink().
You cannot do that. All methods in an interface are meant to be public.
Apparently, you have several classes that implement VendingMachine_ADT, and they use a method named cancel that is the same for them - or at least similar.
In this case, you can make a base class for VendingMachine_ADT, and make cancel a protected method of the base class. Your cancel method will be available to descendant classes.
Depending on your needs, you could even have cancel as an abstract method, to be implemented by subclasses. That is as close to an interface as you can get.

Java Extending Final Classes

I would like to override a 3rd party, open-source final class's non-final method.
final class A
{
void put(obj a)
{...}
obj get()
{...}
}
Please tell me how to override the get() and put() methods, yet still retain the other behaviour and functionality of this class.
It's open source: fork it, and make the class non-final.
You won't be able to extend it without making it non-final.
If your class has a defined interface in which put and get methods are defined then You may want to try to proxy the class.
The easiest way is to create something like this:
public interface CommonInterface {
void put(); Object get();
}
final class A implements CommonInterface
{
void put(obj a)
{...}
obj get()
{...}
}
public class ProxyToA implements CommonInterface{
private A a;
void put(Object a){
// your override functionality
}
Object get(){
// same here
}
void otherAStuff(){
a.otherAStuff();
}
}
And then just use CommonInterface and proxy your object. Or you can use JDK proxies, javassist, etc.
You can't extend final class. Per Java spec.
You should definitely try to find out why the class is final. If you are able to convince yourself it is ok to do that, another options is to use AspectJ to just change the behavior of thse two methods.
AspectJ allows you to modify behavior of specific methods. It can do this even for private methods -- security constraints permitting -- and access and assign private fields of the class.
The short answer is that you cannot override the methods because you cannot extend the class. What are you planning to do with the get and put methods by overriding? If you are looking add some functionality to those methods, you can create another class which wraps around this class.

Java: Easy way to make protected methods public

I have a class (Capsule) which has a lot of methods (30+) that are protected. The idea is to allow devs to extend this class and use the protected methods within the class (ImADev), but leave it up to the dev to expose them as public (Overriding the methods as they see fit).
I now have a use case where I want to pass these objects into a few Utility classes/methods and allow them to have access to the protected methods .. except they're protected, so my utility classes/services can't see them.
See the example below:
// My Capsule class with protected methods
public abstract class Capsule {
public Capsule(..) { .. }
protected String getFoo() { return "foo"; }
}
// How a dev should use the class
public class ImADev extends Capsule {
public ImADev(..) { super(..); }
public String getBar() { this.getFoo() + "BAR");
}
// A special utility class
// Helper.helper() can accept any class derived from Capsule
public class Helper {
public String helper(Capsule c) {
return " im doing something awesome with " + c.getFoo();
// Except i cant do this, because c.getFoo() is protected.
}
}
What's the best way around this? Keep in mind I have a lot of protected methods.
Either your class is doing too much, in which case break it up into smaller more well defined classes
Or, implement safe public methods that your utility class can call to wrap you protected methods
Or, just make them public because it sounds like they might/should be
Or, separate the data in the class from the behaviour (composition) then your utility class only has to deal with safer public getter methods an not the protected behaviour methods that can change the internals
A bit difficult to provide a better answer without knowing more about your application and it's use
There is no way 'around' this, except to put the utility class in the same package as the classes with the protected method. If those classes are in more then one package, that won't help.
In deciding to use protected, you made a decision, and now you are stuck with the implications. You can live with it, change to public, or change package membership to take advantage of default access.
I see at least two options.
Make Helper a subclass of Capsule. Or,
Turn your protected methods into default accessibility, and put the Helper class in the same package as the Capsule class.
Edit: You can also probably accomplish exactly what you want with reflection.
Actually there is a way to call protected methods from outside the package or subclass: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/AccessibleObject.html
I'm just kidding! This tool exists for technical stuff like serialization of persistance.
Declaring a method as "protected" is just a way to organise your code and define which part should deal which which data, so trying to get "around" is not a good idea, unless you mistakenly declared it protected. In this case correct the first mistake.
If you are interested in how to organize your code in an efficient and clear way, i highly recommend reading http://java.sun.com/docs/books/effective/

Java final abstract class

I have a quite simple question:
I want to have a Java Class, which provides one public static method, which does something. This is just for encapsulating purposes (to have everything important within one separate class)...
This class should neither be instantiated, nor being extended. That made me write:
final abstract class MyClass {
static void myMethod() {
...
}
... // More private methods and fields...
}
(though I knew, it is forbidden).
I also know, that I can make this class solely final and override the standard constructor while making it private.
But this seems to me more like a "Workaround" and SHOULD more likely be done by final abstract class...
And I hate workarounds. So just for my own interest: Is there another, better way?
You can't get much simpler than using an enum with no instances.
public enum MyLib {;
public static void myHelperMethod() { }
}
This class is final, with explicitly no instances and a private constructor.
This is detected by the compiler rather than as a runtime error. (unlike throwing an exception)
Reference: Effective Java 2nd Edition Item 4 "Enforce noninstantiability with a private constructor"
public final class MyClass { //final not required but clearly states intention
//private default constructor ==> can't be instantiated
//side effect: class is final because it can't be subclassed:
//super() can't be called from subclasses
private MyClass() {
throw new AssertionError()
}
//...
public static void doSomething() {}
}
No, what you should do is create a private empty constructor that throws an exception in it's body. Java is an Object-Oriented language and a class that is never to be instantiated is itself a work-around! :)
final class MyLib{
private MyLib(){
throw new IllegalStateException( "Do not instantiate this class." );
}
// static methods go here
}
No, abstract classes are meant to be extended. Use private constructor, it is not a workaround - it is the way to do it!
Declare the constructor of the class to be private. That ensure noninstantiability and prevents subclassing.
The suggestions of assylias (all Java versions) and Peter Lawrey (>= Java5) are the standard way to go in this case.
However I'd like to bring to your attention that preventing a extension of a static utility class is a very final decision that may come to haunt you later, when you find that you have related functionality in a different project and you'd in fact want to extend it.
I suggest the following:
public abstract MyClass {
protected MyClass() {
}
abstract void noInstancesPlease();
void myMethod() {
...
}
... // More private methods and fields...
}
This goes against established practice since it allows extension of the class when needed, it still prevents accidental instantiation (you can't even create an anonymous subclass instance without getting a very clear compiler error).
It always pisses me that the JDK's utility classes (eg. java.util.Arrays) were in fact made final. If you want to have you own Arrays class with methods for lets say comparison, you can't, you have to make a separate class. This will distribute functionality that (IMO) belongs together and should be available through one class. That leaves you either with wildly distributed utility methods, or you'd have to duplicate every one of the methods to your own class.
I recommend to never make such utility classes final. The advantages do not outweight the disadvantages in my opinion.
You can't mark a class as both abstract and final. They have nearly opposite
meanings. An abstract class must be subclassed, whereas a final class must not be
subclassed. If you see this combination of abstract and final modifiers, used for a class or method declaration, the code will not compile.
This is very simple explanation in plain English.An abstract class cannot be instantiated and can only be extended.A final class cannot be extended.Now if you create an abstract class as a final class, how do you think you're gonna ever use that class, and what is,in reality, the rationale to put yourself in such a trap in the first place?
Check this Reference Site..
Not possible. An abstract class without being inherited is of no use and hence will result in compile time error.
Thanks..

Categories