Java反射
来源:互联网 发布:定额软件app 编辑:程序博客网 时间:2024/06/08 17:49
基本概念
在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。在Java中,反射允许在编译期间不知道接口的名称,字段、方法的情况下,在运行时检查类、接口、字段和方法。它还允许实例化新对象、修改成员变量和调用方法。
使用
要在Java中使用反射,就必须使用到Class类。在面向对象的世界里,万事万物皆对象。所以类也是对象,类是java.lang.Class的实例化对象。也就是在Java中任何一个类都是都是Class类的实例化对象。在进行反射操作前必须先取得该类的类类型(即该类对应的Class类的实例化对象),有三种方法可以完成此项操作:
假定需要进行反射操作的类如下:
class A{ private String name; public int age; public String getName(){ return this.name; } public A(){} public A(String name, int age){ this.name = name; this.age = age; } public void print(int a, int b){ System.out.println(a + b); } public void print(String a, String b){ System.out.println(a + b); }}
- 通过任何一个类中都有隐含的静态成员变量class取得
Class c1 = A.class;
- 若已知某个类的实例化对象,通过getClass方法取得
A a = new A();Class c2 = a.getClass();
- 通过Class类提供的forName(包名.类名称)方法取得(此方法可用于类的动态加载,详情见后)
Class c3 = Class.forName("A");
注:
测试代码
package practicve.reflect;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * Created by lin_y on 2017/6/17. */class A{ private String name; public String getName(){ return this.name; } public void print(int a, int b){ System.out.println(a + b); } public void print(String a, String b){ System.out.println(a + b); }}public class Refelct { public static void main(String [] args) throws ClassNotFoundException { // 方式一:通过类中的隐含静态变量class获取A类的类类型(Class类对象) Class c1 = A.class; // 方式二:通过A的对象a调用getClass方法获取A的类类型(Class类对象) A a = new A(); Class c2 = a.getClass(); // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象) Class c3 = Class.forName("A"); // 一个类只可能是Class类的一个实例对象(c1、c2、c3相等) System.out.println(c1 == c2 && c2 == c3); }}
运行结果
获取Class的实例对象后,便可完成该类的反射操作。下面主要介绍三种反射操作:
1. 构造函数的反射操作
2. 成员变量的反射操作
3. 方法的反射操作
- 构造方法的反射操作
class A{ private String name; public int age; public String getName(){ return this.name; } public A(){} public A(String name, int age){ this.name = name; this.age = age; } public void print(int a, int b){ System.out.println(a + b); } public void print(String a, String b){ System.out.println(a + b); } public String toString(){ return "name:" + this.name + " age:" + this.age; }}public class Refelct { public static void main(String [] args) throws Exception { // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象) Class c = Class.forName("practicve.reflect.A"); // 获取含参构造方法 Constructor cs = c.getConstructor(String.class, int.class); // 调用构造方法实例化A类对象 Object obj = cs.newInstance("zhangsan", 20); System.out.println(obj.toString()); }}
程序运行结果
- 成员变量的反射操作
package practicve.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * Created by lin_y on 2017/6/17. */class A{ private String name; public int age; public String getName(){ return this.name; } public A(){} public A(String name, int age){ this.name = name; this.age = age; } public void print(int a, int b){ System.out.println(a + b); } public void print(String a, String b){ System.out.println(a + b); } public String toString(){ return "name:" + this.name + " age:" + this.age; }}public class Refelct { public static void main(String [] args) throws Exception { // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象) Class c = Class.forName("practicve.reflect.A"); // 获取A类中的成员变量 Field name = c.getDeclaredField("name"); Field age = c.getDeclaredField("age"); // 允许改变private变量 name.setAccessible(true); A a = new A(); // 变量反射操作 name.set(a, "zhangsan"); age.set(a, 20); System.out.println(a.toString()); }}
程序运行结果
- 方法的反射操作
package practicve.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * Created by lin_y on 2017/6/17. */class A{ private String name; public int age; public String getName(){ return this.name; } public A(){} public A(String name, int age){ this.name = name; this.age = age; } public void print(int a, int b){ System.out.println(a + b); } public void print(String a, String b){ System.out.println(a + b); } public String toString(){ return "name:" + this.name + " age:" + this.age; }}public class Refelct { public static void main(String [] args) throws Exception { // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象) Class c = Class.forName("practicve.reflect.A"); // 获取A类中的方法 Method m1 = c.getDeclaredMethod("print", String.class, String.class); Method m2 = c.getDeclaredMethod("print", int.class, int.class); A a = new A(); // 方法的调用 m1.invoke(a, "12", "34"); m2.invoke(a, 12, 34); }}
程序运行结果
注:
附:动态加载
基本概念:使用 new 创建对象是静态加载类,在编译时刻就需要加载所有的可能使用到的类。而动态加载类,是在运行时刻加载所需的类。
比如说,要写一个Office软件,里面包含多种功能,便可以使用动态加载类来实现
OfficeAble接口
package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public interface OfficeAble { public void print();}
Office主类
package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public class Office { public static void main(String [] args) throws Exception { OfficeAble office = (OfficeAble) Class.forName(args[0]).newInstance(); office.print(); }}
Word功能
package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public class Word implements OfficeAble { @Override public void print() { System.out.println("Word start ..."); }}
Excel功能
package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public class Excel implements OfficeAble{ @Override public void print() { System.out.println("Excel start ..."); }}
程序运行时args[0]参数为practicve.reflect.Word,程序运行结果为:
注:
- 【反射】JAVA反射机制
- JAVA 反射
- java 反射
- Java反射
- java反射
- java反射
- JAVA反射
- java 反射
- Java 反射
- java 反射
- Java反射
- java反射
- JAVA 反射
- java 反射
- Java反射
- java反射
- java 反射
- java 反射
- notifyDataSetChanged()无效原因
- JavaWeb开发知识总结(一)-(oracle_基础)
- rhel-exam2
- 最大流最小割定理
- 这是一道水题 UESTC
- Java反射
- 9.用dd生成指定大小的文件
- leetcode 3Sum(Java)
- python3 的 matplotlib绘图库的使用
- Android Studio中的Gradle文件基础
- Vim编辑器中如何编辑多个文件
- Java基础知识之继承
- JavaWeb开发知识总结(二)-(oracle_查询)
- BZOJ 2648: SJY摆棋子/BZOJ 2716: [Violet 3]天使玩偶 kdtree