Class对象
Class对象就是用来创建类的所有“常规“对象的,每一个类都有一个Class对象,每当编译了一个新类,就会产生一个Class对象,保存在同名的.class文件中。
Class.forName(" ");
这个方法是Class类(所有Class对象都属于这个类)的一个static成员,类名需要全包名,返回一个Class对象的引用。
一些常用的方法
Class的newInstance()方法是实现虚拟构造器的一种途径,会返回一个新的Object实例。
类字面常量
java提供了另一种方法来生成对Class对象的引用:类名.class,这样不仅简单,而且在编译时就会受到检查。
泛化的Class引用
Class intclass=int.class;
Class<Integer> gIntClass=int.class;
gIntClass=Integer.class;
intclass=double.class;
gIntClass=double.class//有错误
泛型类的引用只能赋值为其声明的类型,但是普通的类引用可以重新赋值为任何其他的Class对象。
通配符
Class<?> 优于平凡的Class,好处是表示你碰巧或者由于疏忽,而使用了一个非具体类引用,你就是选择了非具体版本。
Class<? extends 类型>被限定为此类型或他的子类。
获取属性
//公共属性
Field[] fields = perClazz.getFields() ;
for(Field field:fields) {
System.out.println(field);
}
System.out.println("====");
//所有属性 (属性的 :公共属性\所有属性的区别 同“方法”)
Field[] declaredFields = perClazz.getDeclaredFields() ;
for(Field declaredField:declaredFields) {
System.out.println(declaredField);
}
获取方法
try {
perClazz = Class.forName("reflect.Person") ;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//获取所有的 公共的方法(1.本类 以及 父类、接口中的所有方法 2.符合访问修饰符规律)
Method[] methods = perClazz.getMethods();
for(Method method:methods) {
System.out.println(method);
}
System.out.println("==========");
//获取当前类的所有方法(1.只能是当前类 2.忽略访问修饰符限制)
Method[] declaredMethods = perClazz.getDeclaredMethods();
for(Method declaredMethod:declaredMethods) {
System.out.println(declaredMethod);
}
获取接口
Class<?>[] interfaces = perClazz.getInterfaces() ;
for(Class<?> inter:interfaces) {
System.out.println(inter);
}
获取父类
Class<?> superclass = perClazz.getSuperclass() ;
System.out.println(superclass);
获取所有构造方法
Constructor<?>[] constructors = perClazz.getConstructors() ;
for(Constructor<?> constructor:constructors) {
System.out.println(constructor);
}
获取一个对象并操作
public static void demo01() throws InstantiationException, IllegalAccessException {
Class<?> perClazz = null ;
try {
perClazz = Class.forName("reflect.Person") ;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person per = (Person)perClazz.newInstance() ;
per.setName("zs");//person中已有的方法
per.setAge(23);
System.out.println( per.getName()+","+per.getAge());
}
操作属性
Field/Method/Constructor.setAccessible(true)方法将访问权限忽略
Person per = (Person)perClazz.newInstance() ;
Field idField = perClazz.getDeclaredField( "id");//根据名字找属性
//访问的是private修饰的id,但是private是私有
//修改属性的访问权限 使用反射时,如果 因为访问修饰符限制造成异常,可以通过 Field/Method/Constructor.setAccessible(true)
idField.setAccessible(true);
idField.set(per, 1); //per.setId(1);
System.out.println( per.getId() );
操作方法
第一个参数是方法名买第二个参数是获取方法的参数类型
Method method = perClazz.getDeclaredMethod("privateMethod", null) ;
method.setAccessible(true);
method.invoke(per,null ) ;//方法的调用:invoke()
//per.say(xxx);
//
Method method2 = perClazz.getDeclaredMethod("privateMethod2", String.class) ;
method2.setAccessible(true);
method2.invoke(per, "zs") ;
操作构造方法
//获取指定的构造方法
//在反射中,根据类型 获取方法时:基本类型(int、char...)和包装类(Integer,Character)是不同的类型
Constructor<?> constructor = perClazz.getConstructor(Integer.class) ;
System.out.println(constructor);
//
Constructor<?> constructor2 = perClazz.getDeclaredConstructor(String.class) ;
System.out.println(constructor2);
//Person per = new Person() ;
//
//
//根据获取的private构造方法,获取对象实例
constructor2.setAccessible(true);
Person per3 = (Person)constructor2.newInstance("zs") ;
System.out.println("per3"+per3);
//
Person per4 = (Person)constructor.newInstance(23) ;//因为constructor是 有参构造方法(Integer),因此需要传入一个Integer值
System.out.println(per4);
//
Constructor<?> constructor3 = perClazz.getConstructor() ;
Person per5 = (Person)constructor3.newInstance( ) ;//因为constructor3是 无参构造方法,因此不需要传值
//
System.out.println(per5);
}