反射是什么?

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

哪里用到反射机制?

a、JDBC中,利用反射动态加载了数据库驱动程序。
b、Web服务器中利用反射调用了Sevlet的服务方法。
c、Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。
d、很多框架都用到反射机制,注入属性,调用方法,如Spring。

反射有什么作用?

如果给定一个类名,就可以通过反射机制来获取类的所有信息,也可以动态的创建对象和编译;
反射的实现主要借助以下四个类:
1、Class:类的对象;
2、Constructor:类的构造方法
3、Field:类中的属性对象
4、Method:类中的方法对象

获取字节码的三种方式

测试对象Person.java

public class Person {public String name;private int age;public Person(){System.out.println("无参数构造方法!");}public Person(String name,int age){System.out.println("有参数构造方法!"+name+"--->"+age);}public Person(String name){System.out.println("一个有参数构造方法!"+name);}public Person(int age){System.out.println("一个有参数构造方法--->"+age);}public void setName(String name){System.out.println("传入的是:"+name);this.name = name;}public String getName() {System.out.println("调用getName:"+name);return name;}public void setAge(int age) {System.out.println("传入的是:"+age);this.age = age;}public int getAge() {System.out.println("调用getAge:");return age;}private void show(String name){System.out.println("show我的姓名:"+name);}public void show(){System.out.println("show我的姓名null:");}
}

方式一

