1.Java反射
1.以前如何使用一个Java类:
- 已知一个类的类名、以及类中的方法属性、构造方法等;
- 调用构造方法创建对象;
- 使用对象调用方法或属性;例:Student student = new Student()。
2.如果仅仅知道一个类的类名,能否动态得到类的定义信息,包括哪些方法、属性等?
通过反射做到:“com.ff.test.bean.Student”
以前学过的反射:JDBC:“com.mysql.cj.jdbc.Driver”;
配置Servlet< servlet-class >全类名。
3.Java反射的概念:
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
3.Java反射的作用:
动态获取类的信息,进一步实现需要的功能。
2.Java反射相关API
1.Java反射相关的类主要包括:
- Class 类型;
- Constructor 构造方法;
- Method 方法;
- Field 属性。
除Class外,其他类都位于java.lang.reflect包中。可见,反射API将类的类型、方法、属性都封装成了类,其中最重要的类是Class,可以说,反射的使用都是从Class开始。
2.Class类 - 一旦class文件被加载到内存,就会为其创建一个Class对象,任何类被使用时都会创建一个Class对象。
- Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息。
3.获得Class的三种方式
(1)Object类中的getClass方法:适用于通过对象获得Class实例的情况,任何类都继承到了getClass方法,任意对象可以调用getClass方法获得Class实例;
(2)类名.class方式:适用于通过类名获得Class实例的情况;
(3)Class类的静态方法:forName(String name):适用于通过类型获得Class实例的情况,尤其类名是变量。
package com.ff.webpro.reflect;
public class User {
public int num;
private String name;
public User(){
System.out.println("无参构造函数");
}
public User(int num){
this.num = num;
System.out.println("一个参数构造函数");
}
public User(int num, String name) {
this.num = num;
this.name = name;
System.out.println("2个参数构造函数(公共)");
}
private User(String name,int num){
this.num = num;
this.name = name;
System.out.println("2个参数构造函数(私有)");
}
@Override
public String toString() {
return "User{" +
"num=" + num +
", name='" + name + '\'' +
'}';
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void eat(){
System.out.println("eat无参方法");
}
public void eat(String a){
System.out.println("eat1个参数方法"+a);
}
public void eat(String a,int n){
System.out.println("eat2个参数方法,私有"+a+n);
}
}
package com.ff.webpro.reflect;
public class TestClass {
/*
Class类的对象理解:
每一个类被加载到内存中,都会创建一个Class的对象,来存储类的信息,反射的起点就是获得类的Class对象。
*/
public static void main(String[] args) throws ClassNotFoundException {
//获得Class对象方式1
String className = "com.ff.webpro.reflect.User";
Class uclass1 = Class.forName(className);
System.out.println(uclass1);//class com.ff.webpro.reflect.User
//获得Class对象方式2
Class uclass2 = User.class;
System.out.println(uclass2);//class com.ff.webpro.reflect.User
System.out.println(uclass1 == uclass2);//true
//获得Class对象方式3
User user1 = new User();
User user2 = new User();
Class uclass3 = user1.getClass();
Class uclass4 = user2.getClass();
System.out.println(uclass3);//class com.ff.webpro.reflect.User
System.out.println(uclass4);//class com.ff.webpro.reflect.User
System.out.println(uclass3 == uclass4);//true
}
}
4.Constructor类
- Constructor类可以通过get***方法获得构造方法的基本信息,例:getName:返回构造方法的名字。
- 除了获得构造方法的基本信息,还可以创建实例:newInstance(Object… initargs):创建实例。
- Constructor实例通过Class实例获得,Class类中定义了如下方法:Constructor< T> getConstructor(Class… parameterTypes):通过指定参数类型,返回构造方法实例。
package com.ff.webpro.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestClass1 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//从Class对象中获得类的相关信息,构造方法,成员变量,成员方法
Class uclass = Class.forName("com.ff.webpro.reflect.User");
//User user = (User)uclass.newInstance();
//获得构造方法
/*Constructor constructor = uclass.getConstructor();//获得的是默认无参的构造方法(公共)
User user = (User) constructor.newInstance();
System.out.println(user);*/
/*Constructor constructor = uclass.getConstructor(int.class,String.class);
User user = (User)constructor.newInstance(22,"张三");
System.out.println(user);*/
/* Constructor declaredConstructor = uclass.getDeclaredConstructor(String.class, int.class);//私有的也可以拿到
declaredConstructor.setAccessible(true);//设置访问权限
User user = (User)declaredConstructor.newInstance("bob",21);
System.out.println(user);*/
Constructor[] declaredConstructors = uclass.getDeclaredConstructors();
for(Constructor con:declaredConstructors){
con.setAccessible(true);
System.out.println(con.getName());
}
}
}
5.Field类的作用:
- Field类将类的属性进行封装,可以获得属性的基本信息、属性的值,也可以对属性进行赋值,getName:返回属性名,set:设置属性值。
6.获得Field实例
通过Class中的方法实现:
- public Field getField(String name);
- 通过指定Field名字,返回Field实例;
- 注意Field的访问权限。
package com.ff.webpro.reflect;
import java.lang.reflect.Field;
public class TestClass2 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class uclass = Class.forName("com.ff.webpro.reflect.User");
//Object obj = uclass.newInstance();
User user = (User)uclass.newInstance();
/*Field numf = uclass.getField("num");//获得指定的公共的成员变量
numf.set(user,22);
System.out.println(user);*/
/*Field namef = uclass.getDeclaredField("name");
namef.setAccessible(true);
namef.set(user,"张三");
System.out.println(user);*/
Field[] fs = uclass.getDeclaredFields();
for(Field f:fs){
f.setAccessible(true);
System.out.println(f.getName());
}
}
}
7.Method类的作用
- Method类将类中的方法进行封装,可以动态获得方法的信息,例:getName:获得方法名字;getParameterTypes:获得方法参数类型。
- 除了动态获得方法信息外,Method还能动态调用某一个对象的具体方法:invoke(Object obj,Object obj…args):使用obj调用该方法,参数为args
8.获得Method实例
Method实例都是通过Class类的方法获得: - Method getMethod(String name,Class… parameterTypes):通过指定方法名,参数类型,返回一个Method实例。
package com.ff.webpro.reflect;
import java.lang.reflect.Field;
public class TestClass2 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class uclass = Class.forName("com.ff.webpro.reflect.User");
//Object obj = uclass.newInstance();
User user = (User)uclass.newInstance();
/*Field numf = uclass.getField("num");//获得指定的公共的成员变量
numf.set(user,22);
System.out.println(user);*/
/*Field namef = uclass.getDeclaredField("name");
namef.setAccessible(true);
namef.set(user,"张三");
System.out.println(user);*/
Field[] fs = uclass.getDeclaredFields();
for(Field f:fs){
f.setAccessible(true);
System.out.println(f.getName());
}
}
}
package com.ff.webpro.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestClass4 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class uclass = Class.forName("com.ff.webpro.reflect.User");
User user = (User)uclass.newInstance();
Field[] fs = uclass.getDeclaredFields();
for(Field f:fs){
String name = f.getName();
Method getm = uclass.getDeclaredMethod("get"+String.valueOf(name.charAt(0)).toUpperCase()+name.substring(1));
//Method setm = uclass.getDeclaredMethod("set"+String.valueOf(name.charAt(0)).toUpperCase()+name.substring(1),f.getType());
System.out.println(getm.invoke(user));
/* System.out.println(setm.invoke(user,0));*/
}
}
}