反射机制:
Java反射机制:是在运行状态中,对于任意一个类,都能够知道该类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Java反射(放射)机制:”程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言 "。从这个观点看,Java并不是动态语言,但是Java有一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整结构(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。因此,Java反射是Java被视为动态语言的一个关键性质。
反射机制的必要性:
1、在涉及某些应用程序时,往往需要动态升级以增加修改工程,而在静态编译体系中一切升级操作都需要对源码进行修改,这就意味着每一次升级就要对整个源代码编译一次。而如果是些大程序编译一次要几小时甚至几天才能完成,如此,显然纯静态的编程方式不太适合。而java是一门静态语言,为了弥补这个缺点,就有了反射机制。
2、Java更多的情况是应用于服务端程序,而服务器上的程序是不能关掉的,即使关掉也要提前给用户通知,但是,如果此时又要对系统进行升级,既要保证体系内其他功能正常运行,还要保证系统升级措施,就可以用发射机制来实现。
3、程序更加清晰,将主程序和功能程序分离,便于后期维护管理。
反射机制的应用:
1、杀毒软件病毒库的在线升级。
2、JDBC数据桥的构建(Class.forName(“数据库驱动包类名称”))。
3、应用程序功能的增加。
4、分析泛型的实质。
5、分析程序,找bug。
反射机制三种实现方式:
1、得到类类型,同时加载类Class class = Class.forName("SomethingName")。
2、已知类对象,由对象得到其所属类Class class = new Demo().getClass().
3、直接由类得到其类对象Class class = Demo.Class。
反射相关类:
1、Class类,用来处理类级别的反射。
2、Field类,用来处理成员变量级的反射。
3、Method类,用来处理方法级的反射。
4、Constructor类,用来处理构造器的反射。
Java反射机制提供了什么功能:
1、获取类的Class对象
2、获取类的Fields
3、获取类的Method
4、获取类的Constructor
5、新建类的实例
注:在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。
获取类的Class对象:
1)、调用getClass
Boolean var1 = true;
Class> classType1 = var1.getClass();
System.out.println(classType1);
//输出:class java.lang.Boolean
2)、运用.class语法
Class> classType2 = Boolean.class;
System.out.println(classType2);
//输出:class java.lang.Boolean
3)、运用static method Class.forName()
Class> classType3 = Class.forName("java.lang.Boolean");
System.out.println(classType3);
//输出:class java.lang.Boolean
4)、运用private wrapper classes的TYPE语法(这里返回的是原生类型,和Boolean.class返回的不同)
Class> classType4 = Boolean.TYPE;
System.out.println(classType4);
//输出:boolean
获取类的Fields:
可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。Java的Class
1)、public Field getField(String name)
People peo = new People();
peo.getClass().getField("");
返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段。
2)、public Field[ ] getFields()
Field[ ] fields = peo.getClass().getFields();
返回一个包含某些Field对象的数组,这些对象反映此Class对象所表示的类或接口的所有可访问公共字段。
3)、public Field getDeclaredField(String name)
peo.getClass().getDeclaredField("");
返回一个Field对象,该对象反映此Class对象所表示的类或接口的指定已声明字段。
4)、public Field[ ] getDeclaredFields()
Field[ ] fields = peo.getClass().getDeclaredFields();
返回Field对象的一个数组,这些对象反映此Class对象所表示的类或接口所声明的所有字段。
getFields和getDclaredFields的区别:getFields返回的是申明为public的属性,包括父类中的,getDclaredFields返回的是指定类定义的所有定义的属性,不包括父类的。
获取类的Method:
通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法。Class
1)、public Method getMethod(String name,Class>... parameterTypes)
返回一个Method对象,它反映此Class对象所表示的类或接口的指定公共成员方法
2)、public Method[ ] getMethods()
返回一个包含某些Method对象的数组,这些对象反映此Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类或超接口继承的那些的类或接口)的公共方法
3)、public Method getDeclaredMethod(String name,Class>... parameterTypes)
返回一个Method对象,该对象反映此Class对象所表示的类或接口的指定已声明方法。
4)、public Method[ ] getDeclaredMethods()
返回Method对象的一个数组,这些对象反映此Class对象表示的类或接口声明的所有方法,包括公共、保护、默认、私有方法,但不包括继承的方法。
获取类的Constructor:
通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例。Class
1)、public Constructor
返回一个Constructor对象,它反映此Class对象所表示的类的指定公共构造方法。
2)、public Constructor>[ ] getConstructors()
返回一个包含某些Constructor对象的数组,这些对象反映此Class对象所表示的类的公共构造方法。
3)、public Constructor> getDeclaredConstructor(Class>... parameterTypes)
返回一个Constructor对象,该对象反映此Class对象所表示的类或接口的指定构造方法。
4)、public Constructor>[ ] getDeclaredConstructors()
返回Constructor对象的一个数组,这些对象反映此Class对象表示的类声明的所有构造方法。包括公共、保护、私有、默认(包)访问构造方法
新建类的实例:
通过反射机制创建新类的实例,以下3种方法
1)、调用无参数
a、调用类的Class对象的newInstance方法,该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败。
Class> cls = (Class>) Class.forName("test.People").newInstance();
或者
People cls = People.class.newInstance();
System.out.println(cls);
newInstance实例化之前须用class的forName()方法加载、连接类对象,由于People类对象有一个有参构造器,没有默认构造器,抛出InstantiationException异常。
b、调用默认(不带参数)Constructor对象的newInstance方法。
Constructor
People peo = con.newInstance();
System.out.println(peo);
通过Constructor的newInstance方法创建对象,同理,无参数的调用,对象要有符合条件的无参构造器,否则会调用失败。
2)、调用带参数
a、调用带参数Constructor对象的newInstance方法。
Constructor对象的newInstance方法和Class类的newInstance方法很像,java.lang.reflect.Constructor类也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数和私有的构造函数。
Constructor
People peo = con.newInstance("xiaohua",2);
System.out.println(peo.age);
通过Constructor的newInstance方法创建对象,调用有参数的构造方法并赋值,输出2。
补充:默认构造器:
在Java中,如果用户没有一个类创建构造器,Java编译器就会自动识别,在JVM中为这个类创建一个默认构造器,这个构造器没有参数。当用户为类创建一个构造器时,不管这个构造器是否有参数,JVM就不再为该类创建一个无参的构造器了,为了防止这个类被其他类继承,所以我们要强调,在为类创建构造器时就要创建一个无参的构造器,以防止子类初始化时,调用父类的默认构造器。所以我们创建的这个无参构造器,也是默认构造器。
补充:newInstance 与 new 的区别:
1)、new的时候,这个要new的类可以没有加载;newInstance必须保证该类已经加载、已经连接,完成该任务的正是class的静态方法forName()方法,这个静态方法调用了启动类加载器(就是加载javaAPI的那个加载器)
2)、new是强类型,相对高效,能调用任何public构造;newInstance是弱类型,低效率,只能调用无参构造。
3)、new只能实现具体类的实例化,不适合于接口编程;newInstance是实现IOC、反射、面对接口编程和依赖倒置等技术方法的必然选择。
4)、newInstance就是通过该类的默认构造函数构建了一个对象,如果没有默认构造函数就抛出InstantiationException,如果没有访问默认构造函数的权限就抛出IIIegalAccessException。
调用类的函数:
通过反射获取类Method对象,调用Field的Invoke方法调用函数。
设置 / 获取类的属性值:
通过反射获取类的Field对象,调用Field方法设置或获取值。
动态Proxy创建代理类:
待整理。