I am fairly new to java development and wounder how I can modify an existing Android class. I would like to change some of the methods in Notification.Builder class in Android (https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/Notification.java).
Specifically do I want to change getNotification(), but in the new implementation I need access to the private fields (e.g., mWhen, mSmallIcon).
I have tried to extend the class, but then I don't have access to the private fields of the superclass (i.e., mWhen, mSmallIcon).
What is the best practice to change the method, is it to copy the source code and modify it?
Update:
To be more precise: how can I change a single method in an existing class and still have access to the private fields of the existing class?
Thanks for all responses!
You could simply call super.getNotification() in your overriden method and modify the resulting object before returning it.
A private (inner) class, method or field are only referenced from within the class in which it is declared.
But you also can declare your own variables and work with it as you wish
The best practice is not to override methods (from third-party classes which were not designed to be overridden), but to create a new class/method which wraps the third-party class. Google for these: "fragile base class problem", "composition over inheritance".
I have tried to extend the class, but then I don't have access to the private fields of the superclass (i.e., mWhen, mSmallIcon).
In the particular class you're extending there are a limited number of methods that set the values of these fields. You can override those methods to hold onto copies of the values in new fields in your subclass which you can then use in your override of getNotification().
This is something of a hack, and wouldn't be workable with a more complex class.
Another hack is to use reflection and invoke setAccessible(true) on the field objects. This also may not be workable depending on security constraints.
If you say exactly the change you're trying to make, there might be a better way.
Related
We use System.out.println without instantiating it or creating object of it. Same goes to Math class and many others (I guess). Is there something special about these classes? Can we use the classes and methods declared within those classes in same fashion? Please help.
You don't have to create objects for the System and Math classes because the methods and variables in those classes are static. This means that they belong to the class itself, not to instances of the class.
For reference see:
Understanding Class Members
Beyond Basic Arithmetic
This is something called 'static' method. In order to invoke static method, you do not need to have an instance of the class.
This also has other side effects such as non-existing 'this' and thus static methods cannot invoke instance methods.
This is mostly used for some sort of utility classes which are often stateless.
Math is a good example for it.
I suggest to read a bit about static methods and static in Java in general.
You don’t need to create object of System and Math class to use it because they have static methods. Static methods belong to the class and thus doesn’t require it to be instantiated.
Although, you can create its object and then also use those methods, but creating a class for static method is of no use.
Why don't we have to create object of System or Math classes in java and use them directly?
Because the methods of Math are declared as static methods, and because System.in / System.out / System.err are static variables.
Is there something special about these classes?
No. Any variables or methods that are declared as static will behave that way.
Can we use the classes and methods declared within those classes in same fashion?
I don't really understand what you are asking there. But, if you are asking if you can create an instance of Math or System so that you can do something like this:
Math myMath = new Math();
myMath.min(1, 2);
No, you can't. Neither of those classes has a public constructor, so you can't new them.
And if you could do that, it would be really bad style!
Reference:
Understanding Class Members
First,you cannot make an instance of the class Math,because it has only a single constructor and it's been marked private and you just can't make an instance of it from outside the class.
Snapshot of the source code of the class Math
Second,you don't need to do that.All of the methods in class Math are static,just use the class name and the dot operator and you can invoke any one of them.
System class can't instantiate/create object because this System class have private constructor.
And it's all members and methods are static, that can be accessible directly by Class name.
this simple and valid answer will help you.
We don't instantiate every other class or method because the JVM(Java Virtual Machine) already loads them into the project and hence, we can use these classes again and again. One such example is the main method. These classes/methods are already predefined for us so there is no need for us to instantiate such classes/methods because they are static.
You don't have to instantiate the object in order to use methods of the math class.
Because to use this methods we don't need object. We can directly invoke this.
These type of classes are called static. Here methods can directly invoked by the class itself.
They are already defined in the JVM. We don't need to instantiate to use methods of this class.
My application has the following class:
MyTextField, which extends JTextField.
I, however, need the methods inside MyTextField in the following class:
MyPasswordField, which extends JPasswordField.
Multiple inheritance isn't allowed in Java, and I'd like to avoid to copy-paste 85% of the class because of this. How to overcome this "limitation"?
Use a helper class that defines the shared functionality. Declare a field in each of MyTextField and in MyPasswordField to hold an instance of the helper class. Relay calls to the helper as needed for the shared functionality, which then only needs to be coded once.
Why don't you use Composition instead of Inheritance.
Your MyPasswordField class can contain an instance variable to myTextField, then you can just use the method using your instance and it's methods.
Let me know if I am going on the wrong track and you expect something different.
You can achieve this with the help of a Helper class with static methods, so you don't need keep an instance of the helper class in your testfields classes.
I am building an API for my application as a middle layer between model and the controller.
The model contains all data and low-level function. I have created a new class for API which uses the model but makes things easier for the user and does not let the user to access the data directly.
Now, I would like to prevent the user from accessing the model and let him to use only the functions from API.
How do I do that?
As far as I believe, this can be simply done by specifying whether the method or variable is private or public. The problem is that I have many static fields for global data. Can I restrict access to static fields so that only private functions of API can access them?
Creating a private static field in a class will ensure that ONLY functions in that class will have access to those fields. Also, if the class is re-instantiated (aka new myClass();), those fields will not be recreated; their values will remain intact and global to all instances of myClass.
In addition to the already posted answer:
It depends on what you mean by "restrict access to static fields":
If you want to prevent others from using them directly inadvertently, use the "private" modifier.
But remember that one can still access them via reflection if no other countermeasures have bin put into place.
This holds true also for the "static int foo" case if you don't seal the package since one can easily put another class into the same package which will have access again.
If you are building an API, maybe you want to read the book Practical API Design, Confessions of a Java Framework Architect.
A Method Is Better Than a Field It's better to use methods —typically getters and setters— to access fields than to expose them directly.
A Factory Is Better Than a Constructor You facilitate an API's future evolution when you expose a factory method rather than a constructor.
Make Everything Final For the sake of future evolution, it's better to disallow subclassing ... make your class final.
...
I have build a subclass from a class in Java that has private methods which I want to access in the subclass, I cannot change or edit the superclass. The problem is of course they are private. Suppose I have written the superclass by myself and there were certain reasons why these methods have to be private. I could copy the code in the subclass. But is there a better way (without producing so much lines of code) to get able to work with them when writing a subclass?
Ignoring that your reasons for wanting to do this are potentially very bad (there's no contract for your usage of private variables, so there are no guarantees that they won't change, or disappear completely!) you could probably do what you want using reflection:
Using:
http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getDeclaredField(java.lang.String)
http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible(boolean)
http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html#get(java.lang.Object)
Class c = object.getClass();
Field field = c.getDeclaredField("somePrivateInstanceVariable");
field.setAccessible(true);
Object someValue = field.get(object);
I just want to emphasise that you should consider the reasons for doing this and decide against it! If you own the code that you are extending, consider if you should instead make the field protected instead of private. Remember, hooking into code you're not supposed to have access to breaks OOP principles (you're circumventing encapsulation) and there are no guarantees the code your application depends on won't disappear in an update to the library (so you're also locking yourself down to a fixed version of the lib).
So you tried with "extends" to inherit the methods from the superclass. And of course they are private, but you can use them in the sublass. Making them abstract would force you to rewrite every in private, i see no other option.
Make super class method's protected. It would be only accessible from sub-class and package.
private modifier's are only accessible with in class.
In your case you should declare the private method as protected instead. Read this for more details on the subject.
I am storing a list of classes through (Classname.class) and would like to instantiate one? Is this possible?
newInstance seems to the method I am after but it doesn't support a constructor?
You can use Class.getConstructors (or Class.getConstructor) to get a list of available constructors, and invoke any of them with Constructor.newInstance, which does accept parameters.
Just to add one point I see missing:
You can invoke newInstance directly on the Class object if it has a public null constructor. (Null constructor is the constructor with no arguments.)
Otherwise, you can find constructors via Class.getConstructors() as others have said.
The Java tutorial on reflection covers this well. But yeah, basically Class.getConstructors, then Constructor.newInstance is where it's at.
Java is designed so you can never "trick" it as long as you use the java.lang/java. classes or other standard libraries. One of the most important things of OOP is that objects should be in a defined state, thus you can be safe that the constructor is always run. Even if you're using some strange-looking reflection libraries to get your work done.
So, using Class.forName("me.Test").newInstance(); (or similar) will under-the-hood invoke the Test() constructor for you.
If you want to invoke another constructor the code is something like:
Test test = (Test)Class.forName("Test").getConstructor(String.class).newInstance("Hello World");
Here the getConstructor asks what the constructor looks like (it wants a string) and then you call it with a string.
You cannot construct new classes this way.
If you have the name of a class you can use Class.forName(className) to load/reference a class.
If you have the byte code for a class you want to create you can have a class loader load the byte code and give you the class. This is likely to be more advanced than you intended.
If you have a list of Class objects obtained through class literals, you might as well statically reference the constructors rather than slipping into reflection evilness.