Java反射机制
问题:
–如果仅仅知道一个类的类名,能否动态得到类的定义信息,包括哪些方法,属性等?
答案:可以通过反射做到
Java反射的概念和作用
Java反射的概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射的作用
动态获取类的信息,进一步实现需要的功能。
Java反射相关API
我们创建一个user类,作为示例
package com.system.test;
public class User {
public String name;
public int age;
private String eat;
public User(){
System.out.println("无参构造方法");
}
public User(String name){
System.out.println("一个参数的构造方法");
}
private User(String name,int age){
System.out.println("两个参数的私有构造方法");
}
public void eat(){
System.out.println("无参方法");
}
public void eat(String name){
System.out.println("一个参方法");
}
private void eat(String name,int age){
System.out.println("两个参方法");
}
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;
}
public String getEat() {
return eat;
}
public void setEat(String eat) {
this.eat = eat;
}
}
Class 类型
一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象。
Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息。
要使用Class类的方法,必须先获得Class类的实例
获得Class类实例的常用方法有如下三个
- 类名.Class
- new + 对象 对象.getClass()
- Class.forName(“路径”)
package com.system.test;
public class test {
/*
使用反射的前提是获得Class对象
*/
public static void main(String[] args) throws ClassNotFoundException {
//1.类名.Class
Class class1 = User.class;
System.out.println(class1);
//2.new + 对象 对象.getClass()
User user = new User();
Class class2 = user.getClass();
System.out.println(class2);
System.out.println(class1==class2);
//3.Class.forName("路径")
//根据类地址,加载类信息到内存中, 创建Class对象,通过Class对象动态获取信息
Class class3 = Class.forName("com.system.test.User");
System.out.println(class3);
System.out.println(class3==class1);
}
}
Constructor 构造方法
package com.system.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class test2 {
/*
使用反射的前提是获得Class对象
*/
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//根据类地址,加载类信息到内存中, 创建Class对象,通过Class对象动态获取信息
Class c = Class.forName("com.system.test.User");
/*
获得类中的构造方法
c.getConstructor()
*/
Constructor constructor1 = c.getConstructor();//获得公告的无参构造方法
User user = (User) constructor1.newInstance();//通过COnstructor类中的newInstance()创建对象
System.out.println(user);
Constructor constructor2 = c.getConstructor(String.class);//获得公共的且只有一个参数的构造方法
User user1 = (User) constructor2.newInstance("admin");
Constructor[] constructor3 = c.getConstructors();//获得所有的公共构造方法
System.out.println(constructor3.length);
Constructor constructor4 = c.getDeclaredConstructor(String.class, int.class);//获得指定的构造方法,包括私有的
constructor4.setAccessible(true);//设置私有权限也可以被访问
User user4 = (User) constructor4.newInstance("admin", 22);
Constructor[] constructor5 = c.getDeclaredConstructors();//获得所有的构造方法信息,包括私有的
System.out.println(constructor5.length);
}
}
Field 属性
–public Field getField(String name)
–通过指定Field名字,返回Field实例
–注意Field的访问权限
package com.system.test;
import com.system.bean.Admin;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class test3 {
/*
使用反射的前提是获得Class对象
*/
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
User user = new User();
user.setName("admin");
user.setAge(22);
user.setEat("粑粑");
System.out.println(test(user));
System.out.println(test(new com.system.bean.Admin()));
}
public static String test(Object obj) throws IllegalAccessException {
Class c = obj.getClass();
Field[] fs = c.getFields();//获取所有公开属性
Field[] fs1 = c.getDeclaredFields();//获取所有属性包含私有
String s ="";
for (Field f : fs1) {
f.setAccessible(true);
s+=f.getName()+":"+f.get(obj)+",";
}
return s.substring(0,s.length()-1);
}
}
Method 方法
Method类将类中的方法进行封装,可以动态获得方法的信息,例如
–getName:获得方法名字
–getParameterTypes:获得方法参数类型
除了动态获得方法信息外,Method还能动态调用某一个对象的具体方法
–invoke(Object obj, Object… args) :使用obj调用该方法,参数为args
Method实例都是通过Class类的方法获得
–Method getMethod(String name, Class… parameterTypes) :通过指定方法名,参数类型,返回一个Method实例
package com.system.test;
import com.system.bean.Admin;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test4 {
/*
使用反射的前提是获得Class对象
*/
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
/*
使用反射前提是获得Class对象
*/
//想调用User类中的 eat
test("com.system.test.User","eat");
test("com.system.bean.Admin","getId");
}
public static void test(String className,String methodName) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class c = Class.forName(className);//Class中封装类的信息
Object obj = c.newInstance();//创建一个对象
Method m = c.getMethod(methodName);//获得类中指定名称的方法
m.setAccessible(true);
m.invoke(obj);//执行调用方法
}
}