Reading Modifiers
Many elements have modifiers in the Java language: classes, fields, methods, constructors, or method and constructor parameters. These modifiers can modify the visibility of the element there are applied to, or the fact that they can be overridden, or made non-modifiable. The Reflection API gives access to these modifiers, once you have a reference on the element you need to query.
Using getModifiers()
A class or class member may be declared with one or more modifiers which affect its runtime behavior:
- Access modifiers:
public
,protected
, andprivate
- Modifier requiring override:
abstract
- Modifier restricting override:
sealed
,non-sealed
- Modifier restricting to one instance:
static
- Modifier prohibiting value modification or extension:
final
- Modifier forcing strict floating point behavior:
strictfp
- Annotations
Not all modifiers are allowed on all classes or all members, for example an interface cannot be final and an enum cannot be abstract. The class java.lang.reflect.Modifier
contains declarations for some possible modifiers (it does not contain sealed
and non-sealed
). It also contains methods which may be used to decode the set of modifiers returned by the method [Class.getModifiers()`](javadoc:Class.getModifiers()).
You can get the modifiers of a class by calling its getModifiers()
method. This method returns an int
, in which each bit represents a modifier. For instance, if the bit 0 is set, it means that the corresponding member is public. If the bit 3 is set, then the corresponding member is static.
Having to decode the modifiers int
would be cumbersome. Fortunately, the class Modifier
is there to help you. This class provides a collection of static methods, one for each modifier, that decodes this integer for you.
Let us see this method in action on two examples.
Class<?> s = String.class;
int modifiers = s.getModifiers();
System.out.println("Is String final? " + Modifier.isFinal(modifiers));
System.out.println("Is String abstract? " + Modifier.isAbstract(modifiers));
The previous code prints the following:
Is String final? true
Is String abstract? false
Indeed, the String
class is final, and non-abstract.
You can run the same code on the Collection
interface.
Class<?> c = Collection.class;
modifiers = c.getModifiers();
System.out.println("Is Collection final? " + Modifier.isFinal(modifiers));
System.out.println("Is Collection abstract? " + Modifier.isAbstract(modifiers));
The previous code prints the following:
Is Collection final? false
Is Collection abstract? true
Since Collection
is an interface, it is implicitly abstract. The compiler adds this modifier for every interface.
The Member Interface
There are two declarations of this getModifiers()
method:
- one on the
Class
class, - and another one on the
Member
interface, that is implemented by the following classes:Field
,Method
, andConstructor
.
Both methods work in the same way: they return the same int
that you need to decode using the factory methods of the Modifier
class.
Access Flags
Both the Class
class and the Member
interface saw the addition of an accessFlags()
method in Java SE 20. This method returns a set of AccessFlag
instances, that makes the reading of modifiers easier.
AccessFlag
is an enumeration that defines the modifiers you can add on a class, a field, a method, or a constructor.
You can see access flags in action on the following example.
Class<?> c = String.class;
Set<AccessFlag> accessFlags = c.accessFlags();
for (AccessFlag accessFlag : accessFlags) {
System.out.println("accessFlag = " + accessFlag);
}
Running the previous example gives you the following result.
accessFlag = PUBLIC
accessFlag = FINAL
accessFlag = SUPER
Note that some modifiers and access flags have a one-to-one correspondence, but not all of them. You can get more information on this point in the documentatoin of the AccessFlag
enumeration.
Last update: July 19, 2024