Execute java instance method via terminal - java

I have an instance. Basic structure is ;
class Instance{
public void load(){
...
}
public boolean execute(){
...
return true;
}
}
As normally we can execute this instance in static void main(String args[]) but how can we execute this instance -> load() -> execute() from terminal or compiled file .class is called within a main method than using reflection to execute defined methods.
Because this instance acts like a script on out project, but we do not define main function into class.
Anyone helps?

I recommend simply adding a public static void main(String args[]) that calls load() and execute() so that your class can be executed from the command line in the usual way. There is little point in over-complicating the problem by building a reflection-based wrapper that will just need its own public static void main(String args[]) anyway.

how can we execute this instance -> load() -> execute() from terminal
You can't.
It'll probably be implemented in Java 9, but for now there is no official way to run methods from the command line.
or compiled file .class is called within a main method than using reflection
As you said, use reflection:
File pathToClass = new File("C:\\Some Folder\\");
Class<?> loaded = null;
try {
ClassLoader loader = new URLClassLoader(new URL[] {pathToClass.toURL()});
loaded = loader.loadClass("some.package.foo.Instance");
} catch(Exception e) {
//do something
}
Object i = loaded.newInstance();
Method method = loaded.getMethod("execute");
Boolean returnValue = (Boolean) method.invoke(i);
I'd recommend not doing this though - there's usually a better way and it just overcomplicates everything.

Related

Get value of System.out.println from main method called via reflection

I'm calling the main method of a class via reflection. For example:
Object o = clasz.getDeclaredConstructor().newInstance();
Method method = clasz.getMethod("main", String[].class);
method.invoke(o, new String[1]);
The called code looks as:
public class Test {
public static void main(String[] args) {
System.out.println("This is a test");
}
}
The reflection works fine and I can see the message in the console.
Is there a way to register something like a binding to the method invocation, for example a PrintWriter or a custom decorated Writer, so I can get the print value as a String?
You can change what System.out is bound to using System.setOut();. You can then make your own:
public class MyTeeingPrinter extends OutputStream {
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final PrintStream original;
public MyTeeingPrinter(PrintStream original) {
this.original = original;
}
#Override public void write(int b) {
original.write(b);
buffer.write(b);
}
public String getAndClear() {
String s = buffer.toString(StandardCharsets.UTF_8);
buffer.reset();
return s;
}
}
And then:
MyTeeingPrinter tee = new MyTeeingPrinter();
System.setOut(new PrintStream(tee));
and now you can invoke tee.getAndClear().
It's a bit of a slog, because whatever code you are running like this is presumably badly designed - it should have instead taken a PrintStream or preferrably an Appendable or Writer, and would write into this writer. Then a trivial one-liner main can be made that just tosses System.out into a writer and hands that to this code you're attempting to run for the case where you just want that code to run and write to sysout, and you can make your own (and stop using reflecting to invoke that main method) and hand that to this code you are running in this scenario.
Note that your reflective code 'works' but is bizarre. There is no need to make a new instance; main is static. The right way is:
Method method = clasz.getMethod("main", String[].class);
method.invoke(null, new String[1]);
That main() method is called in the same process, hence, you can just provide your own stdout implementation/decorator via java.lang.System.setOut(PrintStream) before the reflection magic
An empty string array would work: new String[1] -> new String[0]
You don't need to create a new object to call the static method. Even though java allows calling static methods via objects, this is a bad style and sometimes might cause problems because of name shadowing. Consider the example below:
public class Parent {
public static void main(String[] args) {
Parent child = new Child();
child.test();
}
public static void test() {
System.out.println("Parent.test()");
}
}
class Child extends Parent {
public static void test() {
System.out.println("Child.test()");
}
}
It actually calls Parent.test() even though it's invoked on a Child object

Instantiate an anonymous Java class using reflection

