一、反射

动态语言:是指程序在运行是可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。比如常见的JavaScript就是动态语言,除此以外Python等也属于动态语言,而C、C++则不属于动态语言。从反射角度说Java属于半动态语言。

反射机制:指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。在Java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

反射机制主要提供了以下功能:

  •   在运行时判定任意一个对象所属的类;
  •   在运行时创建对象;
  •   在运行时判定任意一个类所具有的成员变量和方法;
  •   在运行时调用任意一个对象的方法;
  •   生成动态代理;

哪里用到反射机制?

  jdbc中有一行代码:Class.forName('com.mysql.jdbc.Driver.class'); 加载MySQL的驱动类。这就是反射,现在很多框架都用到反射机制,hibernate,struts都是用反射机制实现的。

反射的应用场合

  编译时类型和运行时类型

    在Java程序中许多对象在运行时都会出现两种类型:编译时类型和运行时类型。编译时的类型由声明对象时使用的类型来决定;运行时的类型由实际赋值给对象的类型决定。如:

    Person p = new Student();  其中编译时类型为Person,运行时类型为Student。

  编译时类型无法获取具体方法

    程序在运行时还可能接收到外部传入的对象,该对象的编译时类型为Object,但是程序有需要调用该对象的运行时类型的方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息。然而,如果编译时根本无法预知该对象和类属于哪些类,程序只能依靠运行时信息来发现该对象和类的真实信息,此时就必须使用到反射了。

Java反射API

反射API 用来生成JVM中的类、接口或对象的信息。

  1)Class类:反射的核心类,它表示正在运行的Java应用程序中的类和接口。可以获取类的属性、方法等信息。

  2)Field类:Java.lang.reflect 包中的类,表示类的成员变量,可以用来获取和设置类或接口中的属性值。

  3)Method类:Java.lang.refect 包中的类,表示类的方法,可以用来获取类或接口中的某个方法信息或执行方法。

  4)Constructor类:Java.lang.reflect 包中的类,表示类的构造方法。

反射使用步骤(获取class对象、调用对象的方法)

  1)获取想要操作的类的Class对象,它是反射的核心,通过Class对象我们可以任意调用类的方法。

  2)调用Class类中的方法,即就是反射的使用阶段。

  3)使用反射API来操作这些信息。

获取Class对象的4种方法

  调用某个对象的getClass()方法(即对象名.getClass)

    Person p = new Person();

    Class clazz = p.getClass();

  调用某个类的class属性来获取该类对应的Class对象(即类名.class)

    Class clazz = Person.class;

  使用Class 类中的forName()静态方法(最安全/性能最好)

    Class clazz = Class.forName("类的全路径");

  如果是基本类型的包装类,则可以通过调用包装类的Type属性来获得改包装类的Class对象。

    例:Class<?> claszz = Integer.TYPE;

 当我们获得了想要操作的类的 Class 对象后,可以通过 Class 类中的方法获取并查看该类中的方法和属性。
//获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//获取 Person 类的所有方法信息
Method[] method=clazz.getDeclaredMethods();
for(Method m:method){
System.out.println(m.toString());
}
//获取 Person 类的所有成员属性信息
Field[] field=clazz.getDeclaredFields();
for(Field f:field){
System.out.println(f.toString());
}
//获取 Person 类的所有构造方法信息
Constructor[] constructor=clazz.getDeclaredConstructors();
for(Constructor c:constructor){
System.out.println(c.toString());
}

创建对象的两种方法

  Class 对象的newInstance()

    1)使用Class对象的newInstance()方法来创建该Class对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的空构造器。

  调用Constructor对象的newInstance()

    2)先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建Class对象对应类的实例,通过这种方法可以选定构造方法创建实例。

 //获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//使用.newInstane 方法创建对象
Person p=(Person) clazz.newInstance();
//获取构造方法并创建对象
Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
//创建对象并设置属性
Person p1=(Person) c.newInstance("李四","男",20);

JDK动态加载

  Java反射机制允许程序在运行时加载、探知、使用编译期间完全未知的classes。通过Java的反射机制,可以获得程序内部或第三方JAR包的Class、Method、属性、参数等信息。

  动态加载:程序在运行时调用相应方法,即使其他方法是错误的,程序依旧会执行。

  静态加载:程序在编译时执行,在执行过程中加载所有可能执行到的程序。在这种加载方式下,只要加载中一个方法出错,程序就不能运行。

