I have simple Start class with public Start(String[] params) constructor, which I'm calling from a non-runnable JAR file from the level of other running Java program. Everything is working in runtime environment. The problem occurs, when I try to call newInstance() method, in order to invoke this Start class.
Class Start looks like this:
public class Start {
public Start(String[] params) {
/* initialize MainStage object */
MainStage stage = new MainStage(params);
stage.show();
// MainStage DO NOT have any restriction about params.length
}
}
And that's how I'm calling Start class:
String[] t = new String[] {"One", "Two", "Three"};
try {
Class<?> clazz = Class.forName("org.plugin.Start");
/* line below throws the mentioned exception */
clazz.getDeclaredConstructor(String[].class).newInstance((Object[]) t);
} catch (Exception e) {
e.printStackTrace();
}
It is worth mentioning, that everything except this IllegalArgumentException goes just perfect, that means - JAR is added to the runtime classpath, class Start is calling out without problem, when it has no parameters in its constructor.
You need to make an array of objects, and put t in it, like this:
clazz.getDeclaredConstructor(String[].class).newInstance(new Object[]{t});
Demo.
The reason Java tells you that you have passed an invalid number of parameters is that your code passes t, an array with three elements, to a constructor that takes a single array parameter. In other words, you were missing an extra level of indirection, because parameters that you pass to methods or constructors need to be wrapped in Object[] that has one element per function parameters.
Related
I decided to split the last part of that question here into a new question here: https://softwareengineering.stackexchange.com/questions/411738/extension-of-classes-where-to-put-behaviour-how-much-direct-access-is-allowe
If i have a lib and i want to use it, i wrote mostly a own class. This class has one method. In that there is the code how to instantiate the lib/framework. Sometimes there are a few more methods, with them i not only instantiate the class but use it. For example if i want to start a http-server i have there a start-method.
class Container
{
TheLib theLib;
public void init() //or a constructor
{
//some init of the theLib
}
public void start() //
{
theLib.doSomething(...)
theLib.doSomethingmore(...);
theLib.start(...);
}
//important!
public TheLib getTheLib()
{
return this.theLib; //after i started configured it and so on, i want of course use all methods,
which the lib have in some other parts in my application
}
}
But it seems not to be the best solution.
Are there any better solutions, that OO is?
Often i also use only one method, a own class for this seems to be here a big overhead?
Exposing the lib breaks encapsulation? Tell-Dont-Ask is also violated?
Everything depend on what you actually need or how you have access to your 'the lib' instance.
public class Container {
private TheLib theLib;
/* #1: Do you already created the instance before? */
public Container(TheLib theLib) {
this.theLib = theLib;
}
/* #2: Do you need to created the instance each time? */
public Container() {
this.theLib = new TheLib();
}
public void start() {
theLib.doSomething(...)
theLib.doSomethingmore(...);
theLib.start(...);
}
public TheLib getTheLib() {
return this.theLib;
}
public static void main(String[] args) {
/* #1 */
TheLib theLib = ...;
Container container = new Container(theLib);
/* #2 */
Container container = new Container();
/* Continue the flow of your program */
container.start();
container.getTheLib().doSomethingEvenMore();
}
}
Or maybe you actually need only one instance of your 'Container' class. In this case, you should look on how to make a singleton: Java Singleton and Synchronization
Anwser: Often i also use only one method, a own class for this seems to be here a big overhead?
Well, in Java, you cannot do formal programming like in C, so everything line of code that you write, or will be using, has to be in a class of some sort.
If your piece of code is small and don't really need an object, static function might do the work.
I am new Programmer ,
And I using andengine to develope a game, i juss keep on gettin this weird warning called
The method disposeSplashScene() from the type SceneManager is never used locally
i wanted to initialize my splash scene and dispose is when its no longer required
here is the code
public void createSplashScene(OnCreateSceneCallback pOnCreateSceneCallback)
{
ResourcesManager.getInstance().loadSplashScreen();
splashScene = new SplashScene();
currentScene = splashScene;
pOnCreateSceneCallback.onCreateSceneFinished(splashScene);
}
private void disposeSplashScene()
{
ResourcesManager.getInstance().unloadSplashScreen();
splashScene.disposeScene();
splashScene = null;
}
That warning means you're never calling the disposeSplashScreen function anywhere. Either you need to call it somewhere, or the function itself is unneeded and can be deleted.
If this function is meant to be called from an outside class, it should be public instead of private.
I have 2 classes, cPuzzlePieces and cShapes. cPuzzlePieces extends cShapes.
Right now I get 2 errors on cPuzzlePeaces.
The first error is on the first line of the def and says:
implacet super constructor cShapes is undefined for default constructor.
The second error on the first line of the construter says
constructor call must be the first staemnt
and it is on the first staement.
Here is my code:
public class cPuzzlePieces extends cShapes{ // first error message is here
int mAmountOfShapes;
Context InContext;
void cPuzzlePieces(Context MyContext) throws IOException
{
super( MyContext); // SECOND ERROR MESSAGE IS HERE
InContext=MyContext;
}
}
public class cShapes
{
cShape[] MyShapes;
public int mAmountOfShapes=0;
boolean AnimationRunning=false;
cShapes(Context InContext) throws IOException
{
}
...
...
}
This
void cPuzzlePieces(Context MyContext) throws IOException
is a method, not a constructor.
Remove the void keyword. Add an appropriate access modifier (if need be). Also check for the IOException. Currently, nothing is throwing it.
Related
"Constructor call must be the first statement in a constructor" issue in Java
Java naming conventions state that class names should start with an uppercase alphanumeric character. Please follow that.
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.
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();
}
}
}