Student stu = new Student("zhangsan",30);
Class.forName("com.Lct.Person.Student").newInstance();
Java的反射机制的实现要借助于class类和java.lang.reflect包下4个类: Constructor, Field, Method,Array
Class类 - 代表类的Class对象
Constructor类-代表类的构造方法
Field类-代表类的属性
Method类-代表类的方法
Array类 - 提供动态创建数组,以及访问数组元素的静态方法
通过前四个对象我们可以粗略的看到一个类的各个组成部分
Array类会在最后有所简述。
Java 反射机制主要提供了以下功能
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法
代码示例(获取Class对象)
package com.Lct.classtype;
public class ClassDemo {
public static void main(String[] args) {
//使用实例对象.getClass()
/*Employee employee = new Employee("zhangsan", 18); Class> class1 = employee.getClass(); System.out.println(class1.getName()); System.out.println(class1.getSuperclass().getName());*/
//使用类名.Class
/*Class> class1 = Employee.class; System.out.println(class1.getName()); System.out.println(class1.getSuperclass().getName());*/
//使用Class.forName("")
/*try { Class> class1 = Class.forName("com.Lct.classtype.Employee"); System.out.println(class1.getName()); System.out.println(class1.getSuperclass().getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); }*/
//基本数据类型的Class对象
/* Class > class1 = int.class; System.out.println(class1.getName()); //基本数据类型没有父类,下面代码会报NullPointerException异常 //System.out.println(class1.getSuperclass().getName()); */
//包装类获取基本数据类型的Class对象
/* Class > class1 = Integer.TYPE; System.out.println(class1.getName()); //基本数据类型没有父类,下面代码同样会报NullPointerException异常 //System.out.println(class1.getSuperclass().getName()); */
//获取包装类的Class对象
Class > class1 = Integer.class;
System.out.println(class1.getName());
System.out.println(class1.getSuperclass().getName());
}
}
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Constructor getConstructor(Class[] params) — 根据构造函数的参数,返回一个具体的具有public属性的构造函数
Constructor getConstructors() — 返回所有具有public属性的构造函数数组
Constructor getDeclaredConstructor(Class[] params) — 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
Constructor getDeclaredConstructors() — 返回该类中所有的构造函数数组(不分public和非public属性)
Method getMethod(String name, Class[] params) — 根据方法名和参数,返回一个具体的具有public属性的方法
Method[] getMethods() — 返回所有具有public属性的方法数组
Method getDeclaredMethod(String name, Class[] params) — 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
Method[] getDeclaredMethods() — 返回该类中的所有的方法数组(不分public和非public属性)
Method getMethod(String name, Class[] params) — 根据方法名和参数,返回一个具体的具有public属性的方法
Method[] getMethods() — 返回所有具有public属性的方法数组
Method getDeclaredMethod(String name, Class[] params) — 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
Method[] getDeclaredMethods() — 返回该类中的所有的方法数组(不分public和非public属性)
Method[] getDeclaredMethods()
Method[] getMethods()
抽象的文字描述总是没有代码表现的直白,示例代码中有这两个方法的调用,运行后的结果如下:
getDeclaredMethods方法获取的所有方法 | getMethods方法获取的所有方法 |
---|---|
修饰符–方法名–返回值类型 | 修饰符–方法名–返回值类型 |
public – toString – class java.lang.String | public – toString – class java.lang.String |
public – getName – class java.lang.String | public – getName – class java.lang.String |
public – write – void | public – write – void |
public – setName – void | public – setName – void |
private – work – void | 无法获得work方法 |
public – setAge – void | public – setAge – void |
public – getAge – int | public – getAge – int |
public – sleep – void (父类公共方法) | |
public final – wait – void (超类公共方法) | |
public final native – wait – void (超类公共方法) | |
public final – wait – void (超类公共方法) | |
public – equals – boolean (超类公共方法) | |
public native – hashCode – int (超类公共方法) | |
public final native – getClass – class java.lang.Class (超类公共方法) | |
public final native – notify – void (超类公共方法) | |
public final native – notifyAll – void (超类公共方法) |
配合表格再去看API中的注解就事半功倍了。
Note:
代码示例
package com.Lct.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/** * 测试类 */
public class ReflectionAPIDemo {
public static void main(String[] args) throws Exception{
//获取Employee类所关联的Class对象
Class> classType = Class.forName("com.Lct.reflection.Employee");
//方法1
//通过反射机制调用无参构造方法来实例化对象
Employee employee = (Employee) classType.newInstance();
System.out.println(employee);
System.out.println("----------------------------------");
//方法2
//通过反射机制获取构造方法对象,再通过该对象来实例化Employee类的实例
Constructor> ct = classType.getConstructor(new Class[]{});
//直接强制类型转换也是可以的
Object object = ct.newInstance(new Object[]{});
if (object instanceof Employee) {
Employee em1 = (Employee) object;
System.out.println(em1);
}
System.out.println("----------------------------------");
//通过反射机制获取带参数的构造方法对象,再通过反对向实例化Employee类的实例
Constructor> ct2 = classType.getConstructor(new Class[]{String.class,int.class});
Employee em2 = (Employee) ct2.newInstance(new Object[]{"张三",18});
System.out.println(em2);
//<<关于getMethods()和getDeclaredMethods()的区别>>
//通过反射机制获取Employee类中的所有方法,包括私有的
Method[] methods = classType.getDeclaredMethods();
for (Method method : methods) {
System.out.println(Modifier.toString(method.getModifiers())+"--"+method.getName()+"--"+method.getReturnType());
}
System.out.println("----------------------------------");
//通过反射机制获取Employee类和超类中的所有共有方法
Method[] m2 = classType.getMethods();
for (Method m : m2) {
System.out.println(Modifier.toString(m.getModifiers())+"--"+m.getName()+"--"+m.getReturnType());
}
System.out.println("----------------------------------");
//getMethod方法调用父类的方法
//getDeclaredMethod方法无法调用父类的public方法
Method method2 = classType.getMethod("eat", new Class[]{});
method2.invoke(em2, new Object[]{});
System.out.println("----------------------------------");
//通过反射机制获取指定的方法,包括私有的,并可以调用它
Method method = classType.getDeclaredMethod("work", new Class[]{int.class});
System.out.println(method);
//使私有的可以访问
method.setAccessible(true);
//方法的调用
method.invoke(em2, new Object[]{3});
System.out.println("----------------------------------");
//通过反射机制获取所有属性,包括私有的
Field[] fields = classType.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("----------------------------------");
//通过反射机制获取指定的属性,包括私有的,并可以改变它
Field field = classType.getDeclaredField("name");
//使私有的可以访问
field.setAccessible(true);
String object2 = (String) field.get(em2);
System.out.println(object2);
field.set(em2, "李四");
System.out.println(em2);
System.out.println("----------------------------------");
}
}
/** * 父类 */
class Person{
public void sleep () {
System.out.println("sleeping....");
}
@SuppressWarnings("unused")
private void eat () {
System.out.println("eating....");
}
}
/** * 接口 */
interface Study {
public void write();
}
/** * 子类 */
class Employee extends Person implements Study{
private String name;
private int age;
private Object object;
public Employee() {
super();
System.out.println("无参构造方法");
}
public Employee(String name, int age) {
super();
System.out.println("带参数的构造方法");
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Employee: "+"[name: "+this.name+" age: "+this.age+"]";
}
@SuppressWarnings("unused")
private void work (int num) {
System.out.println(num+" Employee -- working...");
}
@Override
public void write() {
System.out.println(" Employee -- writing...");
}
}
Array
目前很少这么用,个人感觉也是没必要,但是本着存在即合理的原则还是写下来,留个印象。
代码示例
package com.Lct.reflection;
import java.lang.reflect.Array;
public class reflectionArrayDemo {
public static void main(String[] args) throws Exception{
Class> class1 = Class.forName("java.lang.String");
//创建一维数组
Object array = Array.newInstance(class1, 9);
Array.set(array, 0, "zhangdan");
System.out.println(Array.get(array, 0));
//创建二维数组
Object array2 = Array.newInstance(class1, new int[]{2,3}/*创建2行3列的二维数组*/);
Object arrayObj = Array.get(array2, 1);
Array.set(arrayObj, 1, "lisi");
System.out.println(Array.get(arrayObj, 1));
}
}
Android反射机制实现与原理
作者写的巨细靡遗,其中LoadMethod类和升级版的LoadMethodEx类非常值得学习。
Android系统原理与源码分析(1):利用Java反射技术阻止通过按钮关闭对话框
这篇博客是Java反射机制在android中的使用实例,知道可以这样用就好,但不推荐,虽然反射很强大,但是也需谨慎使用。