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
Related
I have several methods in a class that require a boolean to be set to true in order to execute correctly.
I could write the if statement in each method, but it is not convenient if I or someone else wants to ad another method. I or he could forget about the check.
Is there a way in java to execute a method before each other methods (exactly like JUnit does with #BeforeEach ) in a class ?
Edit: Lots of very interesting techniques/answers/concepts proposed. I'll be in touch when I've understood them. Thanks.
Lets make a method turnBooleanTrue() where effectively the boolean is set to true in order for the method to be execute correctly.
Then, you can write up your very own InvocationHandler that would intercept calls to your objects, and then reflectively (using reflection API) invoke first the turnBooleanTrue() method followed by the method to which the call was made.
Will look something like this
public class MyClassInvocationHandler implements InvocationHandler {
// initiate an instance of the class
MyClass myClass = new MyClassImpl();
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// look up turnBooleanTrue() method
Method turnBooleanTrue = myClass.getClass().getMethod("turnBooleanTrue");
// invoke the method
turnBooleanTrue.invoke(...); // toggle the boolean
// invoke the method to which the call was made
// pass in instance of class
Object returnObj = method.invoke(myClass, args);
return returnObj;
}
EDIT
Added some lines to have an object of MyClass initialized. You need something to invoke the method on and maintain the state. Changed util to myClass in the code example above.
Considering my use case, it was a bit overkill to use AOP or other concepts. So I basically did a check in each functions.
With AOP, this is how what you need would look:
// wraps around all methods in your class that have a boolean parameter
#Around(value = "#target(*..YourClass) && args(yourBool)", argNames = "jp,yourBool")
Object scheduleRequest(ProceedingJoinPoint jp, boolean yourBool) {
if (yourBool) {
jp.proceed(yourBool);
} else {
throw new RuntimeException("cannot execute this method!");
}
}
This would handle the case that the method take the boolean you say needs evaluation as its (only) parameter. If it comes from a different source, you may need to wire it into the aspect somehow, that depends on your overall design.
I suggest a simple solution by dividing your workflow in four components.
You have an interface you use to execute commands.
You have an interface that defines which commands you can use.
You have one wrapper that analyzes your boolean value.
You have an implementation of the work performing class, that implements the second interface.
Your wrapper initialize the worker.
Your wrapper exposes an action performing command that accepts the executing interface.
if the boolean is true, pass the worker to the executing interface work method.
the executing interfaces work method calls the work function on the command instance interface, the worker.
See it online: https://ideone.com/H6lQO8
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
WorkDistributer wd = new WorkDistributer();
wd.enable();
wd.performAction((w) -> {w.printHello();});
wd.disable();
wd.performAction((w) -> {w.printHello();});
wd.enable();
wd.performAction((w) -> {w.printAnswer();});
wd.disable();
wd.performAction((w) -> {w.printAnswer();});
}
}
class WorkDistributer
{
private boolean enabled = false;
private ActionPerformer worker;
public WorkDistributer() {
this.worker = new Worker();
}
public void enable() {
enabled = true;
}
public void disable() {
enabled = false;
}
public void performAction(ActionCommand command) {
if(this.enabled) {
command.run(this.worker);
}
}
}
class Worker implements ActionPerformer {
public void printHello() {
System.out.println("hello");
}
public void printAnswer() {
System.out.println(21 * 2);
}
}
interface ActionPerformer {
public void printHello();
public void printAnswer();
}
interface ActionCommand {
public void run(ActionPerformer worker);
}
I've seen this question asked in several ways, but the code is usually specific to the user, and I get lost a little. If I'm missing a nice clear and simple explanation, I'm sorry! I just need to understand this concept, and I've gotten lost on the repeats that I've seen. So I've simplified my own problem as much as I possibly can, to get at the root of the issue.
The goal is to have a main class that I ask for variables, and then have those user-inputted variables assessed by a method in a separate class, with a message returned depending on what the variables are.
import java.io.*;
public class MainClass {
public static void main(String[] args) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
String A;
String B;
try {
System.out.println("Is A present?");
A = reader.readLine();
System.out.println("Is B present?");
B = reader.readLine();
Assess test = new Assess();
} catch (IOException e){
System.out.println("Error reading from user");
}
}
}
And the method I'm trying to use is:
public class Assess extends MainClass {
public static void main(String[] args) {
String A = MainClass.A;
String B = MainClass.B;
if ((A.compareToIgnoreCase("yes")==0) &&
((B.compareToIgnoreCase("yes")==0) | (B.compareToIgnoreCase("maybe")==0)))
{
System.out.println("Success!");
}
else {
System.out.println ("Failure");
}
}
}
I recognize that I'm not properly asking for the output, but I can't even get there and figure out what the heck I'm doing there until I get the thing to compile at all, and I can't do THAT until I figure out how to properly pass values between classes. I know there's fancy ways of doing it, such as with arrays. I'm looking for the conceptually simplest way of sending a variable inputted from inside one class to another class; I need to understand the basic concept here, and I know this is super elementary but I'm just being dumb, and reading what might be duplicate questions hasn't helped.
I know how to do it if the variable is static and declared globally at the beginning, but not how to send it from within the subclass (I know it's impossible to send directly from the subclass...right? I have to set it somehow, and then pull that set value into the other class).
In order to pass variables to an object you have either two options
Constructor - will pass parameter when creating the object
Mutator method - will pass parameters when you call the method
For example in your Main class:
Assess assess = new Assess(A, B);
Or:
Assess assess = new Assess();
assess.setA(A);
assess.setB(B);
In your Assess class you have to add a constructor method
public Assess(String A, String B)
Or setter methods
public void setA(String A)
public void setB(String B)
Also, Assess class should not extend the main class and contain a static main method, it has nothing to do with the main class.
Below there is a code example!
Assess.java
public class Assess {
private a;
private b;
public Assess(String a, String b) {
this.a = a;
this.b = b;
}
public boolean check() {
if ((A.compareToIgnoreCase("yes")==0) &&
((B.compareToIgnoreCase("yes")==0) ||
(B.compareToIgnoreCase("maybe")==0)))
{
System.out.println("Success!");
return true;
} else {
System.out.println ("Failure");
return false;
}
MainClass .java
public class MainClass {
public static void main(String[] args) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
String A;
String B;
try {
System.out.println("Is A present?");
A = reader.readLine();
System.out.println("Is B present?");
B = reader.readLine();
Assess test = new Assess(A, B);
boolean isBothPresent = test.check();
// ................
} catch (IOException e){
System.out.println("Error reading from user");
}
}
I think what you're looking for are method parameters.
In a method definition, you define the method name and the parameters it takes. If you have a method assess that takes a string and returns an integer, for example, you would write:
public int assess(String valueToAssess)
and follow it with code to do whatever you wanted with valueToAssess to determine what integer you wanted to return. When you had decided that i was the int to return, you would put the statement
return i;
into the method; that terminates the method and returns that value to the caller.
The caller obtains the string to be assesed, then calls the method and passes in that string. So it's more of a push than a pull, if you see what I mean.
...
String a = reader.readLine();
int answer = assess(a);
System.out.println("I've decided the answer is " + answer);
Is that what you're looking for?
A subclass will have access to the public members of the superclass. If you want to access a member using {class}.{member} (i.e. MainClass.A) it needs to be statically declared outside of a method.
public class MainClass {
public static String A;
public static String B;
...
}
public class Subclass {
public static void main(String[] args) {
// You can access MainClass.A and MainClass.B here
}
}
Likely a better option is to create a class that has these two Strings as objects that can be manipulated then passed in to the Assess class
public class MainClass {
public String A;
public String B;
public static void main(String[] args) {
// Manipulate A, B, assign values, etc.
Assess assessObject = new Assess(A, B);
if (assessObject.isValidInput()) {
System.out.println("Success!");
} else {
System.out.println("Success!");
}
}
}
public class Assess {
String response1;
String response2;
public Assess (String A, String B) {
response1 = A;
response2 = B;
}
public boolean isValidInput() {
// Put your success/fail logic here
return (response1.compareToIgnoreCase("yes") == 0);
}
}
First you don't need inheritance. Have one class your main class contain main take the main out of Assess class. Create a constructor or setter methods to set the variables in the Assess class.
For instance.
public class MainClass
{
public static void main(String[] Args)
{
Assess ns = new Assess( );
ns.setterMethod(variable to set);
}
}
I'm not 100% sure of your problem, but it sounds like you just need to access variables that exist in one class from a subclass. There are several ways...
You can make them public static variables and reference them as you show in your Assess class. However, they are in the wrong location in MainClass use
public static String A, B;
You can make those variables either public or protected in the parent class (MainClass in your example). Public is NOT recommended as you would not know who or what modified them. You would reference these from the sub-class as if present in the sub-class.
public String A, B; // Bad practice, who modified these?
protected String A, B;
The method that might elicit the least debate is to make them private members and use "accessors" (getters and setters). This makes them accessible programmatically which lets you set breakpoints to catch the culprit that is modifying them, and also let you implement many patterns, such as observer, etc., so that modification of these can invoke services as needed. If "A" were the path to a log file, changing its value could also cause the old log to close and the new one to be opened - just by changing the name of the file.
private String A, B;
public setA(String newValue) {
A = newValue;
}
public String getA() {
return A;
}
BUT ...
Your question says "send to the subclass", but confounded by your knowing how to do this using global variables. I would say that the simplest way is to provide the values with the constructor, effectively injecting the values.
There are other ways, however, your example shows the assessment performed by the constructor. If your Assess class had a separate method to perform the assessment, you would just call that with the variables as arguments.
Your example is confusing since both classes have main methods and the child class does the assessing - I would think you would want the opposite - Have MainClass extend Assess, making "MainClass an Assess'or", let main assign the Strings to Assess' values (or pass them as arguments) to the parent class' "assess" method ("super" added for clarity):
super.setA(local_a);
super.setB(local_b);
super.assess();
or
super.assess(A, B);
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.
What is the difference between ClassName.m() and (new ClassName()).m() m() is a static method.
The difference is that in your second example you are creating an unnecessary object in memory.
It is still calling the same static method for the ClassName class.
It is recommended to use ClassName.m() to avoid unnecessary object creation and to provide context to the developers indicating that a static method is indeed being called.
Three things:
The second has an extra call, which means it might change the outcome. This may be bad, may not, but it is something to consider. See example on how this can work.
The second creates an extra object. That's bad.
The second implies you're calling a method on an object, not on the class itself, which confuses people who read it. That's also bad. See example for how this can be very bad!
Consider the following, reason 1:
class ClassName {
static int nextId;
static int m() { return nextId; }
int id;
ClassName() { id = nextId; nextId++; }
/**
C:\junk>java ClassName
2
2
3
*/
public static void main(String[] args) {
new ClassName();
new ClassName();
System.out.println(ClassName.m());
System.out.println(ClassName.m());
System.out.println((new ClassName()).m());
}
}
Consider the following, adding on to reason 2, as alluded to by #emory:
class ClassName {
// perhaps ClassName has some caching mechanism?
static final List<ClassName> badStructure = new LinkedList<ClassName>();
ClassName() {
// Note this also gives outside threads access to this object
// before it is fully constructed! Generally bad...
badStructure.add(this);
}
public static void main(String[] args) {
ClassName c1 = new ClassName(); // create a ClassName object
c1 = null; // normally it would get GC'd but a ref exist in badStructure! :-(
}
}
Consider the following, reason 3:
class BadSleep implements Runnable {
int i = 0;
public void run() {
while(true) {
i++;
}
}
public static void main(String[] args) throws Exception {
Thread t = new Thread(new BadSleep());
t.start();
// okay t is running - let's pause it for a second
t.sleep(1000); // oh snap! Doesn't pause t, it pauses main! Ugh!
}
}
From an external observer's perspective, there's no difference. Both ways result in a call to the method which can only do the exact same thing in either case. You should never do the second one, though, as it just doesn't make sense to create an object in that case.
If m() is a static method, it's generally correct practice to use ClassName.m() since m() is a method of ClassName, not an object of ClassName.
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()