红橙Darren视频笔记 反射注解泛型简介

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

真的是学的越多,感觉自己不知道的就越多。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值