反射:

框架设计的灵魂

  框架:半成品软件。可以再框架的基础上进行软件开发,简化代码

定义:将类的各个组成部分封装为其他对象,这就是反射机制

好处:

  可以再程序运行过程中,操作这些对象

  可以解耦,提高程序的可扩展性。

获取Class类对象

  

对应第一阶段:Class.forName(全类名):将字节码文件加载进内存,返回Class对象
对应第二阶段:类名.class:通过类名的属性class获取
对应第三阶段:对象.getClass():getClass()方法在Object类中定义

注意:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次

    无论通过哪一种方式获取的Class对象都是同一个

第一种方式:多用于配置文件,将类名定义在配置文件当中,读取文件,加载类
第二种方式:多用于参数的传递
第三种方式:多用于对象的获取字节码的方式
public class ReflectDEmo {
/*
获CLass对象方式:
对应第一阶段:Class.forName(全类名):将字节码文件加载进内存,返回Class对象
对应第二阶段:类名.class:通过类名的属性class获取
对应第三阶段:对象.getClass():getClass()方法在Object类中定义
*/ public static void main(String[] args) throws ClassNotFoundException {
Class cls1 = Class.forName("domain.Person");
System.out.println(cls1); Class<Person> cls2 =Person.class;//ctrl+alt+V
System.out.println(cls2); Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3); // ==比较三个对象
System.out.println(cls1 == cls2);//true
System.out.println(cls1 == cls3);//true
}
}

使用Class对象

  

获取功能:
获取成员变量们
Field[] getFields() 返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段
                  类对象
Field getField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段
                        类对象。
Field[] getDeclaredFields() 返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。
Field getDeclaredField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定已
                            声明字段 类对象。 获取构造方法们
Constructor<T> getConstructor(类<?>...parameterTypes) 返回一个 Constructor对象,
                        该对象反映 Constructor对象表示的类的指定的公共 类函数。
Constructor<?>[] getConstructors() 返回包含一个数组 Constructor对象反射由此表示的类
                            的所有公共构造 类对象。
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 返回一个 Constructor
                        对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。
Constructor<?>[] getDeclaredConstructors() 返回一个反映 Constructor对象表示的类声明的所有
                          Constructor对象的数组 类 。 获取成员方法们
      Method getMethod(String name, 类<?>... parameterTypes) 返回一个 方法对象,它反映此表示
                                     的类或接口的指定公共成员方法 类对象。
      Method[] getMethods() 返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,
                              包括那些由类或接口和那些从超类和超接口继承的声明。
      Method getDeclaredMethod(String name, 类<?>... parameterTypes) 返回一个 方法对象,
                                它反映此表示的类或接口的指定声明的方法 类对象。
      Method[] getDeclaredMethods() 返回包含一个数组 方法对象反射的类或接口的所有声明的方法,
              通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。 获取类名
      String getName() 返回由 类对象表示的实体(类,接口,数组类,原始类型或空白)的名称,
                作为 String 。

Field

  获取到的成员变量可以进行get和set值

  还可以设置忽略访问权限修饰符的安全检测

setAccessible(true);//忽略访问权限修饰符的安全检测,暴力反射

public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//获取Person的Class对象
Class personClass = Person.class;
//获取成员变量
Field[] fieldsp = personClass.getFields();
for (Field field : fieldsp) {
System.out.println(field);
//re:public int domain.Person.birtha
} System.out.println("@@@@@@@@@@@@@@@");
//获取成员变量,指定成员变量名
Field fpbirth = personClass.getField("birtha");
Person p = new Person();
//获取值,需要指定实例对象名字
Object value = fpbirth.get(p);
System.out.println(value);//re: 0 因为没有设置值,所以默认0
//设置值,需要指定实例名i在
fpbirth.set(p,90);
System.out.println(p);
//re:Person{name='null', age=0, birtha=90, birthb=0, birthc=0, birthd=0} System.out.println("++++++++++++++++++++");
//忽略成员变量修饰符,全部获取成员变量
Field[] decaredFieadsp = personClass.getDeclaredFields();
for (Field field : decaredFieadsp) {
System.out.println(field);
}
//re:
/*
private java.lang.String domain.Person.name
private int domain.Person.age
public int domain.Person.birtha
protected int domain.Person.birthb
int domain.Person.birthc
private int domain.Person.birthd
*/
//忽略修饰符,指定名字获取变量
Field field =personClass.getDeclaredField("birthd");
field.setAccessible(true);//忽略访问权限修饰符的安全检测,暴力反射
Object value2 = field.get(p);
System.out.println(value2);//re: 0
}
}

