Get the name of the functions called by a class - java

There are two classes A and B in the same package.
how to get name of the functions of class A called by class B.
Restriction is that the code of A and B cannot be modified.

You cannot use Java reflection to do static code analysis tasks like this. The reflection APIs don't provide the information that is needed.
Off the top of my head, I can think of two approaches that will work:
If you only have the ".class" files, then you can use a bytecode library such as BCEL to load the classes and traverse them to identify all of the method calls.
If you have source code, you could also use some existing Java parser library to create ASTs for your code and analyse them.
(The first approach is probably simpler if all you want is a list of class and method names.)

Reflection can be very useful, but very complicated if you don't understand it.
If you have the name of the class, and want to print the methods:
Class c = Class.forName(the_class_name);
for(Method m : c.getMethods()) {
System.out.println(m.toString());
}
If you want the name of a class given any Object:
String className = the_object.getClass().getName();
A combination of the two could look like this:
for(Method m : the_object.getClass().getMethods())
System.out.println(m.toString());
I think what you are asking for is the names of all the methods from A that B calls.
That can't really be done with reflection, mostly because Java doesn't provide any method for doing this.
The API, as always, provides more information. If you look through there, you might come up with a simple work around.

"Class of all the functions called by class A or class B" is confusing. But, If You want to get the class and function name of caller to a method detectsName described in your class A , then following code will be useful to you.
public class A {
public void detectsName() {
Throwable t = new Throwable();
StackTraceElement traceLine = t.getStackTrace()[1];
// t.printStackTrace();
String className = traceLine.getClassName();
String methodName = traceLine.getMethodName();
int lineNumber = traceLine.getLineNumber();
System.out.println(className);
System.out.println(methodName);
System.out.println(lineNumber);
}
}
If you call this method from any other class say - B, it will be detected.
public class B {
public static void main(String[] args) {
A a = new A();
a.detectsName();
}
}

Dependency Finder can do queries for this. Its approach is to generate meta data in XML and then use regexp based comparison. You may be specifically looking for feature called 'closure' with inbound reference..

Related

How to append a method to existing class using annotation processing in java / kotlin?