/*** 方式一:* 使用 .class 获取字节码对象**/
public void getObject1() throws IllegalAccessException, InstantiationException {//原来  new 只能拿到已经知道的  只能是自己// .class  没有.java//通过反射获取对象  变得高级啦 实现变得复杂啦Person person = new Person();//反射//获取字节码对象Class<Person> clazz = Person.class;Class<Person> clazz1 = Person.class;//判断两个字节码对象是不是同一个System.out.println(clazz == clazz1);//true//使用字节码的newInstance()方法实例化对象  无参数构造//Person person1 = clazz.newInstance();}

方式二

/*** 方式二:* 使用Object.getClass()方法 获取字节码对象;* 1、通过反射获取shi有的private* 2、要使用new 不方便*/
public void getObject2(){//创建对象Person person = new Person();//获取字节码对象Class<? extends Person> aClass = person.getClass();//等价上面两步 Class<? extends Person> aClass1 = new Person().getClass();Class<? extends Person> bClass = person.getClass();//判断两个字节码对象是否相等System.out.println(aClass == bClass);//true
}

方式三

/*** 方式三:* 使用 Class 的forName("") 获取字节码文件* @CallerSensitive*     public static Class<?> forName(String className)*                 throws ClassNotFoundException {*         Class<?> caller = Reflection.getCallerClass();*         return forName0(className, true, ClassLoader.getClassLoader(caller), caller);*     }** 这个重点掌握的* 只需要知道class的名称就ok了*/
public void getObject3() throws ClassNotFoundException {//早期//com.tedu.reflect.Person p = new com.tedu.reflect.Person();//定义class名称String className = "com.test.reflect.Person";//使用class名称获取字节码文件Class<?> aClass = Class.forName(className);Class<?> bClass = Class.forName(className);//判断字节码对象System.out.println(aClass==bClass);//规范出发  需要有配置文件
}

获取构造方法

获取无参构造方法

/*** 功能:获取无参构造方法* @throws IllegalAccessException* @throws InstantiationException* @throws ClassNotFoundException*/
public void getConstructor1() throws IllegalAccessException, InstantiationException, ClassNotFoundException {//定义class名称String className = "com.tedu.reflect.Person";//使用className获取字节码对象Class<Person> aClass = (Class<Person>) Class.forName(className);//创建一个对象Person person = aClass.newInstance();//打印//运行show方法person.show();//打印}

获取有参数构造方法

/*** 功能:获取有参数构造方法** @throws NoSuchMethodException* @throws ClassNotFoundException* @throws IllegalAccessException* @throws InvocationTargetException* @throws InstantiationException*/
public void getConstructor2() throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {//定义class名称String className = "com.test.reflect.Person";//使用forName(“”)获取字节码对象Class<?> aClass = Class.forName(className);//获取有参数的构造方法  传入类型的字节码对象Constructor<?> constructor = aClass.getConstructor(String.class, int.class);//获取实例化对象Person instance = (Person) constructor.newInstance("小花", 18);//设置nameinstance.setName("小强");}/*** 功能:自己实现单个的构造方法** @throws NoSuchMethodException* @throws IllegalAccessException* @throws InvocationTargetException* @throws InstantiationException*/
public void getConstructor3() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//使用反射做等同于下面的构造方法//Person xiaohu = new Person("xiaohu");//获取字节码对象Class<Person> personClass = Person.class;//换种方式,换种心情//获取一个参数的构造方法 传入一个String的字节码对象 定义类型Constructor<Person> constructor =personClass.getConstructor(String.class);//实例化对象   new Person("xiaohu");Person person = constructor.newInstance("xiaohu");
}

获取属性

/*** 功能:*    获取属性  public的** @throws NoSuchFieldException* @throws IllegalAccessException* @throws InstantiationException*/public void getField1() throws NoSuchFieldException, IllegalAccessException, InstantiationException {//获取字节码对象Class<Person> personClass = Person.class;//换种方式,换种心情Person person = personClass.newInstance();//通过名称获取属性Field field = personClass.getField("name");//public修饰的//不使用setName方法赋值  对象   设置的值field.set(person,"huhua");//获取name,打印person.getName();//等同于上面Person person1 = new Person();person1.name="huhua";person1.getName();}/*** 功能:不知道属性名称  不知道属性类型** @throws ClassNotFoundException* @throws IllegalAccessException* @throws InstantiationException*/
public void getField3() throws ClassNotFoundException, IllegalAccessException, InstantiationException {//1、获取字节码对象String className = "com.tedu.reflect.Person";Class<?> clazz = Class.forName(className);Object obj = clazz.newInstance();//2、获取字节码的属性 获取所有属性Field[] fields = clazz.getDeclaredFields();//简单/* for (int i=0;i<fields.length;i++){Field field = fields[i];//3、设置属性的访问权限 暴力访问field.setAccessible(true);//获取属性的类型Class<?> type = field.getType();//4、赋值  type要使用包装类型setF(obj,field,type,"xioaxiao");//5、获取属性值System.out.println(field.get(obj));}*///增强for循环for (Field field:fields) {//3、设置属性的访问权限 暴力访问field.setAccessible(true);//获取属性的类型Class<?> type = field.getType();setF(obj,field,type,"xioaxiao");//5、获取属性值System.out.println(field.get(obj));}
}/*** 功能:封装 设置value** @param obj* @param field* @param type* @param value* @throws IllegalAccessException*/
public void setF(Object obj,Field field,Class<?> type,Object value) throws IllegalAccessException {System.out.println(type);//判断类型if (type==String.class){field.set(obj,value);}else if (type==Integer.class){//Iinterger cast()强制装换field.set(obj,type.cast(value));}else if (type==Boolean.class){field.set(obj,type.cast(value));}else if (type==Short.class){field.set(obj,type.cast(value));}else if (type == Long.class){field.set(obj,type.cast(value));}else if (type == Byte.class){field.set(obj,type.cast(value));}else if (type == Double.class){field.set(obj,type.cast(value));}else if (type == Float.class){field.set(obj,type.cast(value));}
}

获取方法

/*** 功能:获取一般方法* @throws ClassNotFoundException* @throws IllegalAccessException* @throws InstantiationException* @throws NoSuchMethodException* @throws InvocationTargetException*/public void getMethod1() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {//1、获取字节码对象String className = "com.tedu.reflect.Person";Class<?> clazz = Class.forName(className);Object obj = clazz.newInstance();//2、获取方法  下面的只能获取public的// Method show = clazz.getMethod("show");// Method show1 = clazz.getMethod("show", String.class);//能够获取所有的方法Method show = clazz.getDeclaredMethod("show");Method show1 = clazz.getDeclaredMethod("show",String.class);//设置访问权限 暴力访问设置  作为黑客专用show1.setAccessible(true);//3、对方法赋值 传入参数 4、使用方法show.invoke(obj);show1.invoke(obj,"xiaoxiao");//---------------******------------------String name = show.getName();int parameterCount = show1.getParameterCount();TypeVariable<Method>[] typeParameters = show.getTypeParameters();}/*** 在日志系统使用** 这个方法非常重要  login*    show(String name)  监控*    传入的值*    传入的类型*    指定我监控的方法*/
public void getMethod2() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {System.out.println("GetClassDemo.getMethod2");//soutm//1、获取字节码对象Class<Person> clazz = Person.class;//实例化对象  调用无参构造方法Person obj = clazz.newInstance();//2、获取字节码对象的方法Method show = clazz.getDeclaredMethod("show", String.class);show.setAccessible(true);//3、赋值和使用Object o = show.invoke(obj, "小小");//获取方法的名称String name = show.getName();System.out.println("方法名称:"+name);//获取方法的参数数量int parameterCount = show.getParameterCount();System.out.println("参数列表数量:"+parameterCount);//获取参数类型Class<?>[] parameterTypes = show.getParameterTypes();//show.getDeclaredAnnotations();for (Object m:parameterTypes) {System.out.println("参数类型:"+m);}//获取返回值类型Class<?> returnType = show.getReturnType();System.out.println("获取返回值类型:"+returnType);
}

应用练习1

NetCard.java

public class NetCard implements PCI {@Overridepublic void open() {System.out.println("net open");}@Overridepublic void close() {System.out.println("net close");}}

SoundCard.java

public class SoundCard implements PCI {public void open(){System.out.println("sound open");}public void close(){System.out.println("sound close");}}

Mainboard.java

public class Mainboard {public void run() {System.out.println("main board run....");}public void usePCI(PCI p) {//PCI p = new SouncCard();if (p != null) {p.open();p.close();}}
}

PCI.java

public interface PCI {public void open();public void close();}

ReflectTest.java

/** 电脑运行。 */
public class ReflectTest {/*** @param args* @throws Exception */public static void main(String[] args) throws Exception {Mainboard mb = new Mainboard();mb.run();//每次添加一个设备都需要修改代码传递一个新创建的对象
//      mb.usePCI(new SoundCard());//能不能不修改代码就可以完成这个动作。
//      不用new来完成,而是只获取其class文件。在内部实现创建对象的动作。 File configFile = new File("pci.properties");Properties prop = new Properties();FileInputStream fis = new FileInputStream(configFile);prop.load(fis);for(int x=0; x<prop.size(); x++){String pciName = prop.getProperty("pci"+(x+1));Class clazz = Class.forName(pciName);//用Class去加载这个pci子类。 PCI p = (PCI)clazz.newInstance();mb.usePCI(p);}fis.close();}}

应用练习2

--反射与工厂设计模式这时可以发现,利用反射机制实现的工厂设计模式,最大的优势:对于接口子类的扩充将不再影响到工厂类的定义。JavaApiDemo.java
public class JavaApiDemo {public static void main(String[] args) throws Exception {IMessage msg=Factory.getInstance("com.mldn.demo.NetMessage",IMessage.class);msg.send();//【网络消息发送】www.baidu.commsg=Factory.getInstance("com.mldn.demo.CloudMessage",IMessage.class);msg.send();//【云消息发送】www.baidu.comIService service=Factory.getInstance("com.mldn.demo.HouseService",IService.class);service.service();}}class Factory{private Factory(){}/*** 获取接实例化对象* @param className 接口的子类* @param clazz 描述的是一个接口的类型* @return 如果子类存在则返回指定接口的实例化对象*/@SuppressWarnings("unchecked")public static <T> T getInstance(String className,Class<T> clazz){T instance=null;try {instance=(T) Class.forName(className).getDeclaredConstructor().newInstance();}catch (Exception e) {e.printStackTrace();}return instance;}}interface IService{void service();}class HouseService implements IService{@Overridepublic void service() {System.out.println("【服务】为您的住宿提供服务");}}interface IMessage{void send();//消息发送}class NetMessage implements IMessage{@Overridepublic void send() {System.out.println("【网络消息发送】www.baidu.com");}}class CloudMessage implements IMessage{@Overridepublic void send() {System.out.println("【云消息发送】www.baidu.com");}}

课后作业

1 、写一个方法,此方法可以获取obj对象中名为propertyName(自定义)的属性的值
2.(1)写一个Properties格式的配置文件,配置类的完整名称。
(2) 写一个程序,读取这个Properties配置文件,获得类的完整名称并加载这个类。
3、 写一个方法,此方法可将obj对象中名为propertyName的属性的值设置为value.

java之更快学习反射相关推荐

  1. 更快学习 JavaScript 的 6 个思维技巧

    2019独角兽企业重金招聘Python工程师标准>>> 我们在学习JavaScript,或其他任何编码技能的时候,往往是因为这些拦路虎而裹足不前: 有些概念可能会造成混淆,尤其当你是 ...

  2. java转换为c#_C#vs Java哪一个更快? 将25k C#转换为Java(2)

    java转换为c# 在上一篇文章中,我描述了如何将25k行C#转换为Java以及从该练习中学到的教训. 我收到以下问题: 顺便说一句很棒的文章. 移植代码后,性能与C#版本相比如何? 改写系统的动机之 ...

  3. C#vs Java哪一个更快? 将25k C#转换为Java(2)

    在上一篇文章中,我描述了如何将25k行C#转换为Java以及从该练习中学到的教训. 我收到以下问题: 顺便说一句很棒的文章. 迁移代码后,性能与C#版本相比如何? 改写系统的动机之一是使系统变得更快, ...

  4. 更快学习 JavaScript的6个思维技巧

    我们在学习JavaScript,或其他任何编码技能的时候,往往是因为这些拦路虎而裹足不前: 有些概念可能会造成混淆,尤其当你是从其他语言转过来的时候 找不到时间(有时是动力)学习. 很容易忘记已经理解 ...

  5. 更快学习编程的7个重要技巧

    无论您是正在攻读计算机科学的学位,还是使用GI Bill选择下一个任务的资深人士,有抱负的自学成才的开发人员或编码训练营的学生,精通编程技术都是永恒的斗争.为了帮助您的学习(由Coding Dojo讲 ...

  6. 机器学习 训练较快的模型_通过心理模型更快地学习软件,第1部分

    机器学习 训练较快的模型 什么是心理模型? (What Are Mental Models?) The easiest way to describe them is that they're pat ...

  7. C ++或Java,高频交易哪个更快?

    总览 关于什么是高频交易的最佳解决方案,存在不同意见. 问题的一部分是高频交易的变化超出您的预期,另一部分是更快的含义. 我的看法 如果您有一个典型的Java程序员和一个典型的C ++程序员,并且每个 ...

  8. Java菜鸟到大牛学习路线之高级篇

    这是一套Java菜鸟到大牛的学习路线之高级教程,由工作了10年的资深Java架构师整理. 01-java高级架构师设计-基础深入         J2SE深入讲解         Java多线程与并发 ...

  9. 服务器webpack构建性能,[译] 优化 WEBPACK 以更快地构建 REACT

    如果您的 Webpack 构建缓慢且有大量的库 -- 别担心,有一种方法可以提高增量构建的速度!Webpack 的 DLLPlugin 允许您将所有的依赖项构建到一个文件中.这是一个取代分块的很好选择 ...

最新文章

  1. c#执行oracle存储过程,C#中如何执行存储过程方法
  2. spring解决ajax跨域问题
  3. 保持寄存器和输入寄存器的区别_串行移位寄存器74HC595
  4. IntelliJ IDEA for Mac 如何在当前的普通Java项目中创建新的模块/添加模块/创建模块
  5. SQLite | Insert、Delete、Updata 与 Drop 语句
  6. Go 单元测试--Mock接口实现和对接口打桩
  7. mysql-存储过程 使用游标获取数据集并且操作
  8. 如何查看有没有django及版本
  9. java 调用bat脚本 等待返回_java程序调用bat脚本
  10. 广告投放类型以及各大平台计费准则+推广常用评价指标
  11. Android JetPack架构篇,一个实战项目带你学懂JetPack
  12. 移远BC35-G固件升级
  13. JAVA打印简易版日历
  14. 图像处理课程大设计--汽车牌照自动识别
  15. sql如何查询所有学生都选修了的课程的课程号cno?
  16. 今天没有带U盘,把代码拷到网上再回家贴
  17. 移动硬盘无法读取怎么办?硬盘数据可以恢复吗?
  18. python批量循环图片识别_批量识别图中文字自动命名,让你1秒找到骚图
  19. html选择确认,增值税发票选择确认平台
  20. 知识体系之APUE/内核编程

热门文章

  1. 关于 hystrix 的异常 fallback method wasn't found
  2. windows下VOT-toolkit环境配置
  3. 电流电压转换器,频率电压转换器
  4. 2021-2027全球及中国DVD刻录系统行业研究及十四五规划分析报告
  5. BBB学习(六):Windows电脑通信调试(2):BBB连接网络
  6. 数字化运营加速城市轨道交通发展,新基建背景下搭建地铁管理系统
  7. .asar反编译,electron打包以后反编译,使用node.js安装asar和反编译app.asar
  8. vmware安装苹果虚拟机卡在苹果图标位置不动
  9. 互联网运营面试题_运营十问 | 总结运营面试可能遇到的问题
  10. linux下FTP、SFTP命令详解