您的位置:首页 > 编程语言 > Java开发

深入理解Java5的反射与注解机制

2017-06-05 15:11 615 查看
1.首先我们需要理解的一个知识点,什么是反射呢?

答:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

2.什么是注解?

答:Annotation(注解)是JDK1.5及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注解是以‘@注解名’在代码中存在的,根据注解数的个数,我们可以将注解分为:标记注解、单值注解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实现对这些元数据(用来描述数据的数据)的访问。另外,你可以在编译时选择代码里的注解是否只存在于源代码级,或者它也能在class文件、或者运行时中出(SOURCE/CLASS/RUNTIME)。

3.如何实现反射?

为了方便这里我直接使用项目中使用过的FtpEntity.java这个类来演示反射。FtpEntity.java内部仅仅实现了getter setter。下面我们一起来研究。

try {
Class cla = FtpEntity.class;//得到需要反射的Class
Object obj = cla.newInstance();//初始化这个对象

Method m1 = cla.getMethod("setServer", String.class);//获取setServer方法,并申明参数类型
Method m2 = cla.getMethod("getServer");//获取getServer方法

m1.setAccessible(true);//设置为执行私有的方法
m2.setAccessible(true);

m1.invoke(obj,"初始化");//执行m1方法
String res = (String) m2.invoke(obj);//执行m2方法 并拿到返回的参数。

System.out.println(res);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//实例化对象
4.注解的使用
在讲解注解之前,我想大家应该都知道java里的@Resource注解把,与它具有相同功能的还有@Autowired。这里我多说一句,那么它们之间有什么区别呢?这两个注解的区是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

我们打开源码观看@Resourse如何编写一个注解。

package javax.annotation;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {

String name() default "";
String lookup() default "";
Class<?> type() default java.lang.Object.class;
enum AuthenticationType {
CONTAINER,
APPLICATION
}
AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
boolean shareable() default true;
String mappedName() default "";
String description() default "";
}
5.注解如何使用?

使用java反射机制拿到每个属性,方法对应的注解。根据注解的参数不用执行不同的操作。

6.演示实现安卓Activity的自动设置视图。

6.1 需求如下
我们在Android开发的时候,总是会写到setContentView方法,为了避免每次都写重复的代码,我们需要使用注解来代替我们做这个事情,只需要在类Activity上声明一个ContentView注解和对应的布局文件就可以了。

6.2 Activity代码如下

@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewUtils.injectContentView(this);
}
}
6.3 定义ContentView注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}

6.4 反射拿注解 自动调用setContentView方法

public static void injectContentView(Activity activity) {
Class a = activity.getClass();
if (a.isAnnotationPresent(ContentView.class)) {
// 得到activity这个类的ContentView注解
ContentView contentView = (ContentView) a.getAnnotation(ContentView.class);
// 得到注解的值
int layoutId = contentView.value();
// 使用反射调用setContentView
try {
Method method = a.getMethod("setContentView", int.class);
method.setAccessible(true);
method.invoke(activity, layoutId);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
6.5就这么简单?

对,就是这么简单。但是如果要实现事件的注解就需要使用Java动态代理了。这个只是将在下一篇博客介绍。有关反射、注解的知识不可能就这么少,需要大家去多研究。注的详细介绍大家就去百度吧。我这里就不班门弄釜了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: