Reflection
1. Introduction to Reflection
JAVA reflection mechanism is that all attributes and methods of this class can be known for any entity class in running state; any method and attributes can be invoked and modified for any object; this function of dynamic acquisition of information and dynamic invocation of object methods is called anti-java language. The shooting mechanism.
2. The Role of Reflection
Reflection mechanism allows a program to obtain the internal information of any known class at runtime, including modifiers, fields, methods, etc., and can change the contents of fields or call methods at runtime.
(1) Flexible coding, code can be assembled at runtime without source code links between components, reducing code coupling;
(2) There are also dynamic agents, factory mode implementation and so on; but it should be noted that improper use of reflection will result in high resource consumption!
(3) Obtain the information of hidden classes and modify it.
3. Three ways to get Class
(1) By calling getClass() method on the object, it is usually applied to: pass in a type of object, but do not know what the specific class is, using this method, such as passing in an object of type Object;
(2) It is obtained directly by class name and class, which is the most secure and reliable method with higher program performance.
(3) The static method of forName() of Class object is the most commonly used method, but sometimes the exception of ClassNotFoundException is thrown.
Class c3 = Class.forName("com.aj.Person");
(4) Obtain by ClassLoader:
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
There are many ways to access API s such as member variables, member methods, interfaces, superclasses, construction methods and so on through Class classes.
getName(): Gets the full name of the class.
getFields(): Gets the properties of the public type of the class.
getDeclaredFields(): Gets all attributes of the class. Including private declarations and inheritance classes
getMethods(): A method to get the public type of a class.
getDeclaredMethods(): Get all the methods of the class. Including private declarations and inheritance classes
getMethod(String name, Class[] parameterTypes): Gets the specific method of the class, the name parameter specifies the name of the method, and the parameterTypes parameter specifies the parameter type of the method.
getConstructors(): Gets the construction method of the public type of the class.
getConstructor(Class[] parameterTypes): Gets the specific constructor of the class, and the parameterTypes parameter specifies the parameter type of the constructor.
newInstance(): An object of this class is created by its parametric-free constructor.
II. Annotations
- @ Retention represents the retention strategy of annotations:
(1) RetentionPolicy.SOURCE: Annotations are reserved only in source files, and are discarded when Java files are compiled into class files;
(2) RetentionPolicy.CLASS: Annotations are saved to class files, but jvm is abandoned when loading class files and cannot be read by reflection, which is the default life cycle;
(3) RetentionPolicy.RUNTIME: Annotations are not only saved in the class file, but still exist after the jvm loads the class file and can be read by reflection.
These three life cycles correspond to: java source file (. java file) > class file --> bytecode in memory, life cycle len gt h SOURCE < CLASS < RUNTIME, so where the former can work, the latter can also work. In general, if you need to dynamically obtain annotation information at runtime, you can only use RUNTIME annotation; if you want to do some pre-processing operations at compile time, such as generating some auxiliary code (such as ButterKnife), you use CLASS annotation; if you just do some checking operations, such as @Override and @SuppressWarnings, SOURCE annotations are available.
- @ Target represents the possible grammatical location of annotations, where defined annotations can be used. The optional location is as follows:
ElementType.TYPE classes, interfaces (including annotation types) or enumeration declarations
ElementType.FIELD field declaration
ElementType.METHOD Method Statement
Parameter declaration of ElementType.PARAMETER method
Constructor declaration of ElementType.CONSTRUCTOR class
ElementType.LOCAL_VARIABLE Local Variable Statement
ElementType.ANNOTATION_TYPE Annotation Statement
ElementType.PACKAGE package declaration
ElementType. TYPE_PARAMETERJDK 1.8 New, Type parameter declaration
ElementType. TYPE_USEJDK 1.8 New, Type Use Statement
III. IOC Annotation Framework
The content of this study and notes is to write an IOC framework of FindViewById by using the reflection and annotation mentioned above, so as to reduce the repetition of the same code in the project and deepen the understanding of reflection and annotation.
- Notes:
Annotations to FindViewById
package com.bombking.bkchat.baselib.ioc; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface FindViewById { //Indicates that a value can be passed int value(); }
Click on the annotation of the event
package com.bombking.bkchat.baselib.ioc; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) //Runtime public @interface OnClick { int[] value(); }
- IOC Tool Class
package com.bombking.bkchat.baselib.ioc; import android.app.Activity; import android.view.View; import com.bombking.bkchat.baselib.net.CheckNet; import com.bombking.bkchat.baselib.net.NetManagerUtil; import com.bombking.bkchat.utils.ToastUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ViewIoc { // binding annotations public static void bindInit(Activity activity){ findViewById(activity); onClickListener(activity); } /** * find view by id * @param activity */ private static void findViewById(Activity activity){ Class<?> clazz = activity.getClass(); //1. Get all attributes in activity; clazz. getFields () - > Get attributes of public Field[] fields = clazz.getDeclaredFields(); //2. Traversing to get the attributes of the annotations; for (Field field : fields){ FindViewById findViewById = field.getAnnotation(FindViewById.class); //3. Traverse through all attributes, and if the annotation is not empty, get the viewId of the annotation if (findViewById != null){ int viewId = findViewById.value(); //4.findViewById, get view; View view = activity.findViewById(viewId); //5. Dynamic injection of view into activity attributes is equivalent to assigning attributes obtained from annotations to member variables in activity. try { field.setAccessible(true);//Determine properties that can be manipulated privately field.set(activity, view); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } /** * Click Events * @param activity */ private static void onClickListener(final Activity activity) { Class<?> clazz = activity.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (final Method method : methods){ OnClick onClick = method.getAnnotation(OnClick.class); final boolean isNet = method.getAnnotation(CheckNet.class) != null;//Add a network check comment if (onClick != null){ //Gets the id value of the View annotated above all methods; int[] values = onClick.value(); //Traverse to find all view s; for (int viewId : values){ View view = activity.findViewById(viewId); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Check whether the network is available if (isNet){ if (!NetManagerUtil.cureentNetIsAvailable(activity)){ ToastUtils.getInstance().toastShort("Current no network");//Operation without network return; } } //Use reflection method.setAccessible(true);//Private method permissions try { method.invoke(activity); } catch (Exception e) { try { method.invoke(activity, view);//Compatible with view } catch (Exception e1) { e1.printStackTrace(); } e.printStackTrace(); } } }); } } } } }
- Use
@FindViewById(R.id.btn_register) Button button; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewIoc.bindInit(this); }
@OnClick({R.id.bt1,R.id.bt2}) @CheckNet private void getData(){ Toast.makeText(this,"Request background data",Toast.LENGTH_LONG).show(); }
Concluding remarks: I am a newcomer, if there is something wrong, welcome to correct, thank you for reading;