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(...);
Related
I am new to Java. Maybe the question is a bit naive.
For example, I have a pkg1, in which there are 2 Java files: f1.java and f2.java
As the title, I feel it is reasonable
to use a package-private-top-level class for f1,
then use a public-top-level class for f2,
then the outside of pkg1 can still access f1 via f2.
I can even have f3, f4... ..., which are all using package-private class as their top-level class. Then f2.java will become a package-interface file for the rest of files in pkg1.
So, why is the fact that a top-level class must be public? Just to prevent from unnecessary complexity?
According to Oracle Java tutorial, public isn't the only possible modifier for top-level class:
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
So, basically, there's no problem in making some classes protected or package-private if your design requests it.
Term 'top-level class' actually exists in Java as well as terms 'inner class' and 'nested class', I suggest you to take a look on this page to clear some basics of java class hierarchy.
why is the fact that a top-level class must be public?
A "top level" class in Java is just a class that isn't a nested class (a class inside another class — JLS§8). They are not required to be public.
You may be thinking of applications that are run via the java tool (not all are!). The class meant to be used as the entry point for the java tool is usually shown as public in examples, but it isn't required to be. It is required to have a public static void main method accepting a String array, but the class itself doesn't have to be public.
A top level class should be public because a public class can be used any where in the java universe,but if you declare a class private or protected then its sole purpose is lost declaring a class private will not allow this class to be visible to any other class and marking it is protected will also do the same thing.Its always recommended to make a class default or public.
This might be simple for seasoned java developers but I just cant seem to figure it out. I read a post from here. The code was
View v = new View(this) {
#Override
protected void onDraw(Canvas canvas) {
System.out.println("large view on draw called");
super.onDraw(canvas);
}
};
It was an Android question. Here the user creates an instance of a view and overrides a method in a single line. Is there a name for this kind of coding?
My second doubt is, he overrides a protected method from another package. Isn't protected mean package private. I know this will work as I tried it out but I just couldn't figure out why it worked. So why is this code working?
I did try to google this and search in SO before asking but couldn't figure out an answer.
protected means (roughly) "available to sub-classes". (See this table.) Since the new View(this) { ... } creates a subclass, it is possible to override the method within it.
In this case it doesn't matter that you're in a different package. (See the protected line and second column in this table.) The fact that the method is in a subclass is sufficient to "get access" to a protected method.
Potential follow-up question: What sense does it make, if I can't call the method anyway?
All methods in Java are virtual. This means that whenever the View class performs a seemingly internal call to the onDraw method, this call will be dispatched to the overridden method.
That is not exactly a kind of coding. That is a Java anonymous class. It is very common in Android and in general with event listeners and that kind of stuff.
For more details you can read this link (probably not the best one):
The anonymous inner classes is very useful in some situation. For
example consider a situation where you need to create the instance of
an object without creating subclass of a class and also performing
additional tasks such as method overloading.
About your second question, the keyword protected means that the method is only available to subclasses, so it is possible to override the method.
This is an anonymous class. You are correct that you are overriding a protected method and this is perfectly normal. A protected method is visible, and can therefore be overridden, by a sub class, which is what you have created here.
Package protected is the default scope when you do not provide a scope for your variable or method. That is different to protected.
So many answeres were there for "protected", so i am going to other one :)
#override is informing the compiler to override the base class method, and if there is no base class method of this signature then throws compilation error.
These are called annotations. You can search for annotations topic in java. You can create custom annotations as well.
Regards,
SSuman185
Just like others here are already answered this is called anonymous class, and overriding protected methods is legal since protected methods are visible to child classes and classes in same package.
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).
In Java, I have an abstract class with a method implemented (not abstract) which I want to be accessible by other classes which extend it, but not by everyone else in the package..
I think this is not possible, because private keeps it private, public and protected expose it too much..
How would you approach the problem? Reimplementing the same method in all the extended classes is out of discussion.. is there a way to access the parent methods?
thanks!
If you want the method to be accessible by anything that extends the class then protected is the modifier you want. This is what it is for.
but not by everyone else in the package.. That's not possible. You can use protected access to allow access for subclasses but that will also include access for every class in the same package.
Use protected and make a package that contains only the abstract class and it's subclasses. Don't put any other classes in that package that shouldn't have access to protected methods.
If your concern is that someone else might create a new class in that package and start accessing protected methods, there really isn't a language construct to prevent that. You have either trust your other developers or have a stringent peer review process.
as for my observation when the class itself is having default access modifier, what is the use of having public methods in it. the java compiler could have stopped using public methods in default class. is there any reason for that?
The non-public class might implement a public interface. This would mean that classes outside of the package could not create an instance of this class or create references of that type, but they would still be able to invoke methods on it if passed an instance.
For example, a public factory class might create an instance of an non-public class in its package and return it.
One reason: if your class implements some interface (or extends some abstract class with abstract public methods), then you may not reduce the visibility of those implemented methods.
It is a beautiful combination of Security and Usability packed in one.
I would mark a Class with default access if I want it to have a, well, package access (so that no other package can use it or better change the code) and marking a method public, I am making the method accessible to all other classes regardless of the package they belong to.
How does that help? A class which is secure enough to perform all the complex code implementation and usable enough to give the output to the user who wants to use it.
How can anyone use that? Well you write code to help them use it by creating a public class which extends this default class. You Instantiate this public Subclass in any package (after importing of-course) and this has all the methods marked public.
You have a class which does your magic which everyone can use without giving anyone else a hint of how you got it done!