反射机制的优缺点?

优点:
  1)能够运行时动态获取类的实例,大大提高程序的灵活性。

  2)与Java动态编译相结合,可以实现无比强大的功能。

缺点:

  1)使用反射的性能较低。Java反射是要解析字节码,将内存中的对象进行解析。

  解决方案:

    a. 由于JDK的安全检查耗时较多,所以通过setAccessible(true)的方式关闭安全检查来(取消对访问控制修饰符的检查)提升反射速度。

    b. 需要多次动态创建一个类的实例的时候,有缓存的写法会比没有缓存要快很多。

    c. ReflectASM工具类,通过字节码生成的方式加快反射速度。

  2)使用反射相对来说不安全,破坏了类的封装性,可以通过反射获取这个类的私有方法和属性。

二、Java注解

1、概念

  Annotation(注解)是Java提供的一种对源程序中元素关联信息和元数据(metadata)的途径和方法。Annotation(注解)是一个接口,程序可以通过反射来获取制定程序中元素的Annotation对象,然后通过该Annotation对象来获取注解中的元数据信息。

2、四种标准元注解

元注解作用是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其他annotation类型作说明。

  @Target  修饰的对象范围

    @Target说明了annotation所修饰的对象范围:annotation可被用于packages、types(类、接口、枚举、annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在annotation类型的声明中使用了target可更加明晰其修饰的目标。

  @Retention 定义被保留的时间长短

    Retention定义了该annotation被保留的时间长短:表示需要在什么级别保存注解信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效),取值(RetentionPoicy)有:

      SOURCE:在源文件中有效(即源文件保留)

      CLASS:在class文件中有效(即class保留)

      RUNTIME:在运行时有效(即运行时保留)

  @Documented 描述-javadoc

    @Documented用于描述其他类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。

  @Inherited 阐述了某个被标注的类型是被继承的

    @Inherited元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

3、注解处理器

  如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建与使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。下面实现一个注解处理器。

  /1:*** 定义注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
/**供应商编号*/
public int id() default -1;
/*** 供应商名称*/
public String name() default "";
/** * 供应商地址*/
public String address() default "";
}
//2:注解使用
public class Apple {
@FruitProvider(id = 1, name = "陕西红富士集团", address = "陕西省西安市延安路")
private String appleProvider;
public void setAppleProvider(String appleProvider) {
this.appleProvider = appleProvider;
}
public String getAppleProvider() {
return appleProvider; }
/3:*********** 注解处理器 ***************/
public class FruitInfoUtil {
public static void getFruitInfo(Class<?> clazz) {
String strFruitProvicer = "供应商信息:";
Field[] fields = clazz.getDeclaredFields();//通过反射获取处理注解
for (Field field : fields) {
if (field.isAnnotationPresent(FruitProvider.class)) {
FruitProvider fruitProvider = (FruitProvider) field.getAnnotation(FruitProvider.class);//注解信息的处理地方
        strFruitProvicer = " 供应商编号:" + fruitProvider.id() + " 供应商名称:"
          + fruitProvider.name() + " 供应商地址:"+ fruitProvider.address();
     System.out.println(strFruitProvicer);
}
}
}
}
public class FruitRun {
public static void main(String[] args) {
FruitInfoUtil.getFruitInfo(Apple.class);
/***********输出结果***************/
// 供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延
}
}

Java反射及注解的更多相关文章

  1. Java反射,注解,以及动态代理

    Java反射,注解,以及动态代理 基础  最近在准备实习面试,被学长问到了Java反射,注解和动态代理的内容,发现有点自己有点懵,这几天查了很多资料,就来说下自己的理解吧[如有错误,望指正] Java ...

  2. java 反射,注解,泛型,内省(高级知识点)

     Java反射 1.Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs    取得任何一个已知名称的class的内部信息, 包括 ...

  3. java反射获取注解并拼接sql语句

    先建两个注解 分别为 Table 和 Column package com.hk.test; import java.lang.annotation.ElementType; import java. ...

  4. 【转】JAVA反射与注解

