Android-自定义注解-反射基础
Let’s go
上一章Android-自定义注解-注解基础-自定义注解我们基本上入门了这个注解的基本的东西,具体用途我们还需要学了反射之后就大概有个印象了。然后就可以尝试去使用反射做一些事情,想想butterknife….
认识一下
什么事反射?反射有什么用?我们一起来了解下相关资料…
什么事反射(来自百度百科)
image先了解这点就行。就是可以获取一个类的属性,方法等信息,感觉就是说你可以不用知道那个类到底有什么属性,什么方法,我们就获取所有的属性和方法,然后可以去invoke方法,获得各种定义的变量。
举个例子(下面方法你可以获取到testTv2这个变量,可以获取到onCreate、clickView等方法信息):
public class MainActivity extends AppCompatActivity {
public TextView testTv2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void clickView(){
}
}
知道就行。后面看看怎么操作这个东东。另外了解下一些知识点(来自百度百科)
image阅读一下还是挺有意思的!
反射有什么用?
逆向代码 ,例如反编译
与注解相结合的框架 例如Retrofit
单纯的反射机制应用框架 例如EventBus 2.x
动态生成类框架 例如Gson
举个简单例子:加载游戏可能会涉及到高、低、中帧率模式,一般进入游戏你可以用switch, if等判断,
你也可以用利用类名称产生一个加载实例对象,进而渲染不同的。比如你的渲染类有HighRender, LowRender,
MiddleRender三个渲染类。你可以Class.forName("xxxRender").newInstance()产生一个渲染对象。
紧紧几行代码就可以搞定!貌似酷酷滴...
说点不好的,其实反射动态生成对象的时间有可能比你直接生成的时间慢很多(我之前利用反射findviewbyid发现比直接findviewbyid慢40倍,纳秒级! 还好是纳秒级,不然没法玩了….但是这样也暴露了单纯的反射某些情况获取不是高效的。所以我之前有提到说butterknife不是单纯的反射….理解如果有偏差,后面我们再来更正,学习总是会有不对的地方-实践出真知)
来简单实践下
我们就简单看看反射有哪些方法供我们使用,主要是java.lang.Class,以及java.lang.reflect和两个东东!!!
java.lang.Class和java.lang.reflect
我们想要获取一个类的属性,方法等,就需要Class这个类,这个类获取的属性(filed、method等),然后想要获取具体的method的名称等就需要java.lang.reflect这个包里面很多相关的类,进而通过类具体的方法获取具体的属性值。
看下java.lang.Class相关api,你就大体了解了咯….
看下java.lang.reflect,你就可以利用获取的file, method等对象去调用具体的方法获取值。
imageSo,到这里我们基本知道了,原来可以这样的。那具体我们还是来段测试代码吧,我们就搞个java工程就行,不用非得搞android工程….或者Android工程里面随便新建一个测试类,搞个void main(String[] args)函数就可以运行了塞! (有些测试之前有了解,所以顺便调皮一下….看看,还有些无聊的测试,喵喵)
package com.test.com.mylibrary;
public class TestReflect2 {
private int dontfuck = 0;
public void setDontfuck(int _dontfuck){
this.dontfuck = _dontfuck;
}
}
package com.test.com.mylibrary;
import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestReflect {
private int dontfuck = 0;
public void setDontfuck(int _dontfuck){
this.dontfuck = _dontfuck;
}
public static void main(String[] args){
try {
///< 这个地方要全路径...com.test.com.mylibrary.TestReflect2
TestReflect2 testReflect2 = (TestReflect2)Class.forName("com.test.com.mylibrary.TestReflect2").newInstance();
///< 只能获取public的
Field[] fields = testReflect2.getClass().getFields();
long firstTime = System.nanoTime();
for ( int i = 0; i < fields.length; ++i){
System.out.println("field'name = " + fields[i].getName());
}
System.out.println("循环time1=" + (System.nanoTime() - firstTime));
firstTime = System.nanoTime();
///< 这种遍历效率更好,后空再琢磨....
for ( Field field : fields){
System.out.println("field'name = " + field.getName());
}
System.out.println("循环time2=" + (System.nanoTime() - firstTime));
///< 可以获取private的....
fields = testReflect2.getClass().getDeclaredFields();
for ( int i = 0; i < fields.length; ++i){
System.out.println("delared field'name = " + fields[i].getName());
}
///< 获取所有的,包括继承来的public版本的?? 这个地方可能涉及到class声明一个类之后有哪些变化的机制,有空可以研究下...
Method[] methods = testReflect2.getClass().getMethods();
for (Method method : methods){
System.out.println("method'name = " + method.getName());
}
///< 获取自己声明的-这样方法要少一点
methods = testReflect2.getClass().getDeclaredMethods();
for (Method method : methods){
System.out.println("delared method'name = " + method.getName());
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
看结果:
image可以看一看哟,少年。还是有点意思的哈,有什么不明白的可以看看api文档….api
反射还有很多东西
基础我们到这里,后面继续深入一下下看看Android里面我们怎么搞~~~嗖嗖的…下雨了,记得照顾好记几个…