反射

1. 反射机制的概念

反射机制就是在程序运行时,可以动态获取任意一个类及其所有属性和方法并创建对象,可以对任意一个对象调用其任意方法和属性。

2. 反射机制的作用

在程序运行时获取任意类的对象,访问任意类的属性、方法(不论是否私有)。

3. 反射机制的理解

反射机制就是将Java类中的各个成分映射成一个个对象,例如将类映射成一个Class类对象,将方法映射成Method类对象。可通过这些对象来完成对类的方法、属性的获取以及对对象方法的调用。

4. Class类的使用

Class类是对类对象进行操作的基础。可通过Class对象进行类对象的创建、获取类的属性及方法、获取类的构造方法等操作。

5. Class文件获取的三种方式

  1. 通过类对象获取class文件
String str = new String();
Class strClass1 = str.getClass();
  1. 通过类.class获取
Class strClass2 = String.class;
  1. 通过类名获取
Class strClass3 = Class.forName("com.myh.day0720.Person");

6. 获取Constructor对象

获取Constructor对象可以使用getConstructors()同时获取多个构造函数也可以使用getConstructor(参数类型)获取单个构造函数。

创建了一个Person类:

package com.myh.day0720;public class Person {private String name;private int age;Person() {System.out.println("无参默认构造方法被调用。");}private Person (String name, int age) {this.name = name;System.out.println("私有有参构造方法被调用");}public Person(String name) {this.name = name;System.out.println("公有参数为" + name + "的有参构造方法被调用。");}public String getName() {System.out.println("对象的属性name = " + name + "被获取。");return name;}public void setName(String name) {System.out.println("对象的属性name被赋值为" + name + "。");this.name = name;}private void sayHi() {System.out.println("Hello");}
}

获取Contructor对象:

