1. 反射
作用:能够做一般做不到的事情,即获取私有方法 变量 构造方法 或者调用添加@hide的方法。比如XUtil的IOC( https://blog.csdn.net/u011109881/article/details/113762180 ),获取其他应用的资源文件( https://blog.csdn.net/u011109881/article/details/115558620 )都可以通过反射做到
所有的反射功能都是基于我们字节码(class),一个类的 class 在内存中应该只有一份,而且 class 其实也是一个Class对象
每个Class大致有以下3个部分
构造方法(Constructor) 方法(Method) 属性/域(Filed)
下面我们的例子按照如下顺序学习反射
1 反射调用构造方法
1.1 直接调用newInstance创建对象
1.2 调用getDeclaredConstructor来创建对象
1.3获取带参数的构造方法构建的对象
2 反射调用filed
3 反射调用method
3.1 调用无参方法
4 反射调用hide的方法或类
首先构建一个测试类
public class ReflectTestClass {
private static final String TAG = "ReflectTestClass";
private String mName = "hjcai";
// public ReflectTestClass() {
// }
private ReflectTestClass() {
Log.e(TAG, "Constructor without parameters is called");
}
private ReflectTestClass(String name) {
mName = name;
Log.e(TAG, "Constructor with parameter String called");
}
private String getName() {
Log.e(TAG, "getName: " + mName);
return mName;
}
private void setName(String mName) {
this.mName = mName;
Log.e(TAG, "setName: " + mName);
}
}
反射调用的类
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MyActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testReflect();
}
private void testReflect() {
Log.e(TAG, "testReflect: start ======>");
getPrivateConstructor();
Log.e(TAG, "testReflect: end ======>");
getPrivateField();
Log.e(TAG, "getPrivateMethod: start ======>");
getPrivateMethod();
Log.e(TAG, "getPrivateMethod: end ======>");
getHideMethod();
}
// 1 反射调用构造方法
private void getPrivateConstructor() {
try {
// 1.1 直接调用newInstance创建对象
// 只能获取无参 public 的构造方法来构建对象 如果没有无参构造方法 则抛出异常
ReflectTestClass reflectTestClassObj = ReflectTestClass.class.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
try {
// 1.2 调用getDeclaredConstructor来创建对象
Constructor<?> reflectTestClassObj = ReflectTestClass.class.getDeclaredConstructor();
reflectTestClassObj.setAccessible(true);
reflectTestClassObj.newInstance();
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
try {
// 1.3获取带参数的构造方法构建的对象
// 注意区分 ReflectTestClass.class.getConstructor() 这个方法返回的是public的构造方法
Constructor<?> reflectTestClassObj = ReflectTestClass.class.getDeclaredConstructor(String.class);
reflectTestClassObj.setAccessible(true);
reflectTestClassObj.newInstance("AAAA");
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
}
// 2 反射调用filed
private void getPrivateField() {
ReflectTestClass object = null;
try {
Constructor<?> reflectTestClassObj = ReflectTestClass.class.getDeclaredConstructor(String.class);
reflectTestClassObj.setAccessible(true);
object = (ReflectTestClass) reflectTestClassObj.newInstance("AAAA");
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
if (object == null){
return;
}
// 开始访问私有变量
try {
Field field = ReflectTestClass.class.getDeclaredField("mName");
field.setAccessible(true);
String name = (String) field.get(object);
Log.e(TAG, "getPrivateField: mName "+name);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
// 3 反射调用method
private void getPrivateMethod() {
ReflectTestClass object = null;
try {
Constructor<?> reflectTestClassObj = ReflectTestClass.class.getDeclaredConstructor(String.class);
reflectTestClassObj.setAccessible(true);
object = (ReflectTestClass) reflectTestClassObj.newInstance("AAAA");
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
if (object == null){
return;
}
// 开始访问私有method
// 3.1 调用无参方法
try {
Method method = ReflectTestClass.class.getDeclaredMethod("getName");
method.setAccessible(true);
method.invoke(object);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
// 3.2 调用含有参数的方法
try {
Method method = ReflectTestClass.class.getDeclaredMethod("setName",String.class);
method.setAccessible(true);
method.invoke(object,"CCCC");
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
// 4 反射调用hide的方法或类
// AssetManager addAssetPath(String path)是一个hide的方法 调用方式其实和普通方法反射调用一样
private void getHideMethod() {
AssetManager assetManager = null;
try {
assetManager = AssetManager.class.newInstance();
Method addAssetPathMethod = AssetManager.class.getDeclaredMethod("addAssetPath",String.class);// addAssetPath(String path)
addAssetPathMethod.invoke(assetManager,"sdcard/app/red.skin");
} catch (IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
最后的输出:
2021-07-14 21:43:23.363 18882-18882/com.example.d04reflectgeneric E/MyActivity: testReflect: start ======>
2021-07-14 21:43:23.364 18882-18882/com.example.d04reflectgeneric W/System.err: java.lang.IllegalAccessException: void com.example.d04reflectgeneric.reflect.ReflectTestClass.<init>() is not accessible from java.lang.Class<com.example.d04reflectgeneric.MainActivity>
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/ReflectTestClass: Constructor without parameters is called
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/ReflectTestClass: Constructor with parameter String called
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/MyActivity: testReflect: end ======>
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/ReflectTestClass: Constructor with parameter String called
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/MyActivity: getPrivateField: mName AAAA
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/MyActivity: getPrivateMethod: start ======>
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/ReflectTestClass: Constructor with parameter String called
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/ReflectTestClass: getName: AAAA
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/ReflectTestClass: setName: CCCC
2021-07-14 21:43:23.365 18882-18882/com.example.d04reflectgeneric E/MyActivity: getPrivateMethod: end ======>
2. 注解
Xutil的View查找就是利用了反射+注解实现的
我在手写注解框架中简单介绍了注解
https://blog.csdn.net/u011109881/article/details/113854660
即像Xutil一样通过反射和注解去 findViewById
注解比较简单,它只是一个标记,没有具体的功能逻辑代码。
3. 泛型
类泛型 在任何地方出现的,代表的是统一类型
/**
* Created by hjcai on 2021/7/15.
* 类泛型学习
*/
public class Container<T> {//此处的<T>是泛型的声明
// 创建只能存储固定类型的数组
private Object[] items = new Object[10];
public void add(T t) {
items[0] = t;
}
public T get(int index) {
return (T) items[index];
}
}
方法泛型
/**
* Created by hjcai on 2021/7/15.
* <p>
* 方法泛型学习
*/
public class MethodGeneric/*如果把<T>泛型申明移到这里就是类的泛型了 T可以在类内部使用 方法上的<T>的声明就可以删除了*/ {
// <T>表示在方法中声明泛型
public <T> void onSuccess(T result) {
}
}
泛型的上限与下限
/**
* Created by hjcai on 2021/7/15.
* 泛型上限 泛型下限 学习
*/
public class BaseActivity extends AppCompatActivity {
// 泛型上限 传入的参数必须是BaseActivity及其子类
// 上限是BaseActivity
// ? 代表任意的意思
public void startActivity(Class<? extends BaseActivity> clazz) {
Intent intent = new Intent(this, clazz);
startActivity(intent);
}
// 泛型下限 传入的参数必须是BaseActivity及其父类
// 下限是BaseActivity
public void startActivity1(Class<? super BaseActivity> clazz) {
Intent intent = new Intent(this, clazz);
startActivity(intent);
}
}
泛型远不止上面说的这么简单 上述的只是泛型的基本知识 泛型更复杂的还有泛型在元组上的运用 泛型类型的擦除 泛型的缺陷等等 目前其实还有很多地方不太了解 贴一下以前看think in java的笔记
https://blog.csdn.net/u011109881/article/details/102658032
真的是学的越多,感觉自己不知道的就越多。。。