HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Determine if Class B uses Class A ( Java Reflection)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
reflectionjavausesdetermineclass

Problem

Below is a function that determines if Class B uses Class A.

Currently, it tests for:

  • Fields



  • Superclass



  • Constructors



  • Methods



private boolean uses(Class b, Class a){
    // Test for Declared field
    for(Field f:b.getDeclaredFields()){
        if(f.getGenericType().equals(a))
            return true;
    } 
    // Test for Inherietence
    if(b.getSuperclass().getName().equals(a.getName()))
        return true;

    // Test for constructors
    for(Constructor c: b.getDeclaredConstructors()){
        for(Class p : c.getParameterTypes())
            if(p.getName().equals(a.getName()))
                return true;
    }
    // Test for methods 
    for(Method m:b.getDeclaredMethods()){
        for(Class p:m.getParameterTypes())
            if(p.getName().equals(a.getName()))
                return true;
    }

    return false;
}


Is there a better way to write this function?

Is the name of the function terrible?

Are there any bugs in the code?

Is my test holistic, that is, did I test for everything?

Solution

Is my test holistic, that is, did I test for everything?

Currently, this is what you're testing for:

  • Declared fields on the class with getDeclaredFields();



  • A superclass with getSuperclass();



  • The parameters of the declared constructors with getDeclaredConstructors();



  • The parameters of the declared methods with getDeclaredMethods().



This is what you are not testing for:

  • Inherited fields: they are not returned by the call to getDeclaredFields(), so fields inherited from superclasses are not considered;



  • The method return type: you are just checking for the type of the parameters but not the return type with getGenericReturnType();



  • Annotations on the method (getAnnotations()), on the method parameters (getParameterAnnotations()) or on the method return type (getAnnotatedReturnType());



  • Annotations on the class itself with getAnnotations();



  • Exceptions declared to be thrown by the methods with getGenericExceptionTypes(), in the same way, the exceptions declared to be thrown by the declared constructors are also not considered;



  • All the hierarchy of the class: you are only testing for the potential superclass, but not for the potential implemented interfaces or the super-superclasses;



  • If the given class is an array type, you are not testing its component type with getComponentType().



  • For the generic types returned by getDeclaredFields() or getGenericReturnType() for example, you can access the actual type argument by casting the type to ParameterizedType and call getActualTypeArguments(). This will return an array of all the type argument of the parameterized type. For example, if a declared field is a Map, it will return the array [class java.lang.String, class java.lang.Integer].




Are there any bugs in the code?

Yes, there is a potential bug: getSuperclass can return null:


If this Class represents either the Object class, an interface, a primitive type, or void, then null is returned

so you need to take care about handling that. Your current code is

if(b.getSuperclass().getName().equals(a.getName()))


which could throw a NullPointerException.

Other comments:

  • Make sure to always use curly braces, even if it is not strictly needed here. It will make the code less error-prone for the future.



  • This only uses the Reflection API. Determining whether a given class A truly uses a given class B or not would require going into the byte-code to see if there are any references through chained method calls, import statements or local variables.

Code Snippets

if(b.getSuperclass().getName().equals(a.getName()))

Context

StackExchange Code Review Q#126537, answer score: 4

Revisions (0)

No revisions yet.