package com.myh.day0720;import java.lang.reflect.Constructor;public class GetConstructorDemo {public static void main(String[] args) throws Exception {Class clazz = Class.forName("com.myh.day0720.Person");// 获取所有公有构造方法System.out.println("----------------- 获取所有公有构造方法 -----------------");Constructor[] constructors = clazz.getConstructors();for (Constructor constructor : constructors) {System.out.println(constructor);}// 获取公有有参构造方法System.out.println("----------------- 获取公有有参构造方法 -----------------");Constructor constructor1 = clazz.getConstructor(String.class);System.out.println(constructor1);
}
----------------- 获取所有公有构造方法 -----------------
public com.myh.day0720.Person(java.lang.String)
----------------- 获取公有有参构造方法 -----------------
public com.myh.day0720.Person(java.lang.String)

7. 获取私有Constructor对象

获取非公有的Constructor对象可以使用getDeclaredConstructors()和getDeclaredConstructor(参数类型)来实现:

package com.myh.day0720;import java.lang.reflect.Constructor;public class GetConstructorDemo {public static void main(String[] args) throws Exception {Class clazz = Class.forName("com.myh.day0720.Person");// 获取所有构造方法System.out.println("----------------- 获取所有构造方法 -----------------");Constructor[] declaredConstructors = clazz.getDeclaredConstructors();for (Constructor declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);}// 获取默认无参构造方法System.out.println("----------------- 获取默认无参构造方法 -----------------");Constructor constructor = clazz.getDeclaredConstructor();System.out.println(constructor);// 获取私有有参构造方法System.out.println("----------------- 获取私有有参构造方法 -----------------");Constructor constructor2 = clazz.getDeclaredConstructor(String.class, int.class);System.out.println(constructor2);}
}
----------------- 获取所有构造方法 -----------------
public com.myh.day0720.Person(java.lang.String)
private com.myh.day0720.Person(java.lang.String,int)
com.myh.day0720.Person()
----------------- 获取默认无参构造方法 -----------------
com.myh.day0720.Person()
----------------- 获取私有有参构造方法 -----------------
private com.myh.day0720.Person(java.lang.String,int)

8. 获取Method对象

获取Method对象可以使用getMethods()获取所有方法(包括从父类继承的方法),也可以使用getMethod(方法名, 参数类型)获取单个方法。

package com.myh.day0720;import java.lang.reflect.Method;public class GetMethodDemo {public static void main(String[] args) throws Exception {Class clazz = Class.forName("com.myh.day0720.Person");// 获取所有公有方法System.out.println("----------------- 获取所有公有方法 -----------------");Method[] methods = clazz.getMethods();for (Method method : methods) {System.out.println(method);}// 获取单个公有方法System.out.println("----------------- 获取单个公有方法 -----------------");Method method = clazz.getMethod("setName", String.class);System.out.println(method);}
}
----------------- 获取所有公有方法 -----------------
public java.lang.String com.myh.day0720.Person.getName()
public void com.myh.day0720.Person.setName(java.lang.String)
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
----------------- 获取单个公有方法 -----------------
public void com.myh.day0720.Person.setName(java.lang.String)

9. 获取私有Method对象

获取私有Method对象可以使用getDeclaredMethods()获取所有方法,也可以使用getDeclaredMethod(方法名, 参数类型)获取单个方法。

package com.myh.day0720;import java.lang.reflect.Method;public class GetMethodDemo {public static void main(String[] args) throws Exception {Class clazz = Class.forName("com.myh.day0720.Person");// 获取所有方法System.out.println("----------------- 获取所有方法 -----------------");Method[] declaredMethods = clazz.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod);}// 获取单个私有方法System.out.println("----------------- 获取单个私有方法 -----------------");Method method1 = clazz.getDeclaredMethod("sayHi");System.out.println(method1);}
}
----------------- 获取所有方法 -----------------
private void com.myh.day0720.Person.sayHi()
public java.lang.String com.myh.day0720.Person.getName()
public void com.myh.day0720.Person.setName(java.lang.String)
----------------- 获取单个私有方法 -----------------
private void com.myh.day0720.Person.sayHi()

10. Constructor的使用

Constructor类提供了很多方法函数用来获取构造函数的信息。getName()方法可以获得当前构造函数的方法名;getModifiers()可以获取当前方法的修饰符;getParamenterTypes()可以获取当前构造方法的参数类型;newInstance()可以使用当前构造方法创造一个新对象。

package com.myh.day0720;import java.lang.reflect.Constructor;public class ConstructorDemo {public static void main(String[] args) throws Exception {Class clazz = Class.forName("com.myh.day0720.Person");Constructor constructor = clazz.getConstructor(String.class);// 获取方法名System.out.println(constructor.getName());// 获取修饰符System.out.println(constructor.getModifiers());// 获取构造方法的参数类型Class[] parameterTypes = constructor.getParameterTypes();for (Class parameterType : parameterTypes) {System.out.println(parameterType);}// 创建一个新对象Person person = (Person) constructor.newInstance("kk");}
}
com.myh.day0720.Person
1
class java.lang.String
公有参数为kk的有参构造方法被调用。

11. Method类的使用

Method类提供了很多方法来获取当前方法对象的信息。getName()方法可以获得当前方法的方法名;getModifiers()获取当前方法的修饰符;getParamenterTypes()获取当前方法的参数类型;getReturnTypes()获取当前方法的返回值;invoke()可以执行该方法。

package com.myh.day0720;import java.lang.reflect.Method;public class MethodDemo {public static void main(String[] args) throws Exception {Class clazz = Class.forName("com.myh.day0720.Person");Method method = clazz.getMethod("setName", String.class);// 获取方法名System.out.println(method.getName());// 获取修饰符System.out.println(method.getModifiers());// 获取方法的参数类型Class[] parameterTypes = method.getParameterTypes();for (Class parameterType : parameterTypes) {System.out.println(parameterType);}// 获取方法的返回值System.out.println(method.getReturnType());// 执行该方法Person person = (Person) clazz.newInstance();method.invoke(person, "John");}
}
setName
1
class java.lang.String
void
无参默认构造方法被调用。
对象的属性name被赋值为John。

12. Field类的使用

Field类用于对类的属性进行操作。

Class对象调用getFields()函数可以获取所有公有属性,调用getDeclaredFields()可以获取所有属性,调用getField(属性名)可以获取指定公有属性,调用getDeclaredField(属性名)可以获取指定属性。

Field类提供了getType()方法获取属性声明时的类型;getName() 获取属性声明时的名字;getAnnotations()获取属性上的所有注解;getModifiers()获取属性的修饰;isEnumConstant()判断该属性是否是枚举类;isSynthetic() 判断该属性是否是复合类;get(Object obj)获取obj对象上这个字段的值。

package com.myh.day0720;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;public class FieldDemo {public static void main(String[] args) throws Exception {Class clazz = Class.forName("com.myh.day0720.Person");// 获取Person类的私有属性nameField name = clazz.getDeclaredField("name");// 获取字段类型System.out.println(name.getType());// 获取字段名System.out.println(name.getName());// 获取字段上的所有注解Annotation[] annotations = name.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}// 获取该属性的修饰System.out.println(name.getModifiers());// 判断该属性是否为枚举类System.out.println(name.isEnumConstant());// 判断该属性是否为复合类System.out.println(name.isSynthetic());// 获取某一对象该字段的值,如果该字段为静态字段则传入nullPerson person = new Person("Aloha");name.setAccessible(true); // 因为该字段为私有,所以要将该字段的可见性设置为trueSystem.out.println(name.get(person));}
}
name
2
false
false
公有参数为Aloha的有参构造方法被调用。
Aloha

13. Modifier类的介绍

Modifier类是修饰符工具类,上述反射类中的getModifier()方法获取的modifier值就需要通过Modifier类来查看其对应的修饰符。Modifier类将每个修饰符封装成int常量,通过调用Modifier.toString()可以对反射类中的modefier值进行解码。

System.out.println(Modifier.toString(name.getModifiers()));
private

14. 反射使用练习

package com.myh.day0720.work;import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;public class ReflectTest {public static void main(String[] args) throws Exception {// 1、通过对象获取完整的包名和类名String str = new String();System.out.println("String对象的完整包名和类名为:" + str.getClass().getName());// 2、实例化Class类对象// 2.1.通过类对象获取Class strClass1 = str.getClass();// 2.2.通过类.class获取Class strClass2 = String.class;// 2.3.通过类名获取Class personClass = Class.forName("com.myh.day0720.Person");// 3、通过Class实例化其他类对象System.out.println();Object o = personClass.newInstance();// 4、通过Class调用其他类中的构造函数System.out.println();Constructor[] constructors = personClass.getConstructors();// 遍历构造函数for (Constructor constructor : constructors) {// 获取构造函数的参数个数int num = constructor.getParameterCount();// 构造函数的参数,均为nullObject[] params = new Object[num];constructor.newInstance(params);}// 5、获取一个类实现的接口System.out.println("\nPerson类实现了接口:");Class[] interfaces = personClass.getInterfaces();for (Class anInterface : interfaces) {System.out.println(anInterface);}// 6、获取某个类的父类System.out.println("\nPerson类的父类有:");Class superclass = personClass.getSuperclass();System.out.println(superclass);// 7、获取某个类的全部构造函数System.out.println("\nPerson类的全部构造函数有:");Constructor[] declaredConstructors = personClass.getDeclaredConstructors();for (Constructor declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);}// 8、获取某个类的全部属性System.out.println("\nPerson类的全部属性有:");Field[] declaredFields = personClass.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(declaredField);}// 9、调用某个类的set和get方法Field name = personClass.getDeclaredField("name");name.setAccessible(true); // 因为字段私有,所以设置为可见System.out.println("\n字段name的值为" + name.get(o));name.set(o, "what!");System.out.println("字段name的值已被改为" + name.get(o));// 10、操作对象属性// 获取字段类型System.out.println("\n字段的类型为" + name.getType());// 获取字段名System.out.println("字段名为" + name.getName());// 获取该属性的修饰System.out.println("字段修饰符为" + Modifier.toString(name.getModifiers()));// 判断该属性是否为枚举类boolean e = name.isEnumConstant();String out1 = e ? "是":"不是" + "枚举类";System.out.println("字段" + out1);// 判断该属性是否为复合类boolean s = name.isSynthetic();String out2 = s ? "是":"不是" + "复合类";System.out.println("字段" + out2);}
}
String对象的完整包名和类名为:java.lang.String无参默认构造方法被调用。无参默认构造方法被调用。
公有参数为null的有参构造方法被调用。Person类实现了接口:
interface java.io.Serializable
interface java.util.RandomAccessPerson类的父类有:
class java.lang.ObjectPerson类的全部构造函数有:
public com.myh.day0720.Person()
public com.myh.day0720.Person(java.lang.String)
private com.myh.day0720.Person(java.lang.String,int)Person类的全部属性有:
private java.lang.String com.myh.day0720.Person.name
private int com.myh.day0720.Person.age
public int com.myh.day0720.Person.sex字段name的值为null
字段name的值已被改为what!字段的类型为class java.lang.String
字段名为name
字段修饰符为private
字段不是枚举类
字段不是复合类

15. 反射机制在工厂设计模式中的应用

工厂接口:

package factory;import product.Product;public interface Factory {public Product produce();
}

工厂实现类:

package factory;import product.Product;
import product.Car;public class CarFactory implements Factory{@Overridepublic Product produce() { return new Car(); }
}
package factory;import product.Product;
import product.Plane;public class PlaneFactory implements Factory{@Overridepublic Product produce() {return new Plane();}
}

产品接口:

package product;public interface Product {public void run();
}

产品实现类:

package product;public class Car implements Product {@Overridepublic void run() {System.out.println("The car is running.");}
}
package product;public class Plane implements Product{@Overridepublic void run() {System.out.println("The plane is flying");}
}

config.xml文件:

<config><className>factory.CarFactory</className>
</config>

XMLUtil.java

import javax.xml.parsers.*;import org.w3c.dom.*;import java.io.*;public class XMLUtil {public static Object getBean() {try {DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = dFactory.newDocumentBuilder();Document doc = builder.parse(new File("config.xml"));NodeList nl = doc.getElementsByTagName("className");Node classNode = nl.item(0).getFirstChild();String cName = classNode.getNodeValue();Class c = Class.forName(cName);Object obj = c.newInstance();return obj;} catch (Exception e) {e.printStackTrace();return null;}}
}

Client.java

import product.Product;
import factory.Factory;public class Client {public static void main(String[] args) {Product product;Factory factory;factory = (Factory) XMLUtil.getBean();product = factory.produce();product.run();}
}

输出结果:

The car is running.

Java学习笔记 7-20 反射相关推荐

  1. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

  2. Java学习笔记 2021-7-1 2021-7-8

    Java学习笔记 Stream流 1 Stream流的体验 stream流的生成操作 stream中间流操作 filter limit和skip concat和distinct sorted map和 ...

  3. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  4. Java学习笔记(原创)

    Java学习笔记(原创) 2011-12-01 16:37:00|  分类: Java|举报|字号 订阅 下载LOFTER客户端 基本知识 一. Java基础 1. java语言的特点: ①简单:没有 ...

  5. 【JAVA学习笔记】你知道的越多,你不知道的越多系列一

    JAVA学习笔记 [JAVA学习笔记]你知道的越多,你不知道的越多之多系列一 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 JAVA学习笔记 前言 一.什么是可变参数 二 ...

  6. java学习笔记11--Annotation

    java学习笔记11--Annotation Annotation:在JDK1.5之后增加的一个新特性,这种特性被称为元数据特性,在JDK1.5之后称为注释,即:使用注释的方式加入一些程序的信息. j ...

  7. Java学习笔记(十)--控制台输入输出

    输入输出 一.控制台输入 在程序运行中要获取用户的输入数据来控制程序,我们要使用到 java.util 包中的 Scanner 类.当然 Java 中还可以使用其他的输入方式,但这里主要讲解 Scan ...

  8. java学习笔记16--I/O流和文件

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note16.html,转载请注明源地址. IO(Input  Output)流 IO流用来处理 ...

  9. java学习笔记8--接口总结

    接着前面的学习: java学习笔记7--抽象类与抽象方法 java学习笔记6--类的继承.Object类 java学习笔记5--类的方法 java学习笔记4--对象的初始化与回收 java学习笔记3- ...

  10. java学习笔记6--类的继承、Object类

    接着前面的学习: java学习笔记5--类的方法 java学习笔记4--类与对象的基本概念(2) java学习笔记3--类与对象的基本概念(1) java学习笔记2--数据类型.数组 java学习笔记 ...

最新文章

  1. FastJson 转换 javaBean 时 null 值被忽略都问题
  2. ReentrantLock 实现原理
  3. elasticSearch6源码分析(7)node
  4. [译] APT分析报告:03.OpBlueRaven揭露APT组织Fin7/Carbanak(上)Tirion恶意软件
  5. Action framework BAdI Definition TRIGGER_EXECUTED
  6. 对于Eclipse的正确用法
  7. Redis -- 基础操作 [2]
  8. C++ 语法都不会怎么写代码? 03
  9. 已经windows如何在安装linux,如何在已经安装linux情况下安装windows
  10. iOS多线程:『pthread、NSThread』详尽总结
  11. SVN打开HTML文件,tortoisesvn安装后怎么打开
  12. 好券零购4.0开发笔记
  13. Java编程入门:使用Eclipse快捷键
  14. 【Audio音频兴趣拓展】如何调试频响曲线?
  15. (混沌序列统计特性)离散傅里叶测试---matlab
  16. 提交代码遇到 Everything up-to-date 或 提交代码遇到 On branch master Your branch and ‘origin/master‘ have diverg
  17. mysql表分区join_​实战:Flink 1.12 维表 Join Hive 最新分区功能体验
  18. 【算法打卡(二分查找)---7.12】
  19. STM32调试出现Cannot access Memory的情况
  20. 云服务器一键搭建脚本

热门文章

  1. 三相异步电机速度闭环控制(前馈+PID)
  2. 显示图例(legend)
  3. php调用python程序
  4. 【PCB专题】印制电路板(PCB)的发明
  5. 糖果传奇的成功之路:三消游戏货币化技巧
  6. 数理统计复习笔记一——统计中常用的抽样分布(卡方分布,t分布,F分布)
  7. sql修改日期不改变时间
  8. 利用python写福字【弄个不一样的五福~】
  9. D3D11和D3D12多线程渲染框架的比较(一)
  10. 18届完全模型组预总