java反射机制
1、 java反射机制
JAVA 反射机制就是在运行状态中,对于任意一个类,都可以知道这个类的所有的属性和方法;
对于任意一个对象,都可以调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为Java的反射机制。
2、 获取Class对象的三种方式:
1. 通过Object类获取
Class cs1 = new String(“”).getClass();
2. 通过Class类的静态方法来获取
Class cls = Class.forName("demo1.User");// 类的全路径
3. 如果T是一个已定义的类型,在Java中。它的.Class文件名:T.Class就代表了与其匹配的Class对象。
Class cs1= Person.class;
Class cs2=int.class;
3、 Class类重要方法:
1. getName()
返回String形式的该类的简要描述。
2. newInstance()
该方法根据Class对象产生该对应类的实例,
Constructor cs[] = cls.getConstructors();
User user = (User) cs[0].newInstance();
或者:
User user2 = (User) cs[1].newInstance("myname");
3. getClassLoader()
返回该Class对象对应的类加载器。
4. getComponentType()
该方法针对数组对象的Class对象,可以得到该数组的组成元素所对应对象的Class对象。
Int[] ints = new int{1,2,3};
Class cls1 = ints.getClass;
Class cls2 = cls1. getComponentType();
Cls2对象所对应的就是int这个基本类型的Class对象。
5. getSuperClass();
返回某个子类对应的直接父类所对应的Class对象。
6. isArray();
判断此Classduix 所对应的是否是一个数组对象。
4、 反射机制的功能:
1、 在运行时判断任意一个对象所属的类;
2、 在运行时构造任意一个类的对象;
3、 判断任意一个类所具有的成员变量和方法;
4、 运行时调用任意一个对象的方法;
5、 生成动态代理;
5、下面这段代码有助于我们更好的理解反射。
实体类:
package demo1;public class User {
public User() {
System.out.println("调用User无参构造方法");
}
public User(String username) {
this.username = username;
System.out.println("调用带参数User的构造方法");
}
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private String getUsername2() {
return username;
System.out.println("调用了私有get方法");
}
}
测试类:
package demo1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class test1 {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) throws Exception {
// 1、加载user实体类
Class cls = Class.forName("demo1.User");// 类的全路径
// 2、查看类的构造方法
Constructor cs[] = cls.getConstructors();// 获取的构造函数不是按照顺序来获取的
System.out.println("cs数组构造函数顺序" + cs[0].getParameterTypes());// 查看获取的构造函数需要的是什么样的参数
System.out.println("构造方法个数" + cs.length);
// 3、用构造方法创建对象
User user = (User) cs[0].newInstance();
// 构造方法 传入参数
User user2 = (User) cs[1].newInstance("myname");
System.out.println(user2.getUsername());
// 获取指定的构造函数 有参
Constructor c = cls.getConstructor(String.class);
User user3 = (User) c.newInstance("myname");
System.out.println(user3.getUsername());
// 无参
Constructor c2 = cls.getConstructor();
User user4 = (User) c2.newInstance();
System.out.println(user4.getUsername());
// 获取变量,只能访问公有的
// Field fields[] = cls.getFields();
// getDeclared获得所有属性
Field fields[] = cls.getDeclaredFields();
System.out.println(fields.length);
for (Field f : fields) {
System.out.println(f.getName());
}
// Field field = cls.getField("username");
Field field = cls.getDeclaredField("username");
// 使私有属性可访问
field.setAccessible(true);
System.out.println(field.get(user2));
// obj.username
// 获取方法
Method method = cls.getMethod("setUsername", String.class);
method.invoke(user2, "lin");
Method method2 = cls.getMethod("getUsername");
System.out.println(method2.invoke(user2));
Method method3 = cls.getDeclaredMethod("getUsername");
method3.setAccessible(true);
System.out.println("私有get:" + method3.invoke(user2));
}
6、异常:上述代码可能存在异常(jdk版本不同)
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
出现此异常是因为:
// 2、查看类的构造方法
Constructor cs[] = cls.getConstructors();
获取的构造函数不是按照顺序来获取的
而调用
// 3、用构造方法创建对象
User user = (User) cs[0].newInstance();
cs[0]可能是有参构造函数,想要的到无参的实例,就报错。
当然也有可能不会报错,可能是jdk版本存在的问题,这问题不是关注反射的重点。
此外在数据库连接中,加载数据库的驱动类,也是用到了反射。