There is a BookView.class that has a private method defined as below
public class BookView{
private boolean importBook(String epubBookPath){
//The function that adds books to database.
}
}
I am trying to call this function from a different package. My code is
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
/*Now we add the book information to the sqlite file.*/
TextView textView=(TextView)findViewById(R.id.textView1);
String filename = textView.getText().toString();
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String epubBookPath = baseDir+filename;
Log.i("epubBookPath:",epubBookPath); //No errors till here!
try {
Method m=BookView.class.getDeclaredMethod("importBook");
m.setAccessible(true);//Abracadabra
//I need help from here! How do i pass the epubBookPath to the private importBook method.
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Intent in = new Intent(getApplicationContext(),
CallEPubUIActivity.class);
startActivity(in);
}
EDIT:
I found another public method in the jar file which is doing the above work.
public void jsImportBook(String epubBookPath) {
if (!BookView.this.importBook(epubBookPath))
return;
BookView.this.createBookshelf();
}
If you want to do that you should make it public or make a public wrapper method it.
If thats not possible, you can work your way around it, but thats ugly and bad and you should have really good reasons to do so.
public boolean importBook(String epubBookPath){
//The function that adds books to database.
}
or
public boolean importBookPublic(String epubBookPath){
return importBook(epubBookPath);
}
private boolean importBook(String epubBookPath){
//The function that adds books to database.
}
Also note that if you CAN'T access the method directly in a third-party library than it is most likely INTENDED that way. Take a look at the call hierarchy of the private method and see if you find a public method that does the call to the private one and that also does what you need.
Libraries are often designed in a way that a public method does some checking (all Parameters given, authenticated etc.) and then pass the call to the private method to do the actual work. You almost never want to work around that process.
With reflection, you'll need an instance of BookView to invoke the method with (unless it's a static method).
BookView yourInstance = new BookView();
Method m = BookView.class.getDeclaredMethod("importBook");
m.setAccessible(true);//Abracadabra
Boolean result = (Boolean) m.invoke(yourInstance, "A Path"); // pass your epubBookPath parameter (in this example it is "A Path"
The method you are looking for is Method#invoke(Object, Object...)
Use reflection to get you method and set Accessible as true, then invoke the method using BookView Object instance and required parameters(path string) using statement as below:
Boolean result = (Boolean)method.invoke(bookObject, epubBookPath);
Sample code as below:
Method method = BookView.getDeclaredMethod("importBook");
method.setAccessible(true);
Boolean result = (Boolean)method.invoke(bookObject, epubBookPath);
Private methods cannot be accessed outside the class it is defined.
Make it Public.
Related
I want to find out whether method for some object is being called for that instance or not.
Is it possible in java ?
Like ...
class Button {
public void focus(){}
public void setName(){}
}
class MyTest {
public static void main(String[] args){
Button button = new Button();
button.focus();
// I want to find out on button instance whether focus() or setName() is called or not.
whetherMethodCalled(button);
// OR
whetherMethodCalled(button, 'focus');
whetherMethodCalled(button, 'setName');
}
}
EDIT : Forgot to add Button class is third party class which I cannot modify... Also I want to check in my code whether method has called for given object instance or not on basis of that I have to write some code.
In order to reduce extra work, perhaps profiling your application with JConsole or another tool is good enough to show if certain methods have run. Another option is using a code coverage tool like EMMA which detects dead code. There is a list of open-source profilers for Java at http://java-source.net/open-source/profilers and EMMA is at http://emma.sourceforge.net/.
With some extra work AspectJ could be use to intercept method calls without changing existing code. For example, the following would intercept calls to Button.focus()
#Aspect
public class InterceptButtonMethods {
#Before("execution(* Button.focus())")
public void beforeInvoke() {
System.out.println("Button.focus invoked");
incrementFocusCount();
}
}
If more extra work is ok, there is a way to wrap all calls to the Button's focus() and setName() methods so that they update separate counters in addition to their normal functions. This can be done by extending Button in YourButton class which is identical to Button except for a couple of int counters with getters, setters and increment methods; and countingFocus() and countingSetName() methods which update their counters and call focus() and setName() respectively, such as in outline:
Class YourButton extends Button {
int focusCount;
int setNameCount
int getFocusCount() {return this.focusCount;}
void setFocusCount(int counter) {this.focusCount = counter} // optional to reset counter
void incrementFocusCount() {this.focusCount = getFocusCount() + 1;)
...
void countingFocus() {
incrementFocusCount();
focus()
}
...
}
If it is required in many places and involves complex things, I recommend to use Mockito to test your code. Using that you can verify if the method was invoked (also how many times if invoked)
You can mock the button and verify in your MyTest how many times the method must be called. Using Mockito you can mock and stub your methods(Stubbing voids requires different approach from when(Object) because the compiler does not like void methods inside brackets) and then verify it using verify statement.
verify(mockButton, times(1)).focus();
verify(mockButton, times(1)).setName();
You can write a wrapper class over the 3rd party Button class through which all calls to Button class will be made.
This wrapper class can keep track of whether each method has been called or not
class ButtonCaller {
private Button button = null;
private boolean focusCalled;
private boolean setNameCalled;
public ButtonCaller() {
button = new Button();
focusCalled = false;
setNameCalled = false;
}
public void focus() {
button.focus();
focusCalled = true;
}
public void setName() {
button.setName();
setNameCalled = true;
}
public void whetherMethodCalled(ButtonMethod method) {
switch (method) {
case FOCUS:
return focusCalled;
case SET_NAME:
return setNameCalled;
}
throw new RuntimeException("Unknown ButtonMethod !!!");
}
public static Enum ButtonMethod {
FOCUS,
SET_NAME;
}
}
I am using Kmax to create a DAQ software. The philosophy of the GUI and the code is that every object on the GUI(radio buttons, check boxes, progress bars etc) has to have the same name with the relevant method. For instance an object named BUTTON is linked with the method public void BUTTON(KmaxWidget widget){code}.
My code is
import kmax.ext.*;
public class Runtime implements KmaxRuntime {
KmaxToolsheet tlsh; // Store a reference to the toolsheet environment
KmaxHist hist1D;
KmaxWidget checkBoxWidget;
public void init(KmaxToolsheet toolsheet) {
tlsh = toolsheet; // Save this reference for use in the toolsheet
hist1D = tlsh.getKmaxHist("HIST1D");
checkBoxWidget = tlsh.getKmaxWidget("CHECK_BOX_CALIB_METH");
tlsh.getKmaxWidget("CHECK_BOX_CALIB_METH").setProperty("VALUE", "1");
}
public static boolean stringToBool(String s) {
if (s.equals("1"))
return true;
if (s.equals("0"))
return false;
return true;
}
public void CalibInit(KmaxWidget widget, KmaxHist histo){
histo.setUseXAxisCalibration(stringToBool(widget.getProperty("VALUE")));
histo.update();
}
public void chooseCalib(){
checkBoxWidget = tlsh.getKmaxWidget("CHECK_BOX_CALIB_METH");
checkCalib(checkBoxWidget,hist1D);
}
public void GO(KmaxToolsheet toolsheet){}
public void SRQ(KmaxDevice device) {}
public void HALT(KmaxToolsheet toolsheet) {}
} // End of the Runtime object
In the above code I have the check box CHECK_BOX_CALIB_METH. The problem arises when someone wants to create many objects;one has to create many methods. In the above code you can see what I am trying to do. I want to create a "main" method that will do every function that is needed and then another method will apply those functions to each object.
This code compiles without any errors, but the check box isn't working. So I was thinking if there is a way around this. For instance a method that will include "submethods" that will do the job! Or perhaps a method that will construct methods in a for loop for each radio button, check box, progress bar etc. Something like
for(int i=0; i<number_of_buttons ; i++){public void BUTTON_i(){code}}
The above code may look ridiculous but I don't know what else to think and I really want to avoid having one method for each button.
Is something like that possible or is there another way around this?
EDIT
For instance I have 6 methods that do exactly the same;they just have different names.
public void SET_CALIB_1(KmaxWidget widget) {
double C0 = (getValueFrom("Ch2_1")*getValueFrom("En1_1")-getValueFrom("Ch1_1")*getValueFrom("En2_1"))/(getValueFrom("Ch2_1")-getValueFrom("Ch1_1"));
double C1 = (getValueFrom("En2_1")-getValueFrom("En1_1"))/(getValueFrom("Ch2_1")-getValueFrom("Ch1_1"));
double C2 = 0;
double[] coef = {C0, C1, C2};
hist1.setXCalibration(coef);
hist1.setUseXAxisCalibration(true);
hist1.update();
} // SET_CALIB_1
Is there a way to have a generator method to generate methods like the above?
what are the design goals for this software?
reflection may be a much better way to get access to the members; and/or put all the components into an array for access.
I find that I tend to over-engineer things a lot; since I enjoy building things; but then they get way too complicated and don't work.
so I advise to take a walk (or trudge through the snow) and think about it some more.
Here is the declaration in 'MainActivity.java'
private static String competition = null;
I've created a setter function which adds value to it.
public static void setCompetition(String competition1) {
competition = competition1;
}
I've created a getter function to get the value in another class from the same package:
public static String getCompetition() {
return competition;
}
However it returns null.
Here is how I tried to use it in a function
public void onReceive(Context context, Intent intent) {
with in the class AlarmNotify which extends BroadcastReceiver:
final String competition = MainActivity.getCompetition();
I think you are not invoking setCompetition anywhere. To validate that, try with this piece of code -
public static void setCompetition(String competition1) {
System.out.println("Set competition to "+competition1);
competition = competition1;
}
If you do not see any printed message, then setCompetition is not being invoked. Ensure that this is being invoked.
Here is the mistake I did:
I was calling a network based async task, which takes few seconds to retrieve the data. It works in the background.
I was calling another function which was trying to access these values. It was being fired instantaneously, even before the async task could run. That is why it was returning null.
Async task hadn't returned those values.
Ultimately I put the call to the other function in the postExecute method of the Async.
Hope that helps anyone who makes the same mistake as I did.
I have Java-related question:
I want to know is there a way to create path to class (in program) by using a variable(s).
Im making a program that will download pictures from certain sites and show them to a user. However, different sites have different forms, that's why I have to define a series of functions specific to each. They cannot be put in the same class because functions that preform same job (just for another site) would have to have same names. I'm trying to make adding support for another site later as simple as possible.
Anyway, the question is, could I call a function in program using a variable to determine its location.
For example: code.picturesite.functionINeed();
code is the package containing all of the coding, and picturesite is not a class but rather a variable containing the name of the desired class - that way I can only change value of the variable to call a different function (or the same function in a different class).
I don't really expect that to be possible (this was more for you to understand the nature of the problem), but is there another way to do what I'm trying to achieve here?
Yes, there is a way. It's called reflection.
Given a String containing the class name, you can get an instance like this:
Class<?> c = Class.forName("com.foo.SomeClass");
Object o = c.newInstance(); // assuming there's a default constructor
If there isn't a default constructor, you can get a reference to one via c.getConstructor(param1.getClass(), param2.getClass(), etc)
Given a String containing the method name and an instance, you can invoke that method like this:
Method m = o.getClass().getMethod("someMethod", param1.getClass(), param2.getClass(), etc);
Object result = m.invoke(o, param1, param2, etc);
I'm not immediately seeing anything in your question that couldn't be solved by, instead of having a variable containing a class name, having a variable containing an instance of that class -- to call a function on the class, you would have to know it implements that function, so you could put the function in an interface.
interface SiteThatCanFoo {
void foo();
}
And
class SiteA extends Site implements SiteThatCanFoo {
public void foo() {
System.out.println("Foo");
}
}
Then:
Site currentSite = getCurrentSite(); // or getSiteObjectForName(siteName), or similar
if (SiteThatCanFoo.isAssignableFrom(currentSite.class)) {
((SiteThatCanFoo)currentSite).foo();
}
So you want to do something like this (check ImageDownloader.getImageFrom method)
class SiteADownloader {
public static Image getImage(URI uri) {
System.out.println("invoking SiteADownloader on "+uri);
Image i = null;
// logic for dowlnoading image from siteA
return i;
}
}
class SiteBDownloader {
public static Image getImage(URI uri) {
System.out.println("invoking SiteBDownloader on "+uri);
Image i = null;
// logic for dowlnoading image from siteB
return i;
}
}
// MAIN CLASS
class ImageDownloader {
public static Image getImageFrom(String serverName, URI uri) {
Image i = null;
try {
// load class
Class<?> c = Class.forName(serverName + "Downloader");
// find method to dowload img
Method m = c.getDeclaredMethod("getImage", URI.class);
// invoke method and store result (method should be invoked on
// object, in case of static methods they are invoked on class
// object stored earlier in c reference
i = (Image) m.invoke(c, uri);
} catch (NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException
| InvocationTargetException | ClassNotFoundException e) {
e.printStackTrace();
}
return i;
}
// time for test
public static void main(String[] args) {
try {
Image img = ImageDownloader.getImageFrom("SiteB", new URI(
"adress"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
I am building a user interface in netBeans (coding by hand, more flexible) with multiple toolbars.
What I am trying to do is create an actionListener for each button. I am retrieving names of the functions from XML and parse them to string. I will write implementations for those functions in a separate class, but my problem is the following:
How do I make the link between the function name and the string containing it's name?
Example: String is Open(), function will be Open(someParameter) and in the definitions class there will be static void Open(param).
First of all, consider my comment about your idea of dynamic button behavior resolved from strings being a wrong approach. However if you still need exactly what you asked, what you need is Reflection API.
Here's an example:
Class c = SomeClassWithMethods.class;
Method m = c.getMethod("someMethodName", String.class, Integer.class, Integer.TYPE);
m.invoke(baseObjectFromWhichToCallTheMethod, "stringParam", 10, 5);
Added:
Another option, which is a little bit prettier than reflection, but still a messy design, would be to use a map to link those Strings to methods. The code is a bit longer, but from the Java perspective it is much better than using reflection for your task (unless you have some specific requirement of which I'm not aware). This is how it would work:
//Interface whose instances will bind strings to methods
interface ButtonClickHandler {
void onClick();
}
class SomeClassYouNeed {
//One of the methods that will be bound to "onButtonOneClick()"
public void onButtonOneClick() {
log.info("ButtonOneClick method is called");
}
public void onButtonTwoClick() {
log.info("ButtonTwoClick method is called");
}
//Map that will hold your links
private static Map<String, ButtonClickHandler> buttonActionMap;
//Static constructor to initialize the map
static {
buttonActionMap = new Map<String, ButtonClickHandler>();
buttonActionMap.put("onButtonOneClick()",new ButtonClickHandler() {
#Override
public void onClick() {
onButtonOneClick();
}
});
buttonActionMap.put("onButtonTwoClick()",new ButtonClickHandler() {
#Override
public void onClick() {
onButtonTwoClick();
}
});
}
public void callByName(String methodName) {
final ButtonClickHandler handler = buttonActionMap.get(methodName);
if (handler == null) {
throw new IllegalArgumentException("No handler found by name: "+methodName);
}
handler.onClick();
}
}
After you call callByName("onButtonTwoClick()") it will fetch the respective instance of ButtonClickHandler which will use the static method onButtonTwoClick() to process the click of the button.
It seems to me that you are looking for the equivalent of JS "eval" function in Java. This might help. Nevertheless it is generally not a good idea as #Max stated, you might want to rethink your design.
If i have understood your question correctly you are trying to generate your code files based on some strings taken from a XML file. I can suggest you this library to generate your codes.
For tutorials you can visit this link.
You may even use the Java Reflection API. Here is a link for the tutorial.
Its upto you, that which of the above two you use.