Java Reflection Method Self-Awareness - java

Is there a way, using Java Reflection or otherwise, by which a method can retrieve its own name? Preferably as a string.
Context:- I have a method, which calls another method which would take as input the name of the first method. So I need a way for the first method to be aware of its own name..
Example:-
public class Example
{
static void exampleMethod1()
{
exampleMethod2(name_of_exampleMethod1);
}
static void exampleMethod2(String value)
{
-------some code------------
}
}

As an alternative, you can get it from the current stack:
System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName())

What you ask for can be done by analyzing the stack trace:
new Throwable().getStackTrace()[0].getMethodName();

Related

Possible empty argument when calling method

Hello I have to make a frog catch a fly. I have been given the code they will use to test the method and they will use both
catchFly();
catchFly(3);
is there a way to cater for both possibilities if this were to happen, as I do not know how to check if there are nor arguments
public void catchFly()
{
super.catchFly();
account.credit(100);
super.yellow();
super.jump();
super.green();
}
First define the method which requires the argument:
public void catchFly(int value) {
super.catchFly();
account.credit(value);
super.yellow();
super.jump();
super.green();
}
Which you can use when the value is known:
catchFly(3);
Then for cases where the value isn't known, define an overload which supplies the hard-coded default value:
public void catchFly() {
catchFly(100);
}
Which you can call without an argument:
catchFly();
In cases like this the overloads are generally pass-through methods which invoke the main logic method, simply providing defaults where needed.
yes, it is possible, method overloading is the name for that
just define another method with the same name but other argument (see what is a signature of a method)
public void catchFly(int whatEver){
super.catchFly();
account.credit(whatEver);
super.yellow();
super.jump();
super.green();
}

How to make sure specific parameters are passed to the method?

For example, there is a method public void set_gender(String gender) {}, make sure only "male" or "female" is passed to this method without using enumeration.
Also, how to meet this demand when the method declaration is public void set_gender(String... params) {}?
If there's no such way to realize this, how could I give a warning in IDE when someone is passing a string that this method could not understand, just like how it works in Android Studio when I'm passing a value that is not a flag that defined inside a certain Class.
These are 4 ways I could think of:
Use pre-defined method without parameter:
public void setMale() { /* TODO: Implement */ }
public void setFemale() { /* TODO: Implement */ }
Keep setGender() but use boolean values as its parameter instead of plain String. true means it's male, false female (or the other way around):
public void setGender(boolean male) { /* TODO: Implement */ }
Keep setGender() while using String as its parameter, and throw an IllegalArgumentException if the supplied parameter does not comply with the scope:
public void setGender(String gender) {
if (!"male".equalsIgnoreCase(gender) && !"female".equalsIgnoreCase(gender)) {
throw new IllegalArgumentException("Bad parameter");
}
/* TODO: Implement */
}
Just use enums which, frankly, was designed with this exact use cases in mind. Or IntDef if you're really that worried about performance.
Oh, and as an addition, this question you asked:
If there's no such way to realize this, how could I give a warning in
IDE when someone is passing a string that this method could not
understand, just like how it works in Android Studio when I'm passing
a value that is not a flag that defined inside a certain Class.
They achieve this by using IntDef. ;)
There is StringDef annotation for such cases. You can mark parameter with it and then check it in runtime to verify.

Is reflection execute the method in sequence order?