Constructor

  创建对象

T newInstance(Object... initargs)

使用此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例

   如果是使用无参创建对象,就可以直接使用Class类里面的:

  

T newInstance()

创建由此 对象表示的类的新实例。
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
//获取Person的Class对象
Class personClass = Person.class; //需要指定构造器的参数类型
Constructor constructor =personClass.getConstructor(String.class,int.class);
System.out.println(constructor); //创建对象
Object person = constructor.newInstance("quan",23);
System.out.println(person); System.out.println("############空参##############");
Constructor constructorno =personClass.getConstructor();
System.out.println(constructorno); //创建对象
Object personno = constructorno.newInstance();
System.out.println(personno); //使用Class类里面的方法,实例化无参对象
Object noc = personClass.newInstance();
System.out.println(noc);
}
}
public domain.Person(java.lang.String,int)
Person{name='quan', age=23, birtha=0, birthb=0, birthc=0, birthd=0}
############空参##############
public domain.Person()
Person{name='null', age=0, birtha=0, birthb=0, birthc=0, birthd=0}
Person{name='null', age=0, birtha=0, birthb=0, birthc=0, birthd=0}

Method

public class ReflectDemo4 {
public static void main(String[] args) throws Exception {
//获取Person的Class对象
Class personClass = Person.class;
//获取指定的名称的方法
Method eatmethon= personClass.getMethod("eat");
Person p = new Person();
eatmethon.invoke(p);//执行!!!!!!!!!
//获取带参数的指定名称的方法
Method eatmsg = personClass.getMethod("eat", String.class);
eatmsg.invoke(p,"quanzhiqiang");//执行!!!!!! System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@");
Method[] all_methods = personClass.getMethods();
for (Method all_method : all_methods) {
System.out.println(all_method);//这里的方法会打印很多,因为是继承Object类
System.out.println(all_method.getName());//获取方法名字String
} //获取类名:
String class_name = personClass.getName();
System.out.println(class_name);//获取全类名 }
}

result:

eatign
eatquanzhiqiang
@@@@@@@@@@@@@@@@@@@@@@@@@@
public java.lang.String domain.Person.toString()
toString
public java.lang.String domain.Person.getName()
getName
public void domain.Person.setName(java.lang.String)
setName
public int domain.Person.getAge()
getAge
public void domain.Person.setAge(int)
setAge
public void domain.Person.eat(java.lang.String)
eat
public void domain.Person.eat()
eat
public final void java.lang.Object.wait() throws java.lang.InterruptedException
wait
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
wait
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
wait
public boolean java.lang.Object.equals(java.lang.Object)
equals
public native int java.lang.Object.hashCode()
hashCode
public final native java.lang.Class java.lang.Object.getClass()
getClass
public final native void java.lang.Object.notify()
notify
public final native void java.lang.Object.notifyAll()
notifyAll
domain.Person

反射的案例

需求:写一个“框架” ,不能改变该类的任何代码的前提下,
可以帮我们创建任意类的对象,并且之前其中的任意方法
实现:
11配置文件
22反射
步骤:
1将需要拆改那就的对象的全类名和需要执行的方法定义在配置文件种
2在程序种加载读取配置文件
3使用反射技术来加载类文件进内存
4创建对象
5 执行方法

/*
框架类
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
//可以创建任意类的对象,可以执行任意方法 /*
不能改变框架的任何代码
可以创建任意类的对象,可以执行任意方法
*/
// Person p = new Person();
// p.eat();
//加载配置文件-创建propertiest对象
Properties pro = new Properties();
//加载配置文件-转换为一个集合
//获取class目录下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();//通过反射获取类加载器
//通过类加载器去按照path路径去以字节输入流加载配置文件
InputStream is = classLoader.getResourceAsStream("reflect\\pro.properties");
//使用properties类的load方法以字节输入流的形式获取数据
pro.load(is); //获取配置文件种定义的数据
String className = pro.getProperty("className");//通过getProperty指定变量名称去获取值
String methodName = pro.getProperty("methodName"); //加载该类进内存
Class cls = Class.forName(className);
//创建对象
Object o = cls.newInstance();
//获取方法
Method omethod = cls.getMethod(methodName);
omethod.invoke(o); }
}

当配置文件是下面的时候:

结果:

eat...

配置文件的内容是:

结果为:

sleep...

涉及properties相关:https://www.cnblogs.com/java-quan/p/13160730.html

