【Java基础知识】Java反射--Class、Constructor、Filed、Method类的使用
2017-01-22 19:12
1106 查看
1、反射概念
是程序可以访问、检测和修改它本身状态或行为的一种能力。Java中的反射,能够创建灵活的代码,这些代码可在运行时装配,无需在组件之间进行源代码链接。简单的说就是:通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。每个类都有一个Class对象,每当编写并且编译了一个新类,就会产生一个Class对象【被保存在一个同名的.class文件中】所有的类都是在对其第一次使用的时候,动态加载到JVM中。Class对象仅在需要的时候才被加载,static初始化是在类加载时进行的。一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。Class类与java.lang.reflect类库一起对反射的概念进行了支持,该类包含了Filed,Method,Constructor类,这些类型的对象由JVM在运行时创建,用以表示未知类里对应的成员。这样就可以使用Constructor创建新的对象,使用它get( ), set( )方法读取和修改与Field对象关联的字段,用invoke( )方法调用Method对象关联的方法。另外,还可以调用getFields()、getMethods( )和getConstructor( )等方法,以返回表示字段、方法、以及构造器的对象的数组。这样匿名对象的类信息就可以在运行的时候被完全确定下来,而在编译时不需要知道任何事情。2、如何获取Class对象的引用
获取Class对象的引用【返回表示该对象实际类型的Class引用】的方法,常用的有3种:(1)Object类的getClass()方法:如果我们已经拥有我们所需要类型的对象,就可以通过调用getClass()方法获取Class引用。
(2)类字面常量,数据类型的静态属性class
(3)Class类中的静态方法:public static Class forName(String className).在日常的开发中,常用的是第三种方式获取Class对象,因为是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
获取Class对象的引用示例:
public class ReflectDemo { public static void main(String[] args) throws ClassNotFoundException { /*方式1:通过getClass()方法获取Class对象 * 创建同一个类不同的对象,他们的Class对象是同一个。*/ Person person1 = new Person(); Class clazz1 = person1.getClass(); Person person2 = new Person(); Class clazz2 = person2.getClass(); System.out.println(person1 == person2);// false System.out.println(clazz1 == clazz2);// true // 方式2:通过class静态属性获取Class对象 Class clazz3 = Person.class; System.out.println(clazz1 == clazz3);//true // 方式3:Class类的静态方法forName() Class clazz4 = Class.forName("cn.edu.Person"); System.out.println(clazz1 == clazz4);//true } }
3、通过Class对象获取Constructor对象,并调用构造方法创建实例
(1)获取单个构造方法public Constructor<T> getConstructor(Class<?>... parameterTypes): 返回指定参数类型、具有public访问权限的构造函数
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes): 返回指定参数类型、所有声明的(包括private)构造函数
参数表示的是:你要获取的构造方法的,构造参数个数,及数据类型的class字节码文件对象
(2)获取多个构造方法
public Constructor[] getConstructors():所有公共构造方法 public Constructor[] getDeclaredConstructors():所有构造方法
(3)通过获得的Constructor对象,创建新实例
package cn.edu.reflect; public class Person { /** * 3种范围的成员变量:private, 默认,public * */ private String name; int age; public String address; /**构造函数:无参, 有参(1,2,3个参数)*/ public Person() { } private Person(String name) { this.name = name; } Person(String name, int age) { this.name = name; this.age = age; } public Person(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } /** * 成员函数: * ①public, private * ②有参,无参 * ③无返回值(void),有返回值 * */ public void show() { System.out.println("show"); } public void method(String s) { System.out.println("method " + s); } public String getString(String s, int i) { return s + "---" + i; } private void function() { System.out.println("function"); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]"; } }
public T newInstance(Object... initargs): 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
通过反射获取构造方法并使用一:
package cn.edu.reflect; import java.lang.reflect.Constructor; /*通过反射获取构造方法并使用*/ public class ReflectDemo { public static void main(String[] args) throws Exception { Class clazz = Class.forName("cn.edu.reflect.Person"); //1.获取Constructor[] Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } //2.获取单个默认构造,并且使用获得的此Constructor 对象,创建类的新实例 Constructor con = clazz.getConstructor();//返回的是构造方法对象 Person person1 = new Person(); System.out.println(person1); //调用Constructor的newInstance()方法,实例化对象 Object obj = con.newInstance(); System.out.println(obj); Person person2 = (Person)obj; person2.show(); } } /*运行结果如下: public cn.edu.reflect.Person(java.lang.String,int,java.lang.String) cn.edu.reflect.Person(java.lang.String,int) private cn.edu.reflect.Person(java.lang.String) public cn.edu.reflect.Person() Person [name=null, age=0, address=null] Person [name=null, age=0, address=null] show * */
通过反射去获取该构造方法并使用二:
/* public Person(String name, int age, String address) Person p = new Person("张国荣",47,"香港九龙"); System.out.println(p); */
public class ReflectDemo2 { public static void main(String[] args) throws Exception { Class clazz = Class.forName("cn.edu.reflect.Person"); /*1.获取带参构造方法对象*/ Constructor con = clazz.getConstructor(String.class, int.class,String.class); /*2.通过带参构造方法对象创建对象*/ Object obj = con.newInstance("张国荣",47,"香港九龙"); System.out.println(obj); } } /*Person [name=张国荣, age=47, address=香港九龙]*/
通过反射获取私有构造方法并使用三:
/* private Person(String name){} Person p = new Person("张国荣"); System.out.println(p); */
public class ReflectDemo3 { public static void main(String[] args) throws Exception { Class clazz = Class.forName("cn.edu.reflect.Person"); Constructor constructor = clazz.getDeclaredConstructor(String.class); /*用该私有构造方法创建对象,IllegalAccessException:非法的访问异常, 暴力访问,值为true则指示反射的对象在使用时应该取消Java语言访问检查。*/ constructor.setAccessible(true); Object obj = constructor.newInstance("张国荣"); System.out.println(obj); } } /* Person [name=张国荣, age=0, address=null]*/
4、通过Class实例获取成员变量对象,并且使用成员变量
通过发生获取成员变量并使用public Field[] getFields(): 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 public Field getField(String name): 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段 public Field[] getDeclaredFields(): public Field getDeclaredField(String name):
使用代码实例:
public class ReflectDemo4 { public static void main(String[] args) throws Exception { Class clazz = Class.forName("cn.edu.reflect.Person"); //1.获取所有的成员变量 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } //2.通过无参构造方法创建对象 Constructor constructor = clazz.getConstructor(); Object obj = constructor.newInstance(); System.out.println(obj); /*3.获取单个的成员变量,获取address【public】并对其赋值 *public void set(Object obj,Object value),第一个参数是要修改字段的对象 * 正被修改对象的字段的新值, 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。 * 给obj对象的addressField字段设置值为"香港.九龙" */ Field addressField = clazz.getField("address"); addressField.set(obj, "香港.九龙"); System.out.println(obj); // 获取name【private】并对其赋值 Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); nameField.set(obj, "张国荣"); System.out.println(obj); // 获取age【默认】并对其赋值 Field ageField = clazz.getDeclaredField("age"); ageField.setAccessible(true); ageField.set(obj, 47); System.out.println(obj); } } /* private java.lang.String cn.edu.reflect.Person.name int cn.edu.reflect.Person.age public java.lang.String cn.edu.reflect.Person.address Person [name=null, age=0, address=null] Person [name=null, age=0, address=香港.九龙] Person [name=张国荣, age=0, address=香港.九龙] Person [name=张国荣, age=47, address=香港.九龙] */
5、通过Class实例获取Method对象,并调用方法
public Method[] getMethods():返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口
(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member方法。
public Method[] getDeclaredMethods():
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,
包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
public Method getMethod(String name,Class
public class ReflectDemo5 { public static void main(String[] args) throws Exception { Class clazz = Class.forName("cn.edu.reflect.Person"); Method[] methods = clazz.getMethods(); for (Method method : methods) { System.out.println(method); } Constructor constructor = clazz.getConstructor(); Object obj = constructor.newInstance(); /*1 、获取单个方法【public,无参数,无返回值】,并使用: public void show() */ Method method1 = clazz.getMethod("show"); method1.invoke(obj); //调用obj对象的m1方法 /*2 、获取单个方法【public,有参数,无返回值】,并使用:public void method(String s) */ Method method2 = clazz.getMethod("method", String.class); method2.invoke(obj, "hello"); /*3 、获取单个方法【public,有参数,有返回值】,并使用:public String getString(String s, int i)*/ Method method3 = clazz.getMethod("getString", String.class, int.class); String s =(String)method3.invoke(obj, "hello", 100); System.out.println(s); //4 、获取单个方法【private,无参数,无返回值】,private void function() Method method4 = clazz.getDeclaredMethod("function"); method4.setAccessible(true); method4.invoke(obj); } }
相关文章推荐
- JAVA基础知识之JVM-——使用反射生成并操作对象
- java基础-反射2(反射,反射操作对象,Class对象的使用,类型信息的获取)
- Java ClassLoader基础知识
- JAVA反射使用实例和class.getResource()得到URL中含有中文和空格乱码问题
- 学习Spring必学的Java基础知识(1)----反射
- Java 基础小知识二:使用Comparator 对ArrayList 进行排序
- java反射基础知识
- 黑马程序员--Java基础加强--16.利用反射操作泛型V【通过Constructor反射解析泛型构造方法】【通过Field反射解析泛型成员变量】【个人总结】
- JavaMail基础知识6-JavaMail API使用之消息的回复及转发
- Java基础知识_反射
- 《Spring 3.x 企业应用开发实战》学习笔记 第三章 IoC容器概述 3.2 相关Java基础知识 类装载器 反射机制
- (Java 基础知识) Java反射
- Java基础知识JNI 在Android中使用System.loadLibrary()
- Java基础知识_框架的概念以及用反射开发框架的原理
- 学习Spring必学的Java基础知识----反射
- JavaMail基础知识3-JavaMail API使用之消息提取
- JavaMail基础知识4-JavaMail API使用之消息和标志的删除
- 01-java基础加强,eclipse工具使用,快捷键,断点调试,单元测试,jdk5新特性,增强for循环,集合map,list,可变参数,枚举,反射,泛型
- 黑马程序员--Java基础加强--17.利用反射操作泛型VI【泛型类型变量的语义】【GenericDeclaration接口】【泛型接口TypeVariable】【通过Class反射解析泛型类】
- JavaMail基础知识2-JavaMail API使用之发送消息