    转载自:https://www.daidingkang.cc/2017/07/18/java-reflection-annotations/ 前言 现在在我们构建自己或公司的项目中,或多或少都会依赖几 ...

  5. JavaSE学习总结(十五)—— Java反射与注解

    一.静态语言与动态语言 静态类型语言:是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求.强类型 动态 ...

  6. java反射与注解结合使用(根据传入对象输出查询sql)

    我们在项目开发中有很多地方使用到了注解,关于注解的定义与创建小伙伴可以参考我的文章<java注解>.有任何问题的小伙伴们可以在评论区指出哦,欢迎各位大佬指出问题. 今天我要说的是使用注解与 ...

  7. Java反射与注解

    反射 能够分析类能力的程序称为反射(reflective),代码的这种能力称为"自省".反射机制的功能极其强大,反射机制可以用来: 在运行时分析类的能力 在运行时查看对象,例如,编 ...

  8. Java反射和注解

    反射:http://blog.csdn.net/liujiahan629629/article/details/18013523 注解:http://www.cnblogs.com/peida/arc ...

  9. Java 反射、注解

    1. 泛型 基本用法.泛型擦除.泛型类/泛型方法/泛型接口.泛型关键字.反射泛型! a. 概述 泛型是JDK1.5以后才有的, 可以在编译时期进行类型检查,且可以避免频繁类型转化! // 运行时期异常 ...

随机推荐

  1. Python抓取妹子图,内含福利

    目标抓取全站妹子封面图片全部爬下来以图片标题命名 分析网页数据结构   妹子图首页 接下来找张图片右击点击检查   想要数据 拿到图片链接直接用浏览器可以访问,但是程序下载有反爬虫,图片直接下载不了需 ...

  2. slave_master_info和slave_relay_log_info中的Master_log_pos不一致

    最近在研究mysql的主从,发现一个问题,我在主库做任何修改时,在从库中只有slave_relay_log_info中的Master_log_pos在变化,而slave_master_info中的Ma ...

  3. 如何解决eclipse远程服务器上面的Rabbitmq连接超时问题?

    1.嗯,问题呢,就是一开始安装好RabbitMQ,练习了一下RabbitMQ的使用,但是呢,过了一段时间,我来复习的时候,发现运行出现下面的错误了.后来想想,是自己学习微服务的时候,修改了/etc/h ...

  4. 配置, 映射WebDAV, 并通过IIS网站访问

    服务端 0. 服务端安装IIS时, 选中WebDAV发布, Windows身份验证, 安装完毕后, 打开IIS管理器(inetmgr); 1. 新建网站或使用默认网站, 创建虚拟目录, 虚拟目录物理路 ...

  5. Add an Item to the New Action 在新建按钮中增加一个条目

    In this lesson, you will learn how to add an item to the New Action (NewObjectViewController.NewObje ...

  6. 面试再问ThreadLocal,别说你不会

    转载自:公众号<Java知音> ThreadLocal是什么 以前面试的时候问到ThreadLocal总是一脸懵逼,只知道有这个哥们,不了解他是用来做什么的,更不清楚他的原理了.表面上看他 ...

  7. 松软科技前端课堂:JavaScript 数值方法

    Number 方法帮助您处理数值. Number 方法和属性 原始值(比如 3.14 或 2016),无法拥有属性和方法(因为它们不是对象). 但是通过 JavaScript,方法和属性也可用于原始值 ...

  8. MySQL数据篇(八)-- 存储过程的简单实现

    思考:一般我们的数据都是存储在数据库里面,对于常规的CRUD操作都是用代码实现,比如使用PHP做项目,所有的数据处理都需要主动操作代码实现.如果我们现在有一项目,业务需要在用户下单后,对用户的订单进行 ...

  9. Flask框架后端开发常见错误处理

    1.ValueError: urls must start with a leading slash 这个错误原因可能发生在所有路由相关地方,少加了一个'/'造成的. 2.ImportError: c ...

  10. 使用EA将源码转化为类图

    EA简介: EA 全名 Enterprise Architect,是一款著名的 UML 建模软件.在软件架构设计与逆向工程中具有重要作用.软件十分小巧(< 60MB ),并且有汉化破解版.推荐大 ...