java-反射-注解-json-xml的更多相关文章

  1. 【译】8. Java反射——注解

    原文地址:http://tutorials.jenkov.com/java-reflection/annotations.html ================================== ...

  2. java反射--注解的定义与运用以及权限拦截

    自定义注解类编写的一些规则: 1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是 ...

  3. java反射注解妙用-获取所有接口说明

    转载请注明出处:https://www.cnblogs.com/wenjunwei/p/10293490.html 前言 最近在做项目权限,使用shiro实现restful接口权限管理,对整个项目都进 ...

  4. Java反射+注解案例

    注解类代码,注解的属性可以有多个: package reflect; import java.lang.annotation.Retention; import java.lang.annotatio ...

  5. 利用Java反射机制完成XML到对象的解析

    对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用XML文件是个不错的方法,尤其是在一些Web应用中,经常需要缓存一部分数据,如果将这些数据形成XML文件,解析后放入一个Hasht ...

  6. Java 反射机制学习资料

    Java反射——引言 Java反射——Class对象 Java反射——构造函数 Java反射——字段 Java反射——方法 Java反射——Getter和Setter Java反射——私有字段和私有方 ...

  7. Java反射——引言

    Java反射——引言 原文地址:http://tutorials.jenkov.com/java-reflection/index.html *By Jakob Jenkov Java的反射机制使得它 ...

  8. 【译】1. Java反射——引言

    原文地址:http://tutorials.jenkov.com/java-reflection/index.html *By Jakob Jenkov Java的反射机制使得它可以在运行时检查类.接 ...

  9. 【译】2. Java反射——Class对象

    原文地址:http://tutorials.jenkov.com/java-reflection/classes.html ====================================== ...

  10. 【译】3. Java反射——构造函数

    原文地址:http://tutorials.jenkov.com/java-reflection/constructors.html ================================= ...

随机推荐

  1. 人工智能进度好慢,呜呜呜 还是先来学python!!!!!!!二十三讲、二十四讲!

    0:十转2 def my_bin(x): a ='' if x : a = my_bin(x//2) return a+str(x%2) else: a+='0b' return a print(my ...

  2. github push时提示Username for 'https://github.com' 解决办法

    问题 github push时在输入账号密码后仍提示:Username for 'https://github.com',需要进一步输入账号密码. 解决方案 注意这里的账号密码并不是github的登录 ...

  3. 使用lrzsz在windows、Linux之间互传文件

    使用xshell自带的传输太慢 使用lrzsz进行文件互传: xshell远程linux 安装工具:yum install -y lrzsz,检查是否安装成功:rpm -qa |grep lrzsz ...

  4. docker:alpine使用logrotate切割日志

    最近在交付项目的时候使用了docker,大家都知道日志是项目定位问题的重要依据,但如果一开始项目本身没有对日志进行合理切割那就会导致长时间运行的项目日志文件大得编辑器打不开的情况.这里使用大部分lin ...

  5. Python:time与datetime

    学习自: (10条消息) Python的time和datetime的简单使用_慢行的蜗牛-CSDN博客 Python之 time 与 datetime模块 - 叶灵溪&叶仙樱 - 博客园 py ...

  6. redis缓存雪崩和缓存穿透

    缓存雪崩:由于原有的缓存过期失效,新的缓存还没有缓存进来,有一只请求缓存请求不到,导致所有请求都跑去了数据库,导致数据库IO.内存和CPU眼里过大,甚至导致宕机,使得整个系统崩溃. 解决思路:1,采用 ...

  7. 【阅读SpringMVC源码】手把手带你debug验证SpringMVC执行流程

    ✿ 阅读源码思路: 先跳过非重点,深入每个方法,进入的时候可以把整个可以理一下方法的执行步骤理一下,也可以,理到某一步,继续深入,回来后,接着理清除下面的步骤. ✿ 阅读本文的准备工作,预习一下Spr ...

  8. springboot-jta-atomikos多数据源事务管理

    背景 我们平时在用springboot开发时,要使用事务,只需要在方法上添加@Transaction注解即可,但这种方式只适用单数据源,在多数据源下就不再适用: 比如在多数据源下,我们在一个方法里执行 ...

  9. ASP.NET Core 6框架揭秘实例演示[22]:如何承载你的后台服务[补充]

    借助 .NET提供的服务承载(Hosting)系统,我们可以将一个或者多个长时间运行的后台服务寄宿或者承载我们创建的应用中.任何需要在后台长时间运行的操作都可以定义成标准化的服务并利用该系统来承载,A ...

  10. centos7 安装 nginx-1.18.0 并设置开机自启动

    一.到官网下载nginx Mainline  version:  nginx主力版本,为开发版 Stable version: 稳定版,在生产环境中选择此版本进行安装 Legacy versions: ...