1. 简介反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制容许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的全部信息,并可于运行时改变fields内容或唤起methods; 反射机制允许程序在运行时加载、探知、使用编译期间彻底未知的classes。经过JAVA的反射机制,能够得到程序内部或第三方JAR包的CLASS,METHOD,属性,参数等信息。html
2.JAVA动态加载类和静态加载类的区别java
它们俩本质的区别在于静态加载的类的源程序在编译时期加载(必须存在),而动态加载的类在编译时期能够缺席(源程序没必要存在)。ide
3. JAVA动态加载类和静态加载类的方式this
1 ).程序在编译时执行,在执行过程当中加载全部可能执行到的程序。在这种加载方式下,只要加载中一个方法出错,程序就不能运行。咱们通常写程序默认的是静态加载;new建立对象的方式称做为静态加载。.net
2).动态加载(类惟一字节码对象); 程序在运行时调用相应方法,即便其余方法是错误的,程序依旧会执行。经过动态加载可让程序的可延长性大大提高,对之后的维护和扩展有重要意义。线程
Class c1=Class.forName("XXX");代理
Class c2= XXX.class; excel
XXX u1=new XXX(); Class c3=u1.getClass(); htm
使用当前类的ClassLoader 对象
ClassLoader clo1 =this.getClass.getClassLoader();
Class c3=clo1.loadClass("XXX");
使用当前线程的ClassLoader
ClassLoader clo2 =Thread.currentThread().getContextClassLoader();
Class c4=clo2.loadClass("XXX");
使 用系统ClassLoader,即系统的入口点所使用的ClassLoader,(注意,system ClassLoader与根 ClassLoader并不同。JVM下system ClassLoader一般为App ClassLoader)
ClassLoader clo3=ClassLoader.getSystemClassLoader();
Class c5=clo3.loadClass("XXX");
4.举两个实际例子说明:
1)例一
public interface IUser {
}
package reflect;
public class User implements IUser{
private String name;
private int id;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
}
public static void main (String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
Class c1=Class.forName("reflect.User");//每一个类对应一个字节码实体对象
Class c2=User.class; //每一个类对应一个字节码实体对象
User u1=new User();//构造器实例化一个对象
Class c3=u1.getClass();//该对象对应的字节码实体对象
Object o1=c1.newInstance();//该类反射出的实例
Object o2=c2.newInstance();//该类反射出的实例
System.out.print(o1==o2);//false
System.out.print(c3==c1);//true
System.out.print(c1==c2);//true
ClassLoader clo=Thread.currentThread().getContextClassLoader();
ClassLoader clos=ClassLoader.getSystemClassLoader();
Class c4=clo.loadClass("reflect.User");
Class c5=clo.loadClass("reflect.User");
System.out.println(c5==c1);//true
System.out.print(c4==c1);//true
//利用反射获取一个类的属性
Field[] fs = c1.getDeclaredFields();
for(Field field:fs){
System.out.println("得到属性的修饰符,例如public,static等等 >>"+Modifier.toString(field.getModifiers()));
System.out.println("属性的类型的名字 >>"+field.getType());
System.out.println("属性的名字 >>"+field.getName());
}
Method[] ms = c1.getDeclaredMethods();
for(Method field:ms){
System.out.println("得到方法的修饰符,例如public,static等等 >>"+Modifier.toString(field.getModifiers()));
System.out.println("方法的参数个数 >>"+field.getParameterTypes().length);
System.out.println("方法的名字 >>"+field.getName());
}
System.out.println("c1的父类>>"+c1.getSuperclass()); //c1的父类>>class java.lang.Object
Class[] cs=c1.getInterfaces();
for(Class field:cs){
System.out.println("接口的名字 >>"+field.getName()); //接口的名字 >>reflect.IUser
}
Method method=c1.getDeclaredMethod("setName", String.class);
method.invoke(o1, "guolzlijing");
Method method2=c1.getDeclaredMethod("getName", null);
System.out.println(method2.invoke(o1, null));//guolzlijing
}
2)解释关键字:
方法关键字
getDeclaredMethods()
获取全部的方法(不包括继承类)
getDeclaredMethod方法第一个参数指定一个须要调用的方法名称
第二个参数是须要调用方法的参数类型列表,是参数类型!如无参数能够指定null。
参数必须和方法中同样int和Integer,double和Double被视为不一样的类型。
反射中getMethods 与 getDeclaredMethods 的区别
public Method[] getMethods()返回某个类的全部公用(public)方法包括其继承类的公用方法,固然也包括它所实现接口的方法。
public Method[] getDeclaredMethods()对象表示的类或接口声明的全部方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
固然也包括它所实现接口的方法。
getReturnType()
得到方法的反回类型
getParameterTypes()
得到方法的传入参数类型
getDeclaredMethod("方法名",参数类型.class,……)
得到特定的方法
构造方法关键字
getDeclaredConstructors()
获取全部的构造方法(不包括继承类)
getDeclaredConstructor(参数类型.class,……)
获取特定的构造方法
父类和父接口
getSuperclass()
获取某类的父类
getInterfaces()
获取某类实现的接口
Invoke
一个方法能够生成多个Method对象,但只有一个root对象,主要用于持有一个MethodAccessor对象,这个对象也能够认为一个方法只有一个,至关因而static的,由于Method的invoke是交给MethodAccessor执行的。
能够看到Method.invoke()实际上并非本身实现的反射调用逻辑,而是委托给sun.reflect.MethodAccessor来处理。
每一个实际的Java方法只有一个对应的Method对象做为root。这个root是不会暴露给用户的,而是每次在经过反射获取Method对象时新建立Method对象把root包装起来再给用户。
在第一次调用一个实际Java方法对应得Method对象的invoke()方法以前,实现调用逻辑的MethodAccessor对象还没建立;
等第一次调用时才新建立MethodAccessor并更新给root,而后调用MethodAccessor.invoke()真正完成反射调用。
AVA反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了如下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具备的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
3)例子二:
public interface RunBetter {
public void startPro();
}
public class Word implements RunBetter{
public void startPro() {
// TODO Auto-generated method stub
System.out.println("Word Test!");
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//静态加载。编译时加载,编译时就须要加载所有可能使用到的的类,一个类出错,其余类的功能都不能获得执行 以下注释将编译不经过
/*if("Word".equals(args[0])){
Word Word = new Word();
System.out.println("Word");
}
if("Excel".equals(args[0])){
Excel excel = new Excel();
System.out.println("Excel");
}
}*/
Class c1 = Class.forName(GetProperties.use_classLoador());//配置文件中读取具体实现类
//在这个代码中咱们经过得到类类型newInstance。而后再执行startPro中的方法。
//为何不将RunBetter rb = (RunBetter)c1.newInstance();写成 MainLoad rb = (MainLoad)c1.newInstance(); ???
//不利于拓展,若是有多个实现类都执行startPro方法,这样每加一个类都须要改动源代码程序;接口的形式,只须要 关注接口不关注具体实现类是哪个;也是多态性
RunBetter rb = (RunBetter)c1.newInstance();
rb.startPro();
}
4)例子三:
public interface Attribute {
abstract void belongNature();
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Scanner sc=new Scanner(System.in);
System.out.println("请输入人群,获取属性……");
while(true){
String action=sc.nextLine();
if("exit".equals(action)){
return;
}
if(action.length()>0){
runClassLoader(action);
}
}
}
static void run(String action){
switch (action) {
case "Student":
Student student=new Student();
student.belongNature();
break;
case "Teacher":
Teacher teacher=new Teacher();
teacher.belongNature();
break;
default:
break;
}
}
static void runClassLoader(String action) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
switch (action) {
case "Student":
Class class1=Class.forName(GetProperties.use_classLoador("class_student"));
Attribute attribute=(Attribute)class1.newInstance();
attribute.belongNature();
break;
case "Teacher":
Class class2=Class.forName(GetProperties.use_classLoador("class_teacher"));
Teacher attribute2=(Teacher)class2.newInstance();
attribute2.belongNature();
break;
default:
break;
}
}