JAVA 反射

类反射是指在程序运行期间,对于任意一个类都能够知道这个类的所有属性与方法,并且对于任意一个对象,都能够任意调用他的一个方法,这种动态获取信息与动态调用对象方法的功能是JAVA语言的反射机制

反射机制是目前众多JAVA框架实现的基础
1. 使用JDBC连接数据库(解析XML中的类名,驱动器,bean等)
2. Servlet在Web容器中的加载和运行

类的执行过程:

1. 编译(.java文件生成.class二进制字节码文件)

2. 加载(.class二进制字节码文件加载到内存中)

3. 连接(包含三步:验证.class文件格式是否规范,语义是否正确;准备类变量分配内存并赋予初始值即系统原值;解析是将符号引用转换直接引用,举例String s=aaa,s则为符号引用,aaa为直接引用,解析就是把指向s的地址指向aaa)

4. 初始化(将用户的赋值再覆盖系统默认的值)

类加载步骤:

1. 将.class文件读到内存中的方法区

2. 为.class生成唯一对应的Class对象,并将该对象放到堆里(此处相当于入口,可对应检查方法区的对应类型数据)

Class是一个类,可反向读取类中的信息,生成实例等功能

举例 Good商品类使用反射:

Goods goods=(Goods)Class.forName(className).newInstance();

Class.forName(className) : 获取Class对象,将完整的类名(比如在包中,就是包.类)通过参数className传递

newInstance(): 新实例

Java反射API常用的类

java.lang包:无需导入
java.lang.Class: 反射的核心类,可获取类的方法,属性等信息,生成类的实例

java.lang.reflect包:无需导入
Method类:表示类的方法,可用来获取类中的方法信息或执行方法
Constructor类:表示类的构造方法
Field类:表示类的成员变量,可用来获取和设置类的属性值
 

通过Class类的对象,我们可以

a. 获取类的属性,方法

b. 生成类的实例

c. 调用实例的方法,属性

反射,通过操作Class类的对象

a. 实现对类的操作

b. 实现对对象的操作

生成类的实例三种方法代码:

package exercise;

/**
 * Created by LL on 2021/11/30 14:48
 */
