一个应用可以加载后期出现的类,这种情况可以使用反射技术来完成。
首先告诉类名,直接寻找类名所对应的class文件,并可以将其加载进内存,然后创建其对象,反射技术可以提高程序的扩展性,连new对象都不用了,通过反射技术可以完成对指定名称的类进行对象的创建和内容的调用,其实反射技术就是动态获取一个类,并获取类中的所有内容,简单说反射就是对类的解剖。(反射是用来做框架用的。)
获取字节码文件对象的三种方式:
1、通过Object中的getClass方法获取。
Person p1=new Person();
Class c1=p1.getClass();
Person p2=new Person();
Class c2=p2.getClass();
(c1==c2);//true
因为内存只有一个通过字节码文件创建的对象,虽然是创建了两个对象,但是他们都是根据同一个字节码创建的,描述等属全部都一样,所以创建的对象也是一样的。
2、通过每一个具体数据类型具备的class静态属性就可以完成该类型的class对象的获取,这种方式:必须要明确具体的类型,比如Person;
Class c=Person.class;
3、通过Class类中的方法,forName就可以完成Class对象的获取,这种方式它的扩展性最强,不需要知道具体的类型、只要知道名字,就可以根绝名称就可以去加载指定的类文件,不需要具备获取class对象的类,前两种方式必须知道class类,
Class clazz=Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");//javaweb加载数据库驱动
为什么要加包名:因为此处是字符串,所以必须要写全。
1、获取指定的字节码文件中的属性:字段:
private static final String PERSON_STRING="cn.itcast.person";
获取指定名称的字节码文件对象
Class clazz=Class.forName(PERSON_STRING);
通过该字节码文件对象的方法获取字节码文件中的字段:
Field[] fields=Clazz.getFields();//获取所有的字段,只能拿到公共的属性字段。
Fields=clazz.getDeclaredFields();//私有的东西都能拿到
for(Field field:fields){
System.out.println(field);
}
2、获取指定名称的字段:
Classclazz=Class.forName(PERSON_STRING);
Field field=clazz.getField("name");
获取字段,但是对于非静态的字段,必须要有所属的对象,既然需要该类的对象,就可以通过class类中的newInstance方法来完成,该类实例的创建。
Object obj=clazz.newInstance();本身就是在调用空参数列表构造函数来完成的。
给指定字段赋值。
field.set(obj,"lisi");
Object value=field.get(obj);
System.out.println(value);
3、获取私有字段:
Class clazz=Class.forName(PERSON_STRING);
Field field=clazz.getDeclaredField("age");
field.setAccessible(true);取消对权限的检查,暴力访问,不建议使用
field.set(obj,69);
Object value=field.get(obj);
Object obj=clazz.newInstance();
System.out.println(value);
4、如果没有空参数构造函数时,要对其进行初始化该怎么办呢?
获取类中的构造函数来对指定类进行对象的初始化。
public static voidgetConsDemo(){
Class clazz=Class.forName(PERSON_STRING);
Constructor cons=clazz.getConstructor(String.class);
Object obj=cons.newInstance("小强");
Field field=clazz.getField("name");
Object value=field.get(obj);
}
一般被反射的类都有一个空参数构造函数
5、获取指定类中的所有方法
public static void getMethodsDemo(){
Class clazz=Class.forName(PERSON_STRING);
Mthod[] methods=clazz.getMethods();
Methods=clazz.getDeclaredMethods();获取私有的方法
for(Method method:methods){
System.out.println(method);
}
}
6、获取指定方法
publicstatic void getMethodDemo(){
Class clazz=Class.forName(PERSON_STRING);
Method method=clazz.getMethod("show",null);
Object obj=clazz.newInstance();
method.invoke(obj,null);//调用invoke方法。要指定参数类型,但是这里是无参数的。
}
7、获取一个带参数的方法
public static void getparamMethodDemo(){
Class clazz=Class.forName(PERSON_STRING);
Method method=clazz.getMethod("paramshow",String.class,int.class);
Object obj=clazz.newInstance();
method.invoke(obj,"小二",23);
}
8、获取一个静态方法
method.invoke(nul,null);不需要参数,因为静态的都不需要对象
9、获取一个私有方法。
Method method=clazz.getDeclaredMethod("privateShow",null);
Object obj=clazz.newInstance();
method.setAccessible(true);
method.invoke(obj,null);