patternjavaMinor
Determine if Class B uses Class A ( Java Reflection)
Viewed 0 times
reflectionjavausesdetermineclass
Problem
Below is a function that determines if Class B uses Class A.
Currently, it tests for:
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?
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:
This is what you are not testing for:
Are there any bugs in the code?
Yes, there is a potential bug:
If this
so you need to take care about handling that. Your current code is
which could throw a
Other comments:
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()orgetGenericReturnType()for example, you can access the actual type argument by casting the type toParameterizedTypeand callgetActualTypeArguments(). This will return an array of all the type argument of the parameterized type. For example, if a declared field is aMap, 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 returnedso 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.