- <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">------</span><a target=_blank href="http://www.itheima.com" target="blank" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Java培训、Android培训、iOS培训、.Net培训</a><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">、期待与您交流! -------</span>
- <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">反射的基石:Class</span>
java程序中的各个java类属于同一类事务,描述这类事务的java类名就是Class。
Class常用方法:
isPrimitive()//是否基本类型字节码文件
isArray()//是否数组类型的Class字节码文件
//类的基本组成:Field、Method、Contructor、package
Method getMethod();
总之,只要要源程序中出现的类型,都有各自的Class实例对象,比如int[],void
9大预定义的Class对象:八个基本数据类型+void
注:包装类.TYPE ;得到的是包装类所包装的基本数据类型的class文件
数组也是一种类型,使用isArray();来判断
Java反射机制:
反射就是把Java类中的各种成分映射成相应的java类。
Java运行状态,对任意的类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个属性和方法;这种动态的获取信息和调用对象的方法的功能称为java的反射机制。
Ps
框架就是对外提供一些接口(功能扩张的标准),由实现类按照这个接口的标准去实现,框架内部如果需要操作这些实现类的对象完成某些操作,那么就需要把这些实现类的全名(包名+类名)写在某个配置文件中,框架代码只需要读取这个配置文件,就可以获取这个实现类的字节码文件,然后利用反射技术创建这个实现类的对象并调用相应的方法完成一些操作。
用于描述字节码文件的类就是Class类,创建对象,可以提出字节码文件中的内容,如字段/构造函数/一般函数。该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件进行解刨,只要获取该类的字节码文件对象就可以了。
获取字节码文件对象的3种方式(注:3种方式所得到的字节码都是同一个字节码对象):
1. 类名.class
2. 对象.getClass();
3. Class.forName(“类名”);
测试类,用于后续的被反射的类:
- package com.leaf.bean;
-
- public class Person {
- private int age;
- private String name;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.age = age;
- this.name = name;
- System.out.println(“paramConstructor run”);
- }
-
- public void personMethod() {
- System.out.print("personMethod run");
- }
-
- public void show() {
- System.out.println("name:" + name + "….age:" + age);
- }
-
- private void privateMethod() {
- System.out.println("privateMethod run");
- }
-
- public static void staticMethod() {
- System.out.println("staticMethod run");
- }
- }
示例:获取Class对象
- package com.leaf.test;
-
- import com.leaf.bean.*;
-
-
-
- public class ReflectDemo{
- public static void main(String[] args)throws ClassNotFoundException{
- getClassFile_1();
- getClassFile_2();
- getClassFile_3();
- }
-
-
-
-
-
- public static void getClassFile_1(){
- Person p = new Person("lisi",15);
- Class clazz = p.getClass();
-
- Person p1 = new Person("lisi",15);
- Class clazz1 = p1.getClass();
-
- System.out.println(clazz == clazz1);
- System.out.println("...................");
- }
-
-
-
-
-
- public static void getClassFile_2(){
- Class clazz = Person.class;
- Class clazz1 = Person.class;
-
- System.out.println(clazz == clazz1);
- System.out.println("...................");
- }
-
-
-
-
-
-
-
- public static void getClassFile_3()throws ClassNotFoundException{
-
- String className = "com.leaf.bean.Person";
- Class clazz = Class.forName(className);
-
- System.out.println(clazz);
- }
- }
result:
根据结果分析:三种方法得到的是同一份字节码文件。
示例:
获取Class中的构造函数
- package com.leaf.test;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- public class ReflectDemo1 {
- public static void main(String[] args) {
- try {
- createNewObject_1();
- createNewObject_2();
- } catch (ClassNotFoundException | InstantiationException
- | IllegalAccessException | ClassCastException
- | NoSuchMethodException | InvocationTargetException e) {
-
- e.printStackTrace();
- }
- }
-
- public static void createNewObject_1() throws ClassNotFoundException,
- InstantiationException, IllegalAccessException {
-
-
-
-
-
- String name = "com.leaf.bean.Person";
-
- Class clazz = Class.forName(name);
-
- Object obj = clazz.newInstance();
-
- }
-
- public static void createNewObject_2() throws ClassCastException,
- InstantiationException, NoSuchMethodException,
- IllegalAccessException, InvocationTargetException,
- ClassNotFoundException {
-
-
-
-
-
- String name = "com.leaf.bean.Person";
-
- Class clazz = Class.forName(name);
-
- Constructor constructor = clazz.getConstructor(String.class,int.class);
-
- Object obj = constructor.newInstance("xiaoming",38 );
- }
- }
result:
示例:
获取字节码文件中的字段
- package com.leaf.test;
-
- import java.lang.reflect.Field;
-
- public class ReflectDemo2 {
- public static void main(String[] args) throws Exception {
- getFieldDemo();
-
- }
-
- public static void getFieldDemo() throws Exception {
- Class clazz = Class.forName("com.leaf.bean.Person");
-
-
- Field fieldAge = clazz.getDeclaredField("age");
-
- fieldAge.setAccessible(true);
- Object obj = clazz.newInstance();
-
- fieldAge.set(obj, 89);
-
- Object o = fieldAge.get(obj);
- System.out.println(fieldAge);
- }
- }
result:
示例:
获取Class文件中的类的方法:
- package com.leaf.test;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Method;
-
- public class ReflectDemo3 {
-
- public static void main(String[] args) throws Exception {
- Class clz = Class.forName("com.leaf.bean.Person");
- getMethod_1(clz);
- getMethod_2(clz);
- getMethod_3(clz);
-
- }
-
-
-
- public static void getMethod_1(Class clz)throws Exception{
-
- Method[] methods = clz.getMethods();
-
- methods = clz.getDeclaredMethods();
-
- for(Method method :methods){
-
- System.out.println(method);
- }
-
- }
-
-
-
- public static void getMethod_2(Class clz)throws Exception{
- Method method = clz.getMethod("personMethod",null);
- Object obj = clz.newInstance();
- Constructor con = clz.getConstructor(String.class,int.class);
- obj = con.newInstance("小明",25);
- method.invoke(obj, null);
- }
-
-
-
- public static void getMethod_3(Class clz)throws Exception{
- Method method = clz.getMethod("paramMethod", String.class);
- Constructor con = clz.getConstructor(String.class,int.class);
- Object obj = con.newInstance("小明",25);
- method.invoke(obj, "我是参数");
-
- }
-
-
-
- }
result:
反射的应用:框架
框架与框架要解决的核心问题:
我做房子卖给用户,由用户自己安装门窗和空调,我做的房子就是框架,用户需要使用我的框架,把门窗插入进我提供的框架中,框架和工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
那什么是要解决的核心问题??
我再写框架时,你这个用户可能还在上小学,还不会写程序,我写的框架程序怎样能调用到你以后写的类呢?因为在写程序时,无法知道要被调用的类名,所以在程序中,无法直接new某个类的实例对象了,而是要通过反射的方式来实现。
综合案例:
框架程序怎样能调用到你以后写的类(门窗)呢? 因为在写才程序时无法知道要被调用的类名,所以,在程序中无法直接new 某个类的实例对象了,而要用反射方式来.
示例:
简单框架:通过反射来调用配置文件中的类,并调用其中的方法!
配置文件:config.properties
className=java.util.ArrayList
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Collection;
- import java.util.Properties;
-
- public class ReflectTest2 {
- public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
-
-
-
-
-
-
-
-
-
-
- InputStream is = new FileInputStream("config.properties");
-
-
- Properties pro = new Properties();
- pro.load(is);
- is.close();
-
- String className = pro.getProperty("className");
- Collection col = (Collection)Class.forName(className).newInstance();
-
-
- ReflectPoint rp1 = new ReflectPoint(3, 3);
- ReflectPoint rp2 = new ReflectPoint(5, 5);
- ReflectPoint rp3 = new ReflectPoint(3, 3);
- ReflectPoint rp4 = new ReflectPoint(4, 3);
-
- col.add(rp1);
- col.add(rp2);
- col.add(rp3);
- col.add(rp4);
- col.add(rp1);
-
-
- System.out.println(col.size());
- System.out.println(col);
-
- }
-
- }
- 用来进行测试的类
- package com.leaf.ReflectDemo;
-
- public class ReflectPoint {
- int x;
- int y;
- public ReflectPoint(int x,int y){
- this.x = x;
- this.y = y;
- }
- @Override
- public int hashCode() {
- return x*39+y+41;
- }
- @Override
- public boolean equals(Object obj) {
- if(this == obj){
- return true;
- }
- if(!(obj instanceof ReflectPoint))
- try {
- throw new Exception("类型异常");
- } catch (Exception e) {
- e.printStackTrace();
- }
- ReflectPoint rp = (ReflectPoint)obj;
- int temp = rp.x - this.x;
- return temp==0?(this.y - rp.y)==0:temp==0;
- }
- @Override
- public String toString() {
- return "RP:"+x+":"+y;
- }
- }
result:
反射生效,我们能修改配置文件中的类,来调用其他集合中的类为我们使用,反射是不是很神奇?