1.认识反射机制
1.1 反射的“反”指的是根据对象来取得对象的来源信息
1.2 反射的三种方式

import java,util.Date;public class Test{public static void main(String[] args){Date date = new Date();System.out.println(date.getClass());//通过Class类的getClass()获取Class类对象}
}public class Test{public static void main(String[] args) throws ClassNotFoundException{Class<?> cls =Class.forName("java.util.Date");System.out.println(cls.getName());}}Date.class;//直接获取Class类的实例化对象

1.3 通过反射实例化对象的方法

  public class Test{public static void main(String[] args) throws ClassNotFoundException,InstantiationException,IllegalAccessException{Class<?> cls = Class.forName("java.util.Date");Object obj = cls.newInstance();//创造的是forName中的类的实例System.out.pringln(obj);  } }

1.4 简单工厂模式
传统工厂类的弊端在于每加一个新的类,就得在工厂里面添加创造它的对象的代码,而用反射实例化对象就很好地避免了这一点。这种模式称为简单工厂模式。

interface IFruit{public void eat();
}
class Apple implements IFruit{public void eat(){System.out.println("吃苹果");}
}
class Orange implements IFruit{public void eat(){System.out.println("吃橘子");}
}class FruitFactory{private FruitFactory(){}public static IFruit getInstance(String className){IFruit fruit = null;try{fruit = (IFruit)Class.forName(className).newInstance();}catch(InstiationException|IllegalAccessException|ClassNotFoundException e){e.printStackTrace();}return fruit;}
}public class Test{public static void main(String[] args){IFruit fruit = FruitFactory.getInstance("com.stay.java.testthread.Orange");fruit.eat();}
}

2.反射在类中的其他用途
2.1反射取得父类信息
package com.stay.java.testthread;

 interface IFruit;interface IMessage;class CLS implements IFruit,IMessage{}public class Test{public static void main(String[] args){Class<?> cls = CLS.class;//取得class类对象System.out.println(cls.getPackage().getName());//取得包名称System.out.println(cls.getSuperclass().getName());//取得父类名称Class<?>[] iClass = cls.getInterfaces();for(Class<?> class1:iClass){System.out.println(class1.getName());}}}

2.2 反射调用构造方法

//取得类中所有构造信息package com.stay.java.testthread;import java.lang.reflect.Constructor;class Person{public Person(){}public Person(String name){}public Person(String name,int age){}}public class Test{public static void main(String[] args){Class<?> cls = Person.class;Constructor<?>[] constructors = cls.getConstructors();for(Constructor<?> constructor:constructors){                          System.out.println(constructor);} }}class类通过反射实例化对象的时候,只能够调用类中的无参构造。如果类中没有无参构造则无法使用Class类调用,只能通过明确的构造调用实例化处理
package com.stay.java.testthread;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;class Person{private String name;private int age;public Person(String name,int age){                                                                             this.name = name;this.age = age;}public String toString(){return "Person[name="+name+",age="+age+"]";}
}public class Test{public static void main(String[] args)throws InstantiationException,
IllegalAccessException, NoSuchMethodException, SecurityException,
IllegalArgumentException, InvocationTargetException {Class<?> cls = Person.class;Constructor<?> cons = cls.getConstructor(String.class,int.class);System.out.pringln(cons.newInstance("lalala",19));}
}

2.3 反射调用普通方法

 //取得一个类中的全部普通方法package com.stay.java.testthread;import java.lang.reflect.InvocationTargrtException;
import java.lang.reflect.Method;class Person{private String name;private int age;public Person(){}public Person(String name,int age){this.name = name;this.age = age;}public String toString(){return "Person [name=" + name + ", age=" + age + "]";}public String getName(){return name;}public void setName(){this.name = name;}public int getAge(){return age;}public void setAge(int age){this.age = age;}
}public class Test{public static void main(String[] args)throws Exception{Class<?> cls = Person.class;'Method[] methods = cls.getMethods();for(Method nethod : methods){System.out.println(method);}}
}//通过反射调用方法
public class Test{public static void main(String[] args)throws Exception{Class<?> cls = Class.forName("com.stay.java.testthread.Person");Object obj = cls.newInstance();Method setMethod = cls.getMethod("setName",String class);//需要传入方法名和参数setMethod.invoke(obj,"lalala");//给对象的属性赋值 invoke方法的参数是要被赋值的属性所属的对象名称和所赋的值Method getMethod = cls.getMethod("getName");Object result = getMethod.invoke(obj);System.out.println(result);}
}

2.4 反射调用类中属性

//取得类中全部属性package com.stay.java.testthread;import java.lang.reflect.Field;class Person{public String name;public int age;}class Student extends Person{private String school;}public class Test{public static void main(String[] args)throws Exception{Class<?> cls = Class.forName("com.stay.java.testthread.Student");{//第一组-取得类中全部属性(父类中)Field[] fields = cls.getFields();for(Field field : fields){System.out.println(field);}}System.out.println("------------------------");{//第二组(本类中)Field[] fields = cls.getDeclareFields();for(Field field : fields){System.out.println(field);}   }}}

2.5 动态设置封装方法

public void setAccessible(boolean flag)throws SecurityException

2.6 getType()方法
此方法用来取得属性类型

package com.stay.java.testthread;import java.lang.reflect.Field;class Person{private String name;
}public class Test{public static void main(String[] args)throws Exception{Class<?> cls = Class.forName("com.stay.java.testthread.Person");Object obj = cls.newInstance();Field nameField = cls.getDeclareField("name");System.out.println(name.Field.getType().getName());System.out.println.out.println(name.Field.getType().getSimpleName());}
}

3.反射与简单Java类
用反射的方法对对象的属性进行赋值

package com.stay.java.vo;class Emp{private String ename;private String job;public String getEname(){return ename;}public void setEname(String ename){this.name = ename;
}public String getJob(){return job;
}public void setJob(String job){this.job = job;
}public String toString(){return "Emp{" +"ename='" + ename + '\'' + ", job='" + job + '\'' +'}';
}
}package com.stay.java.ov;import com.stay.java.util.BeanOperation;public class EmpAction extends Emp{private Emp emp = new Emp();//接收一长串字符串,跳转到拆分方法public void setValue(String value) throws Exception{BeanOperation.setBeanValue(this,value);}public Emp getEmp(){return emp;}
}package com.stay.java.util;
//实现对象与属性值的匹配
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class BeanOperation{private BeanOperation(){}//属性的具体内容,格式为:"属性名称:内容|属性名称:内容..."//属性名称的格式是对象名.属性名public static void setBeanValue(Object actionObject,String msg) throws Exception{//按竖线拆分String[] result = msg.split("\\|");for(int i = 0;i<result.length;i++){//进一步拆分String[] temp = result[i].split{":"};String attribute = temp[0];//存属性名String value = temp[1];//存属性值String[] fields = attribute.split("\\.");Object currentObject = getObject(actionObject,fields[1]);setObjectValue(currentObject,fields[1],temp[1]);}}
}public static Object getObject(Object obj,String attribute) throws
Exception{
String methodName = "get" + initCap(attribute) ;
//field[1]里面存的是属性名称,field[0]里面存的是属性要被赋值的那个对象名称
// 调⽤指定属性的Field对象,⽬的是取得对象类型,如果没有此属性意味着操作⽆法继续进
⾏
Field field = obj.getClass().getDeclaredField(attribute) ;if (field == null) {
// 第⼆次尝试从⽗类中取得该属性
field = obj.getClass().getField(attribute) ;
}
if (field == null) {
// 两次都未取得指定属性的对象,表示该对象⼀定不存在
return null ;
}
//如果找到了就取出来
Method method = obj.getClass().getMethod(methodName) ;
return method.invoke(obj) ;
}public static void setObjectValue(Object obj,String attribute,String
value) throws Exception{
Field field = obj.getClass().getDeclaredField(attribute) ;
// 判断属性是否存在
if (field == null) {
// 第⼆次尝试从⽗类中取得该属性
field = obj.getClass().getField(attribute) ;
}
if (field == null) {
// 两次都未取得指定属性的对象,表示该对象⼀定不存在
return ;
}
String methodName = "set" + initCap(attribute) ;
Method setMethod =
obj.getClass().getMethod(methodName,field.getType()) ;
setMethod.invoke(obj,value) ;
}
}

测试类:

package www.bit.java.vo;public class TestDemo {
public static void main(String[] args) throws Exception {
String value = "emp.ename:yuisama|emp.job:Java Coder" ;
EmpAction empAction = new EmpAction() ;
empAction.setValue(value) ;
System.out.println(empAction.getEmp());
}
}

4.ClassLoader类加载器
Q:什么是类加载器?
A:在JVM中,“通过一个类的全限定类名来获取描述此类的二进制字节流”这个动作放在java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”
如果说现在你的类加载路径可能是网络、文件,这个时候就必须实现类加载器,也就是ClassLoader类的主要作用。
4.1 认识ClassLoader

     public ClassLoader getClassLoader()
class Member{}
public class TestDemo{public static void main(String[] args){Class<?> cls = Member.class;System.out.println(cls.getClassLoader());//结果是sun.misc.Launcher$AppClassLoader@58644d46System.out.println(cls.getClassLoader().getParent()) ;//结果是sun.misc.Launcher$ExtClassLoader@6a38e57fSystem.out.println(cls.getClassLoader().getParent().getParent());//结果是null}
}

三个类加载器:
Bootstrap(启动类加载器):隶属于虚拟机,无法被Java程序直接引用。其他类加载器都继承java.lang.ClassLoader.BootStrap.这个类主要负责将lib目录下能被虚拟机识别的类库加载到JVM内存中。
ExtClassLoader(扩展类加载器):负责加载lib\ext目录中,或者被java.ext.dirs系统变量指定的路径中的类库。开发者可以直接i使用扩展类加载器。
AppClassLoader(应用程序类加载器):负责加载用户类路径上指定的类库。此加载器是默认类加载器。
4.2 双亲委派模型
所有的类加载器收到了类加载请求的第一个操作是丢给父类加载器去加载,父类加载器找不到类时,会丢回子类加载器,这时子类加载器尝试自己加载
4.3 loadClass()方法

 //首先检查类是否已经被加载Class<?> c = findLoadClass(name);if(c == null){long t0 = System.nanoTime();try{if(parent != null){c = parent.loadClass(name,false);}else{c = findBootstrapClassOrNull(name);}}catch(ClassNotFoundException e){e.printStackTrace();}if(c == null){long t1 = System.nanoTime();c = findClass(name);}
}if(resolve){resolveClass(c);
}

5.反射与代理设计模式
5.1 动态代理设计模式
一个代理类可以代理所有需要被代理的接口的子类对象

 public interface InvocationHandler{public Object invoke(Object proxy,Method method,Object[] args){throws Throwable;}}

如果要进行对象的绑定,那么就需要一个java.lang.reflect.Proxy程序类。这个程序类的功能是可以绑定所有需要绑定的接口子类对象,而且这些对象都是根据接口自动创建的,该类有一个动态创建绑定对象的方法
public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h) throws IllegalArgumentException

//动态代理设计实现
package www.stay.java.agencyimport java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface ISubject{public void eat(String msg,int num);
}
class RealSubject implements ISubject{public void eat(String msg,int num){System.out.println("我要吃 "+num + "分量的 "+msg) ;}
}//动态代理类
class ProxySubject implements InvacationHandler{private Object target;public Object bind(Object target){this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}public void preHandle(){System.out.println("[ProxySubject] 方法处理前");
}public void afterHandle(){System.out.println("[ProxySubject] 方法处理后");
}public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{this.preHandle();Object ret = method.invoke(this.target,args);this.afterHandle();return ret;
}
}public class TestDemo{public static void main(String[] args){ISubject subject = (ISubject) new ProxySubject().bind(newRealSubject());subject.eat("重庆小面",15);}
}

PS:若要离开接口实现动态代理模式,就要依赖第三方组建包CGLIB

6.反射与Annotation
6.1反射取得Annotation信息
与Annotation有关的信息在java.lang.reflect.AccessibleObject类中有定义

//取得定义在类上的Annotation
package com.stay.annotationimport java.io.Serializable;
import java.lang.annotation.Annotation;@SuppressWarnings("serial")
@Deprecated
class Member implements Serializable{}public class TestAnnotation{public static void main(String[] args){Annotation[] ant = Member.class.getAnnotations();for(Annotation a:ant){System.out.println(a);}}
}//获取方法的Annotationpackage com.stay.annotationimport java.io.Serializable;
import java.lang.annotation.Annotation;@SuppressWarnings("serial")
@Deprecated
class Member implements Serializable{@Deprecated@Overridepublic String toString(){return super.toString();}
}public class TestAnnotation{public static void main(String[] args){Annotation[] ant = new Annotation[0];try{ant = Member.class.getMethod("toString").getAnnotations();}catch(NoSuchMethodException e){e.printStackTrace();}for(Annotation a:ant){System.out.println(a);}}
}6.2 自定义Annotation 首先需要解决的是Annotation的作用范围。不同的Annotation有自己的运行范围,而这些范围就在一个枚举类中定义。//定义一个在运行时生效的Annotationpackage com.stay.annotation;import java.io.Serializable;import java.lang.annotation.Annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;/**自定义一个Annotation名叫MyAnnotation*/@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation{public String name();public int age();//也可以直接定义默认值public String name() default "stay";public int age() default 22;}@Deprecated@MyAnnotation(name = "stay",age=22)class Member implements Serializable{}public class TestAnnotation{public static void main(String[] args){Annotation[] ant = new Annotation[0];ant = Member.class.getAnnotations();for(Annotation a:ant){System.out.println(a);}}}//获取一个具体Annotation的信息package com.stay.annotation;import java.io.Serializable;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;/**自定义一个Annotation名叫MyAnnotation*/@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation{public String name();public int age();//也可以直接定义默认值public String name() default "stay";public int age() default 22;}@Deprecated@MyAnnotation(name = "stay",age=22)class Member implements Serializable{}public class TestAnnotation{public static void main(String[] args){MyAnnotation ma = Member.class.getAnnotation(MyAnnotation.class);System.out.println("姓名:"+ma.name());System.out.println("年龄:"+ma.age());}}6.3 Annotation与工厂设计模式
package com.stay.annotation;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;/***自定义一个Annotation*这个Annotation中定义了一个类*/@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation{public Class<?> target();}interface IFruit{public void eat();}class Apple implements IFruit{@Overridepublic void eat(){System.out.println("吃苹果");}}@MyAnnotation(target=Apple.class)//这样使用target和之前使用类就是同一个作用了class Factory {
public static <T> T getInstance() throws Exception{
MyAnnotation mt = Factory.class.getAnnotation(MyAnnotation.class) ;
return (T) mt.target().newInstance() ;
}
}
public class TestAnnotation {
public static void main(String[] args) throws Exception{
IFruit fruit = Factory.getInstance() ;
fruit.eat() ;}
}

Programmer Log8[反射]_19.09.02相关推荐

  1. “30/Jan/22 09:02 AM”不是有效日期。请按下列格式输入日期:dd/MMM/yy h:mm a

    问题描述 在jira使用中设置日期报错: "30/Jan/22 09:02 AM"不是有效日期.请按下列格式输入日期:dd/MMM/yy h:mm a 问题分析 出现日期报错是因为 ...

  2. IOS学习笔记 ---- 15/09/02

    1.三种方式监听方式: addTarget方法: 使用代理方法: [[NSNotificationCenter defaultCenter] addObserver]方法监听通知: 2.在storyb ...

  3. 《惢客创业日记》2019.09.02(周一) 把习惯变成闹钟

    今天,在学习健康知识的时候,看到了一个关于乔吉拉德起床的故事,这个故事在很多年前就看过,不过,今天看到这个故事却联想到了惢客.说到乔迪拉德,很多懂销售的人都知道,在销售界还被冠以"销售之神& ...

  4. 离散数学 09.02 带有输出的有限状态机

    9.2带有输出的有限状态机\color{blue}9.2 带有输出的有限状态机9.2带有输出的有限状态机 \qquad许多器件,包括计算机元件,可以用一种叫做有限状态机的结构来模拟.很多类型的有限状态 ...

  5. 08.09.02之叽歪

    我们真正需要的不仅仅是一款浏览器,而是一个现代化的网页及应用平台.这就是我们开发Google Chrome的初衷. 说得好!

  6. 【学习日志】2022.09.02 (C++)strcmp和stricmp、strcmpi三者之间的区别、C语言判断文件后缀名、ZENO Audio Update、TEN MINUTES PHYSICS

    (C++)strcmp和stricmp.strcmpi三者之间的区别 (strcmpi在Windows C标准库实现,但不在GNU C标准库实现) #include <string.h> ...

  7. DSMP规范定义的错误码 2012-12-14 09:02阅读(0)

    1.1.1 MISC响应代码与业务网关之间接口消息的错误代码 错误代码 错误描述 备注 0 成功 1 其他错误 100 手机号码不存在 101 手机号码错误 102 用户停机 103 用户欠费 104 ...

  8. 【每日早报】2019/09/02

    今日看点 ✦ 华为Mate 30系列将于9月19日在德国慕尼黑发布 ✦ 盒马mini首店已实现盈利,全国第三店首次开到上海郊区 ✦ 嘀嗒出行用户突破1.3亿,出租车业务进入86个城市 ✦ 我国首个湾区 ...

  9. CCF 2018/09/02 买菜

    题目 去官网看 思路 开始写的时候还是笨方法,一点点地分析两个人停留时间的交集,考虑不同情况下的交谈时间,很费力. 之后还是看了前辈的解法,清晰易懂,在此做下笔记. 建立一个时间段数组,计算每个时间段 ...

最新文章

  1. 《ORACLE PL/SQL编程详细》,游标 ,函数,触发器。。
  2. Python脚本BUG引发学界震动,影响有多大?
  3. 世界级安全技术专家力作——《Linux防火墙》
  4. Avenger v1.0.6.0
  5. python找不到csv文件_Python如何读取csv文件
  6. linux 内存泄漏 定位,一种内存泄露检查和定位的方法
  7. 活动安排(信息学奥赛一本通-T1422)
  8. 宝石光是什么石头_沙漠戈壁的漂亮“石头”让人见了流口水
  9. java linklist 遍历_Java LinkList遍历方式
  10. Java程序设计教程(第三版) 雍俊海 9.6 答案/代码
  11. 在CMD上运行使用java命令运行java文件时出现错误:找不到或者无法加载主类的问题 解决办法
  12. 人工智能 AI 概念梳理
  13. 朴素贝叶斯—豆瓣Top250影评的情感分析与预测
  14. 谷歌地球离线地图包_水经注全国离线地图都有哪些地图数据?
  15. java 计算同比增长率
  16. 招投标工作中投标书编制的流程是怎样的?
  17. 揭秘中国球员十大豪宅
  18. C#设置开机启动时报错,提示“对注册表项“HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run访问被拒绝”
  19. H2教程系列(二) 创建数据库
  20. Kafka的版本号说明

热门文章

  1. lg空调代码大全解决_LG空调故障代码大全31905
  2. mysql 2003 111_MySQL:解决ERROR 2003 (HY000): Can't connect to MySQL server on 'XXX' (111)
  3. 微信抖音群控系统适合做什么项目?
  4. 张天钰 内大计算机学院,20175305张天钰Java结对编程四则运算
  5. 对象切片(object slicing)和多态
  6. 基于SSM的房产中介管理系统的设计
  7. Mysql全文索引性能测试对比
  8. 3.我攻破了美军海军网站 [2]
  9. 解决《新编全医药学大词典》开机启动及桌面快捷方式的问题
  10. ML:通过数据预处理(分布图/箱型图/模型寻找异常值/热图/散点图/回归关系/修正分布正态化/QQ分位图/构造交叉特征/平均数编码)利用十种算法模型调优实现工业蒸汽量回归预测(交叉训练/模型融合)之详