//获取person类对应的class对象
public class Person {
    public static void main(String[] args){
        //方式1: 通过Class.forName()获取,更常用,对于编译器
        //并不知道对象类型,在运行期对未知类型进行操作时更常用
        try {
            Class c = Class.forName("exercise.Person");
            System.out.println(c.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //方法2:通过对象实例的getClass()获取
        Person p = new Person();
        Class c2 = p.getClass();
        System.out.println(c2.getName());


    //方式3: 通过类的class属性获取
        Class c3 = Person.class;
        System.out.println(c3.getName());
   }
}

获取属性(Field——getName()):

getFields() 所有可访问的公共字段

getDeclareFields() 所有字段

getField(String name) 返回一个特定的公共字段对象

获取方法(Method——getName()):

getMethods() 所有公共方法,包括从超类和超接口继承的声明

getDeclareMethods() 所有方法,包括公共,包含,默认(包)访问和私有方法,但不包括继承的方法

getMethod(String name, Class[] parameterTypes) 返回一个方法对象

Person类具体信息如下

package exercise;

/**
 * Created by LL on 2021/11/30 14:48
 */
//获取person类对应的class对象
public class Person {
    private int age;
    private String name;
    public String address;

    public Person(){};

    public Person(int age, String name, String address) {
        this.age = age;
        this.name = name;
        this.address = address;
    }

    private void privateMethor1(){
    }
    public void showInfo(){
        System.out.println(this.getName()+"-"+
                this.getAge()+"-"+this.getAddress());
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

通过反射获取属性与方法

package exercise;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by LL on 2021/11/30 15:24
 */
public class testPerson {
    public static void main(String[] args) {
        //第一步:获取Class对象
        Class c=null;
        try {
            c=Class.forName("exercise.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //第二步:调用Class的相应方法
        //获取Person类的相关属性
        Field[] field1=c.getFields();//获取所有可访问的公共字段
        Field[] field2=c.getDeclaredFields();//获取所有字段

        try {
            Field a=c.getField("address"); //返回一个特定的公共Field对象
            System.out.println("获取到特定的公共字段为"+a.getName());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        // 获取Person类的相关方法
        Method[] method1=c.getMethods();//所有公共方法,包括继承来的方法
        Method[] method2=c.getDeclaredMethods();//所有公共方,私有,默认等方法,不包括继承方法


        //第三步:调用相应反射API,完成需求
        System.out.println("*****所有可访问的公共字段*********");
        for(Field f:field1){
            System.out.println(f.getName());
        }
        System.out.println("**********获取所有字段*********");
        for(Field f:field2){
            System.out.println(f.getName());
        }
        System.out.println("*********所有公共方法,包括继承来的方法****************");
        for(Method m:method1){
            System.out.println(m.getName());
        }
        System.out.println("*********所有公共方,私有,默认等方法,不包括继承方法****************");
        for(Method h:method2){
            System.out.println(h.getName());
        }
    }
}
输出结果如下
获取到特定的公共字段为address
*****所有可访问的公共字段*********
address
**********获取所有字段*********
age
name
address
*********所有公共方法,包括继承来的方法****************
getAddress
getName
setName
showInfo
getAge
setAge
setAddress
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
*********所有公共方,私有,默认等方法,不包括继承方法****************
getAddress
getName
setName
showInfo
getAge
privateMethor1
setAge
setAddress

反射获取构造方法

获取构造方法:getConstructor(Class[] parameterTypes) 返回一个构造方法对象

如参数区域Class[] parameterTypes空白,则属于无参构造

Class[] parameterTypes拥有内容,会传回对应的构造方法

通过Constructor —newInstance(object[] initargs) 可生成类的实例

通过Method—invoke(Object obj, Object[] args) 可在具有指定参数的方法对象上,调用此方法对象表示的基础方法

package exercise;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by LL on 2021/11/30 15:24
 */
public class testPerson {
    public static void main(String[] args) {
        //获取Class对象
        Class c=null;
        try {
            c=Class.forName("kb16.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //获取构造方法对象
        System.out.println("*******利用构造方法实例化对象,并调用对象的方法*******");
        try {
            //获取Person的无参构造方法
            Constructor constructor=c.getConstructor();
            //根据构造方法对象完成类的对象实例化
            try {
                Object obj=constructor.newInstance();
                //通过实例,调用相应方法
                //a.获取相应方法Method对象,第一个参数:方法名称,第二个参数:方法中的参数类型
                //无参-null,带参分别有int,String参数,输入new Class[]{int.class,String.class}
                Method method=c.getMethod("showInfo",null);
                //b.调用相应方法
                method.invoke(obj,null);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        System.out.println("*******获取带参构造*******");
        try {
            Constructor constructor2=c.getConstructor(new Class[]{int.class,String.class,String.class});
            try {
                Object obj2=constructor2.newInstance(new Object[]{
                        18,"张三","北京"
                });
                Method method=c.getMethod("showInfo",null);
                method.invoke(obj2,null);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

节日促销方案:

package exercise;

/**
 * Created by LL on 2021/11/30 16:54
 */
public class ChildrenDayPS {
    public ChildrenDayPS(){}
    public double promoteSales(String productID){
        System.out.println("编号"+productID+"的商品打六折");
        return 0.6;
    }
}





package exercise;

/**
 * Created by LL on 2021/11/30 16:56
 */
public class NationalDayPS {
    public NationalDayPS(){}
    public double promoteSales(String productID){
        System.out.println("编号"+productID+"的商品打七折");
        return 0.7;
    }
}





package exercise;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by LL on 2021/11/30 17:02
 */
public class ProductSales {
    //className 不同促销类方案的类名(完整限定名)
  public void productsaleByRef(String productID, String className){
      try {
          //获得相应类的Class对象
          Class c=Class.forName(className);
          //根据Class去获取构造方法对象
          try {
              Constructor b=c.getConstructor();
              //根据构造方法去完成对象实例化
              try {
                  Object obj=b.newInstance();
                  //调用相应对象的商品打折方法
                  Method method=c.getMethod("promoteSales",String.class);
                  Double discount=(Double)method.invoke(obj,productID);
                  System.out.println("节日折扣"+discount);

              } catch (InstantiationException e) {
                  e.printStackTrace();
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              } catch (InvocationTargetException e) {
                  e.printStackTrace();
              }
          } catch (NoSuchMethodException e) {
              e.printStackTrace();
          }

      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      }
  }

    public static void main(String[] args) {
        ProductSales ps=new ProductSales();
        ps.productsaleByRef("p001","kb16.ChildrenDayPS");
        ps.productsaleByRef("p001","kb16.NationalDayPS");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值