Is it possbile to instantiate an anonymous Java class using reflection.
I have created an anonymous class that I would like to instantiate again later on, is there anyway of doing this?
I can do it with an inner class, but I really need to do it with an anonymous one?
The design of the language says: No, anonymous classes cannot be instantiated except in that one place where you used it.
In practice: Yeah, you can, but, because the specification doesn't say you can (in fact, the specification suggests you can't but doesn't promise that you can't), whatever you write to do this, may (and probably will!) break in a later version of java. Certainly the class file generated will be (this is a newer VM/classfile concept) a nestmate of the other ones, and the module system brings more serious restrictions.
You're also take a wild stab in the dark as to the actual name of the class generated.
In other words, 'before you stop to ask how, perhaps you should think about why', and then reconsider, because this isn't it. If you have a need to use it again later, then name the thing. That's what names are for.
So, the proof of concept - but do not do this, this is silly, eject, abort:
class Test {
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() { public void run() {
System.out.println("Hello!");
}};
r.run();
Class<?> c = Class.forName("Test$1");
Object o = c.getDeclaredConstructor().newInstance();
((Runnable) o).run();
}
}
The above actually works on my particular version of java, my architecture, and the current phase of the moon. It may not work tomorrow. Also note that the constructor of such a thing is perhaps surprising: For example, in this case, the anonymous inner class is made inside a static method and therefore, there is no 'this' argument (normally, the instance is passed along). Whether java will realize that you don't use anything from Test.this inside your anonymous class and therefore omits that from the inner class or not is up to java. You can work around that by querying for all constructors (.getDeclaredConstructors()), but why are you writing a ton of extremely tricky and error-prone code just to hack around something that will likely fail tomorrow?
Please. Don't.
I guess you can. Using standard reflection
class Test {
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() { public void run() {
System.out.println("Hello!");
}};
Class<?> clazz = r.getClass();
Object instance = clazz.newInstance();
System.out.println(instance); // Test$1#7c16905e
System.out.println(instance == r); // false
Method method = clazz.getMethod("run");
method.invoke(instance); // Hello!
}
}
Suppose we defined an anonymous class but didn't save its instance to r. Then we can use Spoon
src/main/java/Test.java
import spoon.Launcher;
import spoon.reflect.CtModel;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtType;
import spoon.reflect.visitor.Filter;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
new Runnable() {
public void run() {
System.out.println("Hello!");
}
};
Launcher launcher = new Launcher();
launcher.addInputResource("src/main/java/Test.java");
CtModel model = launcher.buildModel();
Class<?> clazz = model
.getElements((Filter<CtClass<?>>) CtClass::isAnonymous)
.stream()
.map(CtType::getActualClass)
.findFirst().get();
Object instance = clazz.newInstance();
System.out.println(instance); //Test$1#3fb1549b
Method method = clazz.getMethod("run");
method.invoke(instance); // Hello!
}
}
pom.xml
<dependency>
<groupId>fr.inria.gforge.spoon</groupId>
<artifactId>spoon-core</artifactId>
<version>8.2.0</version>
</dependency>

How is it possible to create object in Class definition itself?

