反射的学习与应用
1. 类对象
1.1 概念
Java 中有一个类,java.lang.Class 类。这个类的对象,就被称之为类对象。
源代码编写好后进行编译后产生的.class文件就是一个类对象
1.2 获取类对象
类名.class
Class c = Sports.class;
Class c2 = int.class;
System.out.println(c);
System.out.println(c2);
结果为:
c为类全名,c2为 int 数据类型
对象.getClass()
Sports p = new Sports();
System.out.println(p.getClass());
结果为:
Class.forName()
try {
Class c3 = Class.forName("com.qf.day09.t5.Sports");
System.out.println(c3);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
结果为:
1.3 使用类对象获取类的信息
当我们获得了类对象,当然就可以调用类对象中的方法。
例如:
- getName(): 获得类的名称,包括包名
- getSimpleName(): 获得类的名称,不包括包名
- getSuperClass(): 获得本类的父类的类对象
- getInterfaces() : 获得本类所实现的所有接口的类对象,返回值类型为 Class[],当然, 这是对的,一个类可以实现多个接口
1.4 使用类对象获取类中方法的信息
在 Class 类中,有两个方法,这两个方法签名如下:
- public Method[] getDeclaredMethods() throws SecurityException
- public Method[] getMethods() throws SecurityException
getMethods() 方法
返回的 Method 类型的数组中,包括所有的公开方法,也包括 父类中定义的公开方法
Method[] ms = c.getMethods();
for(int i = 0; i < ms.length; i++){
System.out.println(ms[i]);
}
结果为:
** getDeclaredMethods ()方法**
会返回在本类中定义的所有方法,包括私有方法
Method[] ms6 = c.getDeclaredMethods();
for(int i = 0; i<ms6.length; i++){
System.out.println(ms6[i].toString());
}
1.5 使用类对象创建对象
newInstance(),这个方法能够通过类的无参构造方法,创建一个对 象。
try {
Sports sports = (Sports)c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
结果为;
2.1 反射包
Field 类封装了属性信息,一个Field对象封装了一个属性的信息。
getField(String name)
可以获得本类的公开书信和以及从父类继承到的公开属性,但是无法获得非公开属性
public static void test(){
Student stu = new Student();
Class c = stu.getClass();
try {
Field nameFile = c.getField("name");
nameFile.set(stu,"tom");
Object value1 = nameFile.get(stu);
System.out.println(value1);
}catch (Exception e){
e.printStackTrace();
}
}
结果为:
getDeclaredMethods(String name)
getDeclaredMethods方法只能获得本类属性,但包括本类的非公开属性
public static void test(){
Student stu = new Student();
Class c = stu.getClass();
try {
Field f = c.getDeclaredField("name");
f.set(stu,"tom");
Object value = f.get(stu);
System.out.println(value);
}catch (Exception e){
e.printStackTrace();
}
}
结果为:
私有属性 setAccessible
除了能够获得 类中的公开属性之外,利用反射还能获得并修改对象的私有属性。
Field无法获得父类的私有属性
public static void test2(){
Student stu = new Student();
try {
Field f = stu.getClass().getDeclaredField("age");
f.setAccessible(true);
f.set(stu,new Integer(18));
Object value = f.get(stu);
System.out.println(value);
}catch (Exception e){
e.printStackTrace();
}
}
结果为:
Method类
public Method getMethod(String name,Class[] parameterTypes)
public Method getDeclaredMethod(String name,Class[] parameterTypes)
两个方法的区别同样与 getMethods 方法和 getDeclaredMethods 方法类似。
getMethod 可 以获得公开方法,包括父类的;getDeclaredMethod 只能获得本类的方法,但不限于公开方 法。
getMethod 以及 getDeclaredMethod 方法有两个参数。
第一个参数是一个字符串参数,表示的是方法的方法名。
第二个为个方法的参数表。
public static void test3(){
Student stu = new Student();
Class c= stu.getClass();
try {
Field f = stu.getClass().getDeclaredField("name");
f.set(stu,"wangwu1");
Method m = c.getDeclaredMethod("study",new Class[]{int.class,double.class});
Object result = m.invoke(stu,new Object[]{new Integer(10),new Double(1.5)});
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
Constructor类
Constructor类封装了构造函数的信息
- 通过 Class 类中的 getConstructors() / getDeclaredConstructors()获得 Constructor 数组。
- 可以通过 Class 类中的 getConstructor() / getDeclaredConstructor()来获得指定的构 造方法。
- ,可以调用 Constructor 类中的 newInstance 方法创建对象
如果创建对象只需要调用无参构造方法的话,就可以直接使用 Class 类中的 newInstance 方法,如果在创建对象的时候需要指定调用其他构造方法的话,就需要使用 Constructor 类。
public class TestConstructor {
public static void main(String[] args) {
try {
Class c= Dog.class;
Dog d1 = (Dog) c.newInstance();
System.out.println(d1);
Constructor con = c.getConstructor(new Class[]{String.class,int.class});
Dog d2 =(Dog) con.newInstance(new Object[]{"Snoopy",new Integer((5))});
System.out.println(d2);
} catch (Exception e) {
e.printStackTrace();
}
}
}