I've got something along the lines of the following:
public class A {
public void theMethod(Object arg1) {
// do some stuff with a single argument
}
}
public class B {
public void reflectingMethod(Object arg) {
Method method = A.class.getMethod("theMethod", Object.class);
method.invoke(new A(), arg);
}
}
How do I modify that so that I can do the following instead?
public class A {
public void theMethod(Object... args) {
// do some stuff with a list of arguments
}
}
public class B {
public void reflectingMethod(Object... args) {
Method method = A.class.getMethod("theMethod", /* what goes here ? */);
method.invoke(new A(), args);
}
}
A.class.getMethod("theMethod", Object[].class);
Darthenius's suggestion in the comments for the original question worked, once I wrapped my head around how to do it.
public class A {
public void theMethod(ArrayList<Object> args) { // do stuff
}
}
public class B {
public void reflectingMethod(ArrayList<Object> args) {
Method method;
try {
method = A.class.getMethod("theMethod", args.getClass());
method.invoke(new A(), args);
} catch (Exception e) {}
}
}
Related
For example, if I wanted to do something like this to call a method:
myLights.addLight(new Fluorescent(lumens));
in order to create a new object in the Fluorescent class and pass down the lumens data. How would I then set up the method to receive this?
Assuming method is not returning anything.
void addlight(Fluorescent a){
// your logic
}
In your Lights class create a method that accepts a Fluorescent object as an argument.
public void addLight(Fluorescent fluorescent){
// do something
}
Here is a basic example:
public class HelloWorld
{
public static void main(String[] args)
{
Light light = new Light();
light.addLight(new Fluorescent("300 lm"));
System.out.print(light.getLumen());
}
}
public class Light {
private String lumen;
public Light() {
}
public void setLumens(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
public void addLight(Fluorescent fluorescent) {
if(fluorescent.getLumen() != null) {
this.lumen = fluorescent.getLumen();
}
}
}
public class Fluorescent {
private String lumen;
public Fluorescent(String lumen){
this.lumen = lumen;
}
public void setLumen(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
}
Seeing that a Fluorescent is a Light, you might want to look in to inheritance.
Look here for some explanation
Java 101: Inheritance in Java, Part 1
public class Fluorescent() {
public Fluorescent(String lumens) {
// do something
}
}
public class Lights() {
public void addLight(Fluorescent fluorescent) {
// do something
}
}
Is there a way on "Rewriting" a function.
Pseudo:
function a() {print "B"}
function a() {print "C"}
Output: C
Overriding
class MyClass {
public void myMethod () {
System.out.println("MyClass");
}
}
class MySubClass extends MyClass {
#Override
public void myMethod () {
System.out.println("MySubClass");
}
public static void main (String[] args) {
MyClass a = new MyClass();
a.myMethod(); // "MyClass"
MySubClass b = new MySubClass();
b.myMethod(); // "MySubClass"
}
}
In this example, MySubClass overrides the inherited method myMethod.
Overloading
class MyClass {
public void myMethod () {
System.out.println("myMethod");
}
public void myMethod (int i) {
System.out.println(i * 2);
}
public void myMethod (String s) {
System.out.println("Hello, " + s);
}
public static void main (String[] args) {
MyClass a = new MyClass();
a.myMethod(); // "myMethod"
a.myMethod(33); // "66"
a.myMethod("Jeremy") // "Hello, Jeremy"
}
}
In this example, MyClass has multiple definitions of the method myMethod, but they accept different arguments.
Simply rewrite the method in its subclass.
public class Something {
public Something() {
}
public void printHi() {
System.out.println("Hi");
}
}
public class SomethingElse extends Something {
public SomethingElse() {
}
public void printHi() {
System.out.println("I refuse to say hi!");
}
}
Something something = new Something();
something.printHi(); // prints Hi
SomethingElse somethingElse = new SomethingElse();
somethingElse.printHi(); // prints I refuse to say hi!
I have the following need and please help me to write good and abstract class.
Different types of operations is needed based on the type
I have a abstract class,
abstract public class FileHelper{
//Template method
//This method defines a generic structure for parsing data
public void parseDataAndGenerateFile(String fileDownloadType)
{
createHeader(fileDownloadType);
generateFile();
}
//We have to write output in a excel file so this step will be same for all subclasses
public void createHeader(String fileDownloadType)
{
System.out.println('Creating HEADER in EXCEL');
}
public void generateFile(String fileDownloadType)
{
System.out.println('Output generated,writing to XLX');
}
}
public class ExcelDataParser extends FileHelper {
String fileDownloadType="";
}
public class TemplateMethodMain {
public static void main(String[] args) {
String fileDownloadType="expired";
ExcelDataParser csvDataParser=new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile(fileDownloadType);
}
}
Please help me and correct me to have a good way of doing this.
If you want to use an abstract base class, you better should declare an abstract method String getDownloadType() in your abstract base class. These method must be overridden by the derived classes and the type could be fix in the derived class.
For example:
abstract public class FileHelper {
abstract String getFileDownloadType();
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
public void generateFile() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
}
public class ExcelDataParser extends FileHelper {
#Override
String getFileDownloadType() {
return "expired";
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
ExcelDataParser csvDataParser = new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile();
}
}
But if you don't need a class for every type, you also could make the type a variable inside a single class and passing the type to the contructor
For example:
public class CsvFileHelper {
private final String fileDownloadType;
public CsvFileHelper(String type) {
fileDownloadType = type;
}
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
public void generateFile() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
CsvFileHelper csvDataParser = new CsvFileHelper("expired");
csvDataParser.parseDataAndGenerateFile();
}
}
I need to call a method after the constructor has ended, and I have no idea what is the better approach.
I have this class:
class A {
public A() {
// ...
}
public void init() {
// call after the constructor
}
}
How do I call init() after the class A has been created?
You either have to do this on the client side, as so:
A a = new A();
a.init();
or you would have to do it in the end of the constructor:
class A {
public A() {
// ...
init();
}
public final void init() {
// ...
}
}
The second way is not recommended however, unless you make the method private or final.
Another alternative may be to use a factory method:
class A {
private A() { // private to make sure one has to go through factory method
// ...
}
public final void init() {
// ...
}
public static A create() {
A a = new A();
a.init();
return a;
}
}
Related questions:
What's wrong with overridable method calls in constructors?
Java call base method from base constructor
You will need a static factory method to construct the object, call the init method, and finally return the object:
class A {
private A() {
//...
}
private void init() {
//Call after the constructor
}
public static A create() {
A a = new A();
a.init();
return a;
}
}
Notice I have made the constructor and the init() method private, so that they can only be accessed by the factory method. Client code would make objects by calling A.create() instead of calling the constructor.
What did you so far? Are you looking something like this?
Class A {
public A() {
//...
}
public void init() {
//Call after the constructor
}
}
public static void main(String[] args)
{
A a = new A();
a.init();
}
I pick up some ideas and provide an abstractable solution:
class A {
protected A() {
// ...
}
protected void init() {
// ...
}
public static <T extends A> T create(Class<T> type) {
try {
T obj = type.newInstance();
obj.init();
return obj;
} catch (ReflectiveOperationException ex) {
System.err.println("No default constructor available.");
assert false;
return null;
}
}
}
If you want to call method BEFORE constructor you can use initializer block. https://www.geeksforgeeks.org/g-fact-26-the-initializer-block-in-java/
class A {
{
init()
}
public A() {
//todo
}
private final void init() {
//todo
}
}
Why not this :
Class A {
public A() {
//... Do you thing
this.init();
}
public void init() {
//Call after the constructor
}
}
I want to route certain chars to methods, so that when the char is typed in the command-line the method is then executed.
Based on the answer How to call a method stored in a HashMap, I'm mapping these chars to methods by using the "Command" design-pattern.
However I want to generically implement this, so it seems that I need to implement reflection in order to use the Method class as a parameter. My attempt is getting a NullPointerException on the field private Method method in my anonymous class...
Here is my code:
import java.lang.reflect.Method;
public interface InvokesMethod {
public void invokeMethod() throws Exception;
public void setMethod(Method method);
} // end of interface
import java.util.HashMap;
import java.lang.reflect.Method;
public class Terminal {
public HashMap<Character, InvokesMethod> commands;
public Terminal() {
this.commands = new HashMap<Character, InvokesMethod>();
try {
this.setCommand('p',
this.getClass().getDeclaredMethod("printHelloWorld"));
} catch (Exception e) {
e.printStackTrace();
}
}
private void printHelloWorld() {
System.out.println("Hello World!");
}
private void setCommand(char letter, Method method) {
this.commands.put(letter, new InvokesMethod() {
// NullPointerException starts here in the stack-trace:
private Method method;
#Override
public void invokeMethod() throws Exception {
method.invoke(null);
}
#Override
public void setMethod(Method method) {
this.method = method;
}
}).setMethod(method);
}
public void executeCommand(char letter) throws Exception {
this.commands.get(letter).invokeMethod();
}
} // end of class
public class Main() {
public static void main(String[] args) {
Terminal commandLine = new Terminal();
try {
commandLine.executeCommand('p');
} catch (Exception e) {
e.printStackTrace();
}
}
} // end of class
Regards to your code you didn't initiate method. Bear in mind that execute with null you must call public static method:
Your other issue , you didn't initiated interface properly. Here is working example:
InvokesMethodItf
public interface InvokesMethodItf {
public void invokeMethod() throws Exception;
public void setMethod(Method method);
}
InvokesMethod
public class InvokesMethod implements InvokesMethodItf{
private Method method;
#Override
public void invokeMethod() throws Exception {
method.invoke(null);
}
#Override
public void setMethod(Method method) {
this.method = method;
}
}
Terminal
public class Terminal {
public HashMap<Character, InvokesMethodItf> commands;
public Terminal() {
this.commands = new HashMap<Character, InvokesMethodItf>();
try {
this.setCommand('p',
this.getClass().getDeclaredMethod("printHelloWorld"));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void printHelloWorld() {// method.invoke(null) looking for "static" method
System.out.println("Hello World!");
}
private void setCommand(char letter, Method method) {
InvokesMethodItf inv = new InvokesMethod();
inv.setMethod(method);
this.commands.put(letter, inv);
}
public void executeCommand(char letter) throws Exception {
this.commands.get(letter).invokeMethod();
}
}
Main
public class Main {
public static void main(String[] args) {
Terminal commandLine = new Terminal();
try {
commandLine.executeCommand('p');
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output:
Hello World!
Thanks to #Maxim's original suggestion here, I have an alternate solution by setting the methods as Strings in the HashMap instead --
import java.util.HashMap;
import java.lang.reflect.Method;
public class Terminal {
private HashMap<Character, String> commands;
public Terminal() {
this.commands = new HashMap<Character, String>();
this.commands.put('p', "printHelloWorld");
}
private void printHelloWorld() {
System.out.println("Hello World!");
}
public void executeCommand(char letter) throws Exception {
Method method = getClass().getDeclaredMethod(this.commands.get(letter));
method.invoke(this);
}
public class Main {
public static void main(String[] args) {
Terminal commandLine = new Terminal();
try {
commandLine.executeCommand('p');
} catch (Exception e) {
e.printStackTrace();
}
}
} // end of class
Output:
Hello World!
Now to figure out how to pass parameters to the reflected methods...