I'm new to annotation processing and code generation. I want to find out how can I perform such operation like appending new method to existing class. Here is an example of what I want to do:
Assume that we have a class with with custom annotations like this one:
class SourceClass {
#CustomAnnotation
fun annotatedFun1(vararg argument: Any) {
//Do something
}
#CustomAnnotation
fun annotatedFun2(vararg argument: Any) {
//Do something
}
fun someOtherFun() {
//Do something
}
}
And the result I want to get - extended copy of that class:
class ResultClass {
fun hasFunWithName(name: String): Boolean {
return (name in arrayOf("annotatedFun1", "annotatedFun2"))
}
fun callFunByName(name: String, vararg arguments: Any) {
when (name) {
"annotatedFun1" -> annotatedFun1(*arguments)
"annotatedFun2" -> annotatedFun2(*arguments)
}
}
fun annotatedFun1(vararg argument: Any) {
//Do something
}
fun annotatedFun2(vararg argument: Any) {
//Do something
}
fun someOtherFun() {
//Do something
}
}
I've already found out how to create annotation processor. I'm looking for a method to save all existing fields, properties and methods in source class and to append a few more methods to it.
If it is possible to modify class without creating new one - it would be perfect, but in all tutorials only new classes are created and I didn't find any example where all contents of source class are being copied to another one.
Please, do not advise to use reflection. I need this for android and so reflection is not the option cause of resources cost. I'm looking for compile-time solution.
It is required for custom script language implemented in app and should be used to simplify wrapper classes structure. When this job is done directly in code - it looks awful when such method count exceeds 20 per class.
Here is a good example of Java Annotation Processing I recently worked with.
It's an implementation of #Immutable annotation.
Check out ByteBuddy or Kotlin Poet to understand how additional code generation works.
For Kotlin you do almost the same, check this manual for Kotlin-specific steps.
With Kotlin, you can use extension functions and that is the recommended way of adding new functionality to existing classes that you don't control. https://kotlinlang.org/docs/reference/extensions.html
You may be abel to follow the pattern used by Project Lombok. See How does lombok work? or the source code for details.
Another option would be to write a new class that extends your source class:
class ResultClass : SourceClass {
fun hasFunWithName(name: String): Boolean {
return (name in arrayOf("annotatedFun1", "annotatedFun2"))
}
fun callFunByName(name: String, vararg arguments: Any) {
when (name) {
"annotatedFun1" -> annotatedFun1(*arguments)
"annotatedFun2" -> annotatedFun2(*arguments)
}
}
}
Or perhaps use composition instead and implemnent cover methods for all the public methods in SourceClass.
If you are not tied to doing this using annotation processing, you could use a separate piece of custom code to process the source code files before compiling. Maybe use a regular expression like /#CustomAnnotation\s+.*fun (\w+)\s*\(([^)]*)\)/gm (Test on Regex101) to find the annotated methods.
If I understood the requirement correctly, the goal is to implement something like described below.
You have a source file C.java that defines the class C like this:
public final class C
{
#Getter
#Setter
private int m_IntValue;
#Getter
#Constructor
private final String m_Text;
}
And now you want to know how to write an annotation processor that jumps in during compilation and modifies the source from C.java that the compiler sees to something like this:
public final class C
{
private int m_IntValue;
public final int getIntValue() { return m_IntValue; }
public final void setIntValue( final int intValue ) { m_IntValue = intValue; }
private final String m_Text;
public final String getText() { return m_Text; }
public C( final String text ) { m_Text = text; }
}
The bad news is, that this is not possible … not with an annotation processor, not for Java 15.
For Java 8 there was a way, using some internal classes with reflection to convince the AP to manipulate the already loaded source code in some way and let the compiler compile it a second time. Unfortunately, it failed more often than it worked …
Currently, an annotation processor can only create a new (in the sense of additional) source file. So one solution could be to extend the class (of course, that would not work for the sample class C above, because the class itself is final and all the attributes are private …
So writing a pre-processor would be another solution; you do not have a file C.java on your hard drive, but one named C.myjava that will be used by that preprocessor to generate C.java, and that in turn is used by the compiler. But that is not done by an annotation processor, but it may be possible to abuse it in that way.
You can also play around with the byte code that was generated by the compiler and add the missing (or additional) functionality there. But that would be really far away from annotation processing …
As a summary: today (as of Java 15), an annotation processor does not allow the manipulation of existing source code (you cannot even exclude some source from being compiled); you can only generate additional source files with an annotation processor.

nameof equivalent in Java

C# 6.0 introduced the nameof() operator, that returns a string representing the name of any class / function / method / local-variable / property identifier put inside it.
If I have a class like this:
class MyClass
{
public SomeOtherClass MyProperty { get; set; }
public void MyMethod()
{
var aLocalVariable = 12;
}
}
I can use the operator like this:
// with class name:
var s = nameof(MyClass); // s == "MyClass"
// with properties:
var s = nameof(MyClass.OneProperty); // s == "OneProperty"
// with methods:
var s = nameof(MyClass.MyMethod); // s == "MyMethod"
// with local variables:
var s = nameof(aLocalVariable); // s == "aLocalVariable".
This is useful since the correct string is checked at compile time. If I misspell the name of some property/method/variable, the compiler returns an error. Also, if I refactor, all the strings are automatically updated. See for example this documentation for real use cases.
Is there any equivalent of that operator in Java? Otherwise, how can I achieve the same result (or similar)?
It can be done using runtime byte code instrumentation, for instance using Byte Buddy library.
See this library: https://github.com/strangeway-org/nameof
The approach is described here: http://in.relation.to/2016/04/14/emulating-property-literals-with-java-8-method-references/
Usage example:
public class NameOfTest {
#Test
public void direct() {
assertEquals("name", $$(Person.class, Person::getName));
}
#Test
public void properties() {
assertEquals("summary", Person.$(Person::getSummary));
}
}
Sadly, there is nothing like this. I had been looking for this functionality a while back and the answer seemed to be that generally speaking, this stuff does not exist.
See Get name of a field
You could, of course, annotate your field with a "Named" annotation to essentially accomplish this goal for your own classes. There's a large variety of frameworks that depend upon similar concepts, actually. Even so, this isn't automatic.
You can't.
You can get a Method or Field using reflection, but you'd have to hardcode the method name as a String, which eliminates the whole purpose.
The concept of properties is not built into java like it is in C#. Getters and setters are just regular methods. You cannot even reference a method as easily as you do in your question. You could try around with reflection to get a handle to a getter method and then cut off the get to get the name of the "property" it resembles, but that's ugly and not the same.
As for local variables, it's not possible at all.
You can't.
If you compile with debug symbols then the .class file will contain a table of variable names (which is how debuggers map variables back to your source code), but there's no guarantee this will be there and it's not exposed in the runtime.
I was also annoyed that there is nothing comparable in Java, so I implemented it myself: https://github.com/mobiuscode-de/nameof
You can simply use it like this:
Name.of(MyClass.class, MyClass::getProperty)
which would just return the String
"property"
It's also on , so you can add it to your project like this:
<dependency>
<groupId>de.mobiuscode.nameof</groupId>
<artifactId>nameof</artifactId>
<version>1.0</version>
</dependency>
or for Gradle:
implementation 'de.mobiuscode.nameof:nameof:1.0'
I realize that it is quite similar to the library from strangeway, but I thought it might be better not to introduce the strange $/$$ notation and enhanced byte code engineering. My library just uses a proxy class on which the getter is called on to determine the name of the passed method. This allows to simply extract the property name.
I also created a blog post about the library with more details.
Lombok has an experimental feature #FieldNameConstants
After adding annotation you get inner type Fields with field names.
#FieldNameConstants
class MyClass {
String myProperty;
}
...
String s = MyClass.Fields.myProperty; // s == "myProperty"

Java - how can I loop methods with same name but different parameters

I have class named: ComplexValidator that extends absract class Validator which have two methods:
Validate(Part part);
getAnswer():
I also have validators, lets name them A, B, C and D.
So
AValidator extends Validator
BValidator extends Validator
CValidator extends Validator
DValidator extends Validator
I am not in front of my code right not so I will use pseudo-code.
CValidator takes different parameter than rest of it, A B and D uses part to get filename etc, but CValidator uses numberOfFiles (which are increased in loop (for part p: multipart) so after every time loop is repeated numberoffiles is increased so I can compare it with maxNumberOfFiles field).
Sadly I didnt know how to make abstract class that will take any parameter to method so all methods must take Part part. Cvalidator doesnt use it and I had to make field numberOfFiles static so I can get access to it.
Is there any way to make those validators takes no parameters but no using static?
Is there any way to make abstract class the way that child classes will be able to change arguments it take?
And if it takes other arguments HOW can I loop it all when I have:
List <Validator> validators = new ArrayList<>();
in my ComplexValidator.
and then I add all child validators to it and loop over them like that:
for (Validator v: validators){
validate(part);
}
The types of the parameters of an overriden method must be the same as the original method.
To face your problem I would create a custom class that wraps all the different parameters that you might want to pass to the validate function.
Something like that
class Wrapper{
Part param1;
File param2;
File param3;
}
class Validator{
void validate (Wrapper wrapper);
}
class ValidatorA extends Validate{
void validate (Wrapper wrapper){
//use wrapper.part...
}
}
class ValidatorC extends Validate{
void validate (Wrapper wrapper){
//use wrapper.file...
}
}
You may want to use java reflection. With a Class you can either getMethods and loop throught the methods and getParameterTypes of each method or if you know in advance the types of the method you wish you can getMethod (without s) and provide an array of type.
In your case I would go to the first method and depending on the presence of the second parameter (number of files), invoke the method the good way (with all the parameters needed).

How to access method properties at compile-time?

I would like to access the usual reflection properties of a specific method without relying on Strings.
Is there any way to get from the method-Identifier to its reflection properties, like parameter types?
void run() {
java.lang.reflect.Method m = myMethod.getMethod(); // how?
Class<?>[] argClasses = m.getParameterTypes();
}
int myMethod(String arg) {
// ...
}
The piece myMethod.getMethod() is not valid. It is my way of saying "get from the method-identifier to the java.lang.reflect.Method object".
The string-way I do not want to use would be similar to m = getClass().getDeclaredMethod("myMethod", ...)
I use myMethod like a regular identifier and not as a String, i.e. "myMethod". I think this would be beneficial for refactoring, where someone renames myMethod to hisMethod -- the relation via the String-name would break, where the relation via the identifier would be refactored as well.
In java methods aren't first class citizens, so there is no solutions in Java for this problem.
Yet I had a similar problem and forged a small tool named picklock for this purpose.

How do I use a Java-defined instance method in Lua?

I'm aware that it is possible to use Java defined static methods in Lua, due to the section "Libraries of Java Functions" on http://luaj.org/luaj/README.html.
However I am struggling to find out how I can use the same for instance methods, I have a shortened example here:
private static class CallbackStore {
public void test(final String test) {
}
}
(I am aware that I can use a static method here as well, but it is not possible with the real life scenario)
I am using the following Lua code:
-- Always name this function "initCallbacks"
function initCallbacks(callbackStore)
callbackStore.test("test")
end
Which does not work as it is expecting userdata back, but I give it a string.
And I call the Lua code like this:
globals.load(new StringReader(codeTextArea.getText()), "interopTest").call();
CallbackStore callbackStore = new CallbackStore();
LuaValue initCallbacks = globals.get("initCallbacks");
initCallbacks.invoke(CoerceJavaToLua.coerce(callbackStore));
where the Lua code is returned by codeTextArea.getText()
Bottom line of my question is, how do I make my code running with test as an instance method?
When accessing member functions (in Lua objects in general, not just luaj) you have to provide the this argument manually as the first argument like so:
callbackStore.test(callbackStore,"test")
Or, you can use the shorthand notation for the same thing:
callbackStore:test("test")

Categories

Resources