How to get method parameter in method without aspect - java

public class Test {
private static void aMethod(String a, int i) {
printParam();
}
private static void aMethod(String a) {
printParam();
}
private static void printParam() {
//System.out.println(gson.toJson(MethodInvocation.getArguments()));
}
}
Is there a way, like MethodInvocation.getArguments but not use aspect(as in the print log case, the method is Changeable, so it's not that convenient), to find out the method's invocation point and print out the method parameters' value without considering the count and type of the parameters?

Related

Java invoke static method with Foreign Context / Check method for recursion

I wanted to check if a method uses recursion. So I wrote this mock up:
public class Main {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = Child.class.getMethod("toBeTested", int.class);
Object result = method.invoke(Super.class, 5);
System.out.println((Integer) result);
}
}
public class Super extends Child{
public static int toBeTested(int a){
System.out.println("validating recursion");
return Child.toBeTested(a);
}
}
public class Child {
public static int toBeTested(int a){
if(a==0)return 0;
return toBeTested(a-1)+1;
}
}
So I tried executing the method in Child with the Context of Super.class hoping in the recursion it would call the Super::toBeTested and I could hence validate the method uses recursion.
Is this even possible the way I tried? If no why not? Any other ideas to check foreign code for recursion...
No, you can't do that because that's not how static methods work, they don't have a "context" that decides what they call at runtime, it's decided at compile time (unless you want to call the classloader the context).
If it was a non-static method then you could do this:
public static class Child extends Super {
public int toBeTested(int a){
System.out.println("validating recursion");
return super.toBeTested(a);
}
}
public static class Super {
public int toBeTested(int a){
if(a==0)return 0;
return toBeTested(a-1)+1;
}
}
public static void main(String args[]) throws Exception {
Method method = Super.class.getMethod("toBeTested", int.class);
Object result = method.invoke(new Child(), 5);
System.out.println((Integer) result);
}
and it would print validating recursion 6 times because the method to be called depends on the runtime type of the object.
To check if static methods call themselves you could read the bytecode of the method (if you have access to it).

Java>=8 call a default method on interface in a static context with instanceof instance?

I was typing and i wonder how can i call a default method on a static context i have a snippet like this.
interface InterfaceWithDefaultMethod{
public default void saySomething(final int a,final int b){System.out.println(String.format("Parameters are %d %d",a,b));}
}
public class StaticsMethodIsNotOverriden2 implements InterfaceWithDefaultMethod {
public static void main(String[] args) {
final StaticsMethodIsNotOverriden2 clazz = new StaticsMethodIsNotOverriden2();
clazz.saySomething(13,20);//Overriden method call with 13 20
clazz.callDefaultSaySomethingFromInstance();//Parameters are 1 2
/*HOW CALL public default void saySomething(final int a,final int b) METHOD HERE....????*/
clazz.InterfaceWithDefaultMethod.super.saySomething(1, 2);/*no enclosing instance of type InterfaceWithDefaultMethod is in scope*/
}
#Override
public void saySomething(int a, int b) {
System.out.println(String.format("Overriden method call with %d %d",a,b));
}
//THIS IS WHAT A WANT TO DO BUT IN STATIC CONTEXT...
private void callDefaultSaySomethingFromInstance(){
InterfaceWithDefaultMethod.super.saySomething(1, 2); /*CALLING DEFAULT METHOD FROM INSTANCE CONTEXT*/
}
}
Is possible to call the default method of InterfaceWithDefaultMethod->saySomething method from static context using a StaticsMethodIsNotOverriden2 instance??
Sorry if the question is plain.
This is not working.
No. A default method is an instance method and, in this case, dynamic binding will kick in. There's no construct for a client of an overridden method to force the invocation of the super-implementation. This can only be done from the subclass (as you've done it in callDefaultSaySomethingFromInstance)
Your only option is to expose a different method in the subclass, and make that method call the implemented interface's default method:
class StaticsMethodIsNotOverriden2 implements InterfaceWithDefaultMethod {
public static void main(String[] args) {
...
clazz.superSaySomething(1, 2);
}
//a different name/signature needed
public void superSaySomething(int a, int b) {
System.out.println(String.format("Forcing super method call with %d %d", a, b));
//the subclass calls default method
InterfaceWithDefaultMethod.super.saySomething(a, b);
}
#Override
public void saySomething(int a, int b) {
System.out.println(String.format("Overriden method call with %d %d", a, b));
}
...
}

Method overloading with collection types doesn't work as expected

