Lesson 08 - Reflection API, Annotations
Lesson 08 - Reflection API, Annotations
Lesson 08 - Reflection API, Annotations
Lesson goals
2
JVM Structure
*.class CLASS LOADER
Native Libs
Execution Engine Native Interface *.dll
3
JVM Structure. Java Heap
4
JVM Structure. Java Stack
▷ Java Stack memory is used for execution of a thread. They
contain method specific values that are short-lived and references
to other objects in the heap that are getting referred from the
method.
▷ Stack memory is always referenced in LIFO (Last-In-First-Out)
order. Whenever a method is invoked, a new block is created in
the stack memory for the method to hold local primitive values
and reference to other objects in the method.
▷ As soon as method ends, the block becomes unused and become
available for next method.
▷ Stack memory size is very less compared to Heap memory.
5
JVM Structure. Java Heap/Stack
6
ClassLoader
7
ClassLoader
▷ There are three two types of built-in ClassLoader in Java:
▷ Bootstrap Class Loader – It loads JDK internal classes, typically
loads rt.jar and other core classes for example java.lang.* package
classes
▷ Extensions Class Loader (Platform Class Loader) – It loads classes
from the JDK extensions directory, usually $JAVA_HOME/lib/ext
directory (no longer supported from Java 11)
▷ System Class Loader (Application Class Loader) – It loads classes
from the current classpath that can be set while invoking a
program using –cp or –classpath command line options.
8
ClassLoader
9
ClassLoader
▷ class loader for HashMap:
○ null
▷ class loader for this class:
○ jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd
▷ class loader for external lib class:
○ jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd
10
Native Methods
Java Application
//native method declaration
public native int nativeMethod();
JNI
DLL
11
Reflection API
12
Reflection API
13
java.lang.Class
14
Class obtaining
▷ By classloader
15
Class instantiation
try {
Class<App> clazz = App.class;
App app = clazz.newInstance(); //requires no-args constructor
log(app.getName());
} catch (InstantiationException | IllegalAccessException e) {
log("Can not instantiate App by reflection: {}“, e.getMessage());
}
16
Class instantiation
try {
Class[] argTypes = {
int.class, String.class, String.class
};
Constructor<App> constructor = clazz.getConstructor(argTypes);
App app = constructor.newInstance(1, “App", "Some App desc");
log(app); //App{id=1, name=‘App’, description=‘Some App desc’}
} catch (Exception e) {
log("Error: {}", e.getMessage());
}
17
Declared fields
18
Fields
19
Declared methods
20
Methods
21
Invisible field update
Class<User> userClass = User.class;
User user = new User(1, "John", 20, "UTF");
log(user.name); // John
try {
Field nameField = userClass.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(user, "Roberto");
log(user.name); // Roberto
} catch (NoSuchFieldException | IllegalAccessException e) {
log("Error: {}“, e.getMessage());
}
22
Invisible method invocation
try {
Method setter = userClass.getDeclaredMethod("setName", String.class);
nameSetter.setAccessible(true);
nameSetter.invoke(user, "Roberto");
log(user.name); // Roberto
} catch (NoSuchMethodException | IllegalAccessException |
InvocationTargetException e) {
log("Error: {}“, e.getMessage());
}
23
Annotations
@Deprecated
@Override
@SuppressWarnings
@FunctionalInterface
@NonNull
…
24
Annotations. Retention Policy
Retention Policy Description
25
Annotations. Element Type
Element Type Description
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Version {
int min();
int max();
27
Annotations
class ApiClass {
@Version // required attributes are missed
void api0(){}
@Deprecated
@Version(min = 1, max = 2)
void api1(){}
@Version(min = 2, max = 3, description = “Some description")
void api2(){}
}
28
Class annotations usage
29
Method annotations usage
30
Homework
▷ Implement your own annotations:
○ @Codec(algorithm = Algorithms.MORSE/Algorithms.CAESAR/…) – add this annotation to all
codec classes with algorithm name specified
○ @Key – (can be applied for Vigenere only)
○ @Shift - (can be applied for Caesar only)
31
Homework
▷ Change implementation of DecodersFactory and EncodersFactory:
○ Remove switch statement
○ Find class marked by @Codec annotation with algorithm = {specified algorithm} and
implements Decoder/Encoder interface using Reflection API
○ Create instance of found class by no-arg constructor using Reflection API
○ Set values of key/shift (where appliable) from properties using Reflection API (key/shift
should be marked by appropriate annotation)
○ Throw exception in case annotation used incorrectly:
■ @Codec – used for class that does not implements Decoder/Encoder interface
■ @Key – used for algorithm does not use key (for example: Caesar)
■ @Shift – used for class that does use shift (for example: Morse)
32
Links
▷ Reflection API
▷ Using java reflection
▷ Annotations
▷ Java classloaders
33
Thanks!
Any Questions?
34