I have a class file, and I just want to get the list of methods name in that class and print it o/p console.
Just assume that I have following methods in Test1 class
public class Test1{
public static void test1()
{
//some code
}
public static void test2()
{
//some code
}
public static void test3()
{
//some code here.
}
}
I just need to call all the above methods from another class in the specific order.
Like test1() first, and second test2() and followed by test3();
What I did like I just created
Method[] methodarray=Test1.getMethods();
if(methodarray.getName().startWith("test"))
{
sysout(methodarray.getName())
}
The above code print the method in specific order first time but not always. some times it prints 3rd method first and 1method seconds, and finally 2 method.
Can anybody tell me the reason?, and how to resolve this?.
-Sasi
Quote from the JavaDoc: "The elements in the returned array are not sorted and are not in any particular order.".
First of all, it's always best to avoid reflection where possible in a project. Most of the time it's used for testing purposes, or if there really is no other way. That being said, if your methods are indeed called test1, test2 and test3 and you want to execute them in this order, you can use the following steps:
Get all methods from the class (you've done that correctly with Method[] allMethods = Test1.getMethods();)
Loop through them and save all which start with "test" in a seperate list
Order that list with a Custom Sorting to sort the Methods of the seperate list by Method-Name. (See here for an example.)
Invoke & Execute them
Still, it takes three loops (or some Java 8+ LINQ-queries) and it doesn't make the code very clear to anyone, including yourself. It's better to just execute them one by one manually, i.e.:
public void someMethod(){
Test1.test1();
Test1.test2();
Test1.test3();
}
That's just my 2c. From the question it wasn't clear what the purpose of the methods are, or if there are more than three. I would suggest keeping away from reflection unless you really have no other way.
As you can read in the javadoc for getDeclaredMethods(), the returned Method[] doesn't follow a particular order.
You can sort the methods easily by using a LinkedHashMap, or any other Map implementation, that maintains order of elements. For example:
public class MethodTest {
private LinkedHashMap<String, Method> expectedMethodsInOrder;
void testOne(){
}
void testEight(){
}
void beforeEight(){
}
#Before
public void prepareMap(){
expectedMethodsInOrder = new LinkedHashMap<>();
expectedMethodsInOrder.put("testOne", null);
expectedMethodsInOrder.put("beforeEight", null);
expectedMethodsInOrder.put("testEight", null);
}
#Test
public void test(){
Method[] methods = MethodTest.class.getDeclaredMethods();
for(Method m : methods){
String name = m.getName();
if(expectedMethodsInOrder.containsKey(name)){
expectedMethodsInOrder.put(name, m);
}
}
System.out.println(expectedMethodsInOrder.values().toString());
}
}
Output:
[void Main.testOne(), void Main.beforeEight(), void Main.testEight()]
It's working as expected in Windows 7 but not in Windows 8. I have same setup on both environments, like JAVA JDK7, and Eclipse IDE JEE build. But reflection returns the method as Its mentioned in respective class file. But not in Windows 8. It seems to be environment issues.
I just wanna update my things which I observed. Please correct me If there is any other root cause.
-Sasi

Is it possible to create a method to have a method passed as parameter and be called inside it?

well I'm wondering if it's possible to have a method where another method is passed as a parameter, so the first method can call the method passed in param?
Like for instance:
public void goToVisitManagementForm() throws ParseException {
if (isAuthenticated() && userTypeIs("Patient")) {
// I could have this whole block just moved to another method?
Panel newPanel = new Panel("Choose the details for your visit");
Component visitManagementForm = new VisitManagementForm(userData,
this);
newPanel.addComponent(visitManagementForm);
mainWindow.setMainPanel(newPanel);
} else {
authenticate();
}
}
If the code block would be moved to another method and it would be passed as a parameter to this method. How can I achieve that and is this a good practice? Because in this case I have the ifs that I always need to paste in...
What about other aspects of this?
This is called a higher-order function and you cannot do this in Java 7 or below. You can simulate passing functions to other functions through the use of an anonymous class that instantiates some interface the function expects, and then calling the function on that object.
For example, to pass a no-arg function:
interface Function {
void apply();
}
void takesAFunction(Function function) {
function.apply();
}
Then the following code snippet would do what you want:
Function myFunction = new Function() {
#Override
public void apply() {
// your code here.
}
};
takesAFunction(myFunction);
As a side note, reflection is extreme overkill for this type of problem.
You can pass methods as parameters using Java Reflection API.
First, you get a method object from a class:
Class c = MyClass.class;
Method[] methods = c.getMethods();
Method m = // choose the method you want
Then your function can take a Method object as a parameter:
public void aFunction(MyClass o, Method m);
And then inside that function you can invoke the method:
m.invoke(o);
This is a very simple example, where the method doesn't take any parameters. It's pretty easy to expand on this example and add the parameters as well.
Yes, but it is a very advanced procedure. You need to use the Method object. Here is the javadoc on Method:
here is the javadoc:
- http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Method.html
If I am understanding your question correctly, you want to be able to pass a method as a parameter. There really is no 'smooth' way to do this in Java. In objective C, it is built right into the language, (#selector tag)

Setting a Variable in another class results in an error

What I am trying to do is set a value in a variable contained within another class.
this is how I am currently trying to achieve it.
BookingUI Class
private void setCarRegNo()
{
aBooking.setCarRegNo();
}
Booking class
public void setCarRegNo(String regNo)
{
carRegNo = regNo;
}
Yet I keep getting an error saying 'setCarRegNo (java.lang.String) in booking cannot be applied to ()
What is it I am doing wrong? Many thanks
You need to pass a String into the setCarRegNo(String ) of Booking class. The method signature declares that it requires a String argument, and your compiler will complain if you dont supply one.
You have to pass a string into the setCarRegNo() function.
Like this: setCarRegNo("Some string");
In your Booking Class, setCarRegNo takes a single parameter of type String.
When you call it from BookingUI, you are not passing in any parameters.
You need to change BookingUI to something like:
private void setCarRegNo()
{
aBooking.setCarRegNo("CarRegNo");
}
you need to pass a string to your setter. change
aBooking.setCarRegNo();
to
aBooking.setCarRegNo("the registration number');
as a note, you should fully spell out the words of the variables.

Categories

Resources