Consider the following class with overloaded methods.
public final class TeaParty {
private void travellerListed( Collection o) {
System.out.println("travellerListed(Collection<?>)");
}
private void travellerListed( List s) {
System.out.println("travellerListed(List<Number>)");
}
private void travellerListed( ArrayList i) {
System.out.println("travellerListed(ArrayList<Integer>)");
}
private void method(List t) {
travellerListed(t) ;
}
public static void main(String[] args) {
TeaParty test = new TeaParty();
test.method(new ArrayList ());
}
}
I'm expecting "travellerListed(ArrayList)" as output. But I get "travellerListed(Collection)".
What cause for this unexpected overloading ?
Actually the code you posted results in "travellerListed(List<Number>)", since you are passing the ArrayList to method, whose argument type is a List, so for the call to travellerListed the compiler chooses private void travellerListed( List s), since method overloading resolution is determined by the compile-time type of the arguments (which means private void travellerListed( ArrayList i) cannot be chosen), and a List is a more specific type than a Collection (which explains why private void travellerListed( Collection o) is not chosen).

java seems to choose the overloaded concrete type when getting an parameterized type

I have been stumbled into the following issue, where I have overloaded the method doSomething(), which takes a Boolean or an Object and I call returnSomething() and pass the return value into doSomething(), as the following snippet shows:
public class SomeService {
public <T> T returnSomething() {
return null;
}
public void doSomething(Boolean a) {
System.out.println("Boolean");
}
public void doSomething(Object a) {
System.out.println("object");
}
public static void main(String[] args) {
SomeService someService = new SomeService();
someService.doSomething(someService.returnSomething()); // prints Boolean
}
}
When I run the code it invokes the doSomething((Boolean)).
As the return type of the returnSomething() is type erased to an Object, I would have expected that it would be invoking doSomething((Object)) instead.
Does anyone know if this is as expected behavior that it invokes doSomething((Boolean)) and not doSomething((Object))?
I tried to change the order of these two methods to see if that mattered but it didn't. I also tried to changed the Boolean parameter to an Integer instead and it did behave in the same manner i.e. it invokes the Non-object method.
As a bonus information I also found out if I add an additional method doSomething((Integer)):
IntelliJ 14 return following error message: cannot resolve method doSomething(java.lang.Object)
Eclipse Mars returns the following error message: the method doMethod(Boolean) is ambiguous for the type SomeService
If I alter the order of the definition of doSomething((Integer)) and doSomething((Boolean)) the error message also changes.
public class SomeService {
public <T> T returnSomething() {
return null;
}
public void doSomething(Boolean a) {
System.out.println("Boolean");
}
public void doSomething(Integer a) {
System.out.println("Integer");
}
public void doSomething(Object a) {
System.out.println("object");
}
public static void main(String[] args) {
SomeService someService = new SomeService();
someService.doSomething(someService.returnSomething()); // compilation error
}
}
The reason of this behavior is because of the generic return type.
public <T> T returnSomething() {
return null;
}
will "return" whatever type is needed from the type system perspective and will always choose the most specific type if that is possible. That's why:
it will pick Boolean in the first example (Boolean is more specific type than Object)
will not compile in your second example (Boolean and Integer are not in the same type hierarchy and so none of them is more specific)

Need to print function's actual parameter name used while calling

I want to print function actual parameter name in function.
For reference please refer below code.Here i am trying reflection.
class Refrction
{
public static int a=12;
public static int b=12;
public static int c=13;
public void click(int x)
{
Class cls=Refrction.class;
Field[] fields = cls.getFields();
//here i want to print "a" if function actual parameter is "a" while calling the click function
//here i want to print "b" if function actual parameter is "b" while calling the click function
//here i want to print "c" if function actual parameter is "c" while calling the click function
}
}
public class Reflections extends Refrction
{
public static void main(String[] args)
{
Refrction ab=new Refrction();
ab.click(a);
ab.click(b);
ab.click(c);
}
}
Unless the values of a, b and c never changes (and you can deduce which variable was used as argument by looking at the value) this is not possible. You need to pass more information to the method.
One way would be to do
public void click(int x, String identifier) {
...
}
and call it with
ab.click(a, "a");
Or, you could wrap the values in a (possibly mutable) object, as follows:
class IntWrapper {
int value;
public IntWrapper(int value) {
this.value = value;
}
}
and then do
public static IntWrapper a = new IntWrapper(11);
and
public void click(IntWrapper wrapper) {
if (wrapper == a) {
...
}
...
}

Categories