I have some doubt on how this works, consider a simple Java program:
package com.example;
public class Test {
public static void main(String[] args) {
Test t = new Test(); (1) <---- How is this possible
t.print();
}
public void print() {
System.out.println("This is demo");
}
}
This is pretty straightforward program.
However, I have doubt at (1). We are creating an instance of Test, but this is still in the definition of Class Test. How is this possible?
Any explanation to help this would be great.
The instance will be created at run-time.
By then, compile-time is over and all of the code of your application (including all class definition) will be "ready".
Even if you call a constructor of a class that has not been encountered by the JVM up to that point, it will dynamically load the class (in its entirety) before executing the constructor call. Note that a) this might actually fail at run-time, in which case you get a ClassNotFoundError, and b) that cannot happen in your case, because you are calling the constructor of the class from itself (so it must have been loaded already).
The compiler does not run any of your code (not even things like static initializers) during compilation.
But it does make sure (during compilation) that every method or constructor that you are trying to call does in fact exist. Again, this could theoretically fail at runtime (if you mess up class files), in which case you would get a NoSuchMethodError.
First We have to Compile this Porgram using javac After Compilation It will give a Class File.
Now time to Execute Your Class Using java which Invokes JVM and load the Class File to the Class Loader.
java fileName.Class
And here
public static void main(String[] args) {
Test t = new Test(); (1) <---- How is this possible
t.print();
}
All we know static Content (either it is Variable or Method In Java) Of class loaded when ClassLoader loads a Class
As You see Main Method is a static Method. and So, It will Automatically Load into the ClassLoader with class File.
Now JVM First find the public static void main(String... args) in class. Which is a static Content means Its a part of Class but not a part of Class Instance. There is no need of Class Instance to Invoke this MainMethod`.
main(String... args) will be Invoked without getting Instance of the Class. In that Main Method , Your Class is Getting Instantiated
Test t = new Test(); \\here t is reference Variable to Test Class Object.
Now Because Class is loaded into the class Loader new Test(); will create a New Object in Heap memory Area of JVM and your method
public void print() {
System.out.println("This is demo");
}
will be invoked using t.print() Which is a Instance Method (Not Static), So It needs Class Instance to Invoke print() Method.
Q: Test t = new Test(); (1) <---- How is this possible
A: Because of the "static" in public static void main(String[] args)
The "static" means that method "main()" is independent of any specific class object.
You can create any class object you want - including a new "Test" object.
One of the benefits of defining "main" to be static is that you can use "main()" as a test method for the class. Each class can have it's own "main", and you can test each class individually by specifying that class in your Java command line.
For example:
public class MyClass {
public int add2(int n) {
return n + 2;
}
public static void main (String[] args) {
MyClass unitTest = new MyClass ();
System.out.println ("add2(2)=" + unitTest.add2(2));
System.out.println("Expected result=4");
}
}
Then test as follows:
javac MyClass.java
java MyClass
add2(2)=4
Expected result=4
This question has actually been asked and answered many times. For example:
Why is the Java main method static?
==================================================================
Here are a few more examples that illustrate the point:
public class CreateMyself {
private int value = 0;
private static CreateMyself m_singleton = null;
// EXAMPLE 1: You can legally create an instance in the constructor ...
public CreateMyself () {
value++;
// CreateMyself o = new CreateMyself (); // BAD!!! This will cause infinite recursion and crash your stack!!!
System.out.println ("Leaving constructor, value=" + value + "...");
}
// EXAMPLE 2: You can legally create another instance in a normal class member
public void createAnother() {
// But ... WHY??? Is there anything you can't do directly, in your own instance?
CreateMyself newInstance = new CreateMyself ();
System.out.println ("Leaving createAnother, value=" + value + "...");
}
// EXAMPLE 3: This is a common idiom for creating a "singleton"
// NOTE: for this to work, you'd also make the constructor PRIVATE (or protected), so the client *must* call "getInstance()", instead of "new".
public static CreateMyself getInstance () {
if (m_singleton == null) {
m_singleton = new CreateMyself ();
}
System.out.println ("returning singleton instance...");
return m_singleton;
}
// EXAMPLE 4: Creating an instance in "static main()" is a common idiom
public static void main (String[] args) {
CreateMyself newInstance = new CreateMyself ();
newInstance.createAnother ();
}
}
There are many other possible uses. For example, maybe you'll have a static method that does a database lookup and returns a list matching objects.
Note that most of the cases where it's really useful for a class to have a method where it creates an instance of itself are probably static methods.

OOD - Best way to pass config to an external class

In my main method I need to execute a system command. I'm creating an external class to execute the command to keep my main method and app class clean. I'm not sure if the best or cleanest approach would be to do the setup for the command in the main method, or just pass the class the configuration reader and let it pull the necessary things it needs.
Would it make my app more tightly coupled or not follow a good design practice if I just pass the external configuration reader to my SystemCommand class?
Ex - approach one to setup from the main method:
public static void main (String[] args) {
String[] command = {
config.getString("program"),
config.getString("audit.script.name"),
config.getString("audit.script.config")
};
String workingDir = config.getString("audit.directory");
SystemCommand runAudit = new SystemCommand(command, workingDir);
runAudit.start();
}
Or alternatively, I can keep the main method simpler by passing a reference to the config and letting the class pull what it needs from there. It seems this approach is still conceptually simple:
public static void main (String[] args) {
SystemCommand runAudit = new SystemCommand(config);
runAudit.start();
}
There's also a matter of configuring where output and logging is specified, but I haven't thought that through yet.
Keep your main() method simple. Your main() method should not have knowledge about the inner details of other classes in the program. This is because it is an entry point and generally entry points should concern themselves with minimalistic initialization and any other house-keeping tasks. The best way to solve your use case would be :
Create a class SystemCommandFactory which would take in a Config instance as a constructor parameter I assume below that SystemCommand is an interface that could have multiple implementations:
public class SystemCommandFactory
{
private final Config config;
public SystemCommandFactory(Config config)
{
this.config = config;
}
//assume we have a ping system command
public SystemCommand getPingCommand()
{
//build system command
SystemCommand command1 = buildSystemCommand();
return command;
}
//assume we have a copy system command
public SystemCommand getCopyCommand()
{
//build system command
SystemCommand command2 = buildSystemCommand();
return command;
}
}
Now your main method would be as simple as :
public static void main(String[] args)
{
SystemCommandFactory factory = new SystemCommandFactory(new Config());
//execute command 1
factory.getPingCommand().execute();
//execute command 2
factory.getCopyCommand().execute();
}
This way you can see that main() method is simple clean and this design is definitely extensible. Adding a new command say MoveCommand is as simple as :
Create a implementation of the SystemCommand interface for the new
command.
Expose a new method within the factory to get this new MoveCommand
In main() call this new factory method to get the new command and
call execute within it.
Hope this helps.

How do I call a method that has a method as its argument?

Here is a piece of code I have: (what I am trying to do with it is: define a method "renamingrule" in my main class, instantiate a instance of my other class "renamescript" and call its rename method passing as a parameter the "renamingrule" method i've defined in the main class. Everything is well in the RenamScript class, no errors, but i dont know how to call the rename method of the script class from my main class/method. thanks)
public class RenameScript2 {
...
public void rename(Method methodToCall) throws IOException, IllegalAccessException, InvocationTargetException {
try
{
...
String command = "cmd /c rename "+_path+"\\"+"\""+next_file+"\" "
+"\""+methodToCall.invoke(next_file, next_index)+"\"";
p = Runtime.getRuntime().exec(command);
}catch(IOException e1) {} catch(IllegalAccessException IA1) {} catch(InvocationTargetException IT1) {} ;
}//end of rename
} //end of class
//=======================================
public class RenameScriptMain2 {
public static String RenamingRule(String input, int file_row)
{
String output = "renamed file "+(file_row+1)+".mp3";
return output;
}
public static void main(String[] args) throws IOException
{
RenameScript2 renamer = new RenameScript2();
renamer.setPath("c:\\users\\roise\\documents\\netbeansprojects\\temp\\files");
try{
renamer.rename(RenamingRule);
}catch(IOException e2) {};
System.out.println("Done from main()\n\n");
}
} //end of class
You get hold of the Method object through Class.getMethod method. Something like this:
RenameScript2.class.getMethod("rename", parameters);
However, I suggest you consider writing an interface for a class that can perform the renaming, instead of passing a Method.
Such interface could look like
interface RenameAction {
void performRename();
}
To wrap the script in a RenameAction object you would do something like
RenameAction action = new RenameAction() {
void performRename() {
// ...
String command = "cmd /c rename "+_path+"\\"+"\""+next_file+"\" "...
p = Runtime.getRuntime().exec(command);
// ...
}
};
You would then simply do like this:
public void rename(RenameAction action) {
action.performRename();
}
Firstly, aioobe is definitely correct, passing a Method object is a little ugly. I'll assume that you're stuck with it!
To get a method, you'll need to use reflection. The below code grabs the method called toString on the class Integer. It then invokes the toString method.
Method method = Integer.class.getMethod("toString");
Object o = method.invoke(new Integer(7));
System.out.println(o);
Static methods don't need to pass the first parameter to method.invoke
Method method = File.class.getMethod("listRoots");
System.out.println(method.invoke(null));
This shows the reason why you shouldn't use it. That string "toString" and "listRoots" are not refactorable. If someone renames a method, then instead of a compile-time error, you'll get a runtime exception thrown (hence the exceptions you'll need to catch, NoSuchMethodException and IllegalAccessException). It's also much slower to use reflection than to use normal code.
Here is how you should do:
Make class RenameScript2 abstract by adding an abstract method public static String RenamingRule(String input, int file_row)
Then have your main class RenameScriptMain2 extend above class RenameScript2 and provide implementation of the method RenamingRule().
Now inside main method create instance of the class RenameScriptMain2 and call method RenamingRule()

Categories

Resources