day726

反射

1. 反射的前提条件:
   必须先有类,类的内容才能被反射处理。
   -类的属性和方法必须使用 static进行修饰,才能被反射访问。

2. 类的内容也是一个对象:
    在 Java 中,每个类都有一块内存空间,这块内存空间就是一个对象。
   这个对象记录了该类中声明的属性、方法和构造方法等信息。

3. Java 中的 Class 类:
   Java 将上述类的抽象概念,统一封装到了 Class类中。
   通过 `Class` 类,我们可以获取类的各种信息,并进行动态调用。

    Class类的对象是不能new

4. 反射的作用:
   反射技术可以让程序在运行时动态获取类的信息,并动态调用类的属性和方法。
   这种动态性使得程序更加灵活和可扩展。

5. 反射的使用场景:
   动态加载类并创建对象
   动态调用类的方法
   获取类的属性和方法
   动态代理

获取类的类对象

public static void main(String[] args) throws ClassNotFoundException {
        //通过类名获取类对象
        Class clazz = EasyClassA.class;
        //通过对象获取类对象
        clazz =new EasyClassA().getClass();
        //通过class方法的forName方法获取
        clazz=Class.forName("day725.EasyColor");
        System.out.println(clazz);

        //类的类对象中存储了类中定义的内容  属性|方法|构造方法
    }

获取类对象的三种方式:
Easy.class
new Easy().getClass()
Class.forName("day726.Easy")
获取公有属性:
c.getField("name") 获取公有属性 name
fName.get(easy) 获取 easy 对象的 name 属性值
fName.set(easy, "李智") 设置 easy 对象的 name 属性值
获取私有属性:
c.getDeclaredField("code") 获取私有属性 code
fCode.set(easy, "10001") 设置 easy 对象的 code 属性值
fCode.get(easy) 获取 easy 对象的 code 属性值
访问私有属性的权限控制:
fsex.set(easy, "女") 设置 easy 对象的 sex 属性值
fAddress.setAccessible(true) 先设置访问权限,才能获取和设置 address 属性值
获取所有公有属性:
c.getFields() 获取类中所有公有属性



import java.lang.reflect.Field;

public class EasyClassB {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //类的类对象中存储了类中定义的内容
        //获取类中的属性
        Class c=Easy.class;
        c=new Easy().getClass();
        c=Class.forName("day726.Easy");
        //获取类对象
        //Java中用来记录 类的属性的类叫做Field
        //fName变量指向的对象就是Easy类中的name属性
        Field fName=c.getField("name");
        //可以获取某一个Easy对象的name属性值
        Easy easy=new Easy();
        easy.name="张赞";
        System.out.println(easy.name);
        //可以获取某一个Easy类的对象的name属性的值
        Object objectName=fName.get(easy);
        System.out.println(objectName+"----");
        //注入该属性的值
        fName.set(easy,"李智");
        System.out.println(easy.name);
     //getFiled  getFields 只能获取类中public声明出来的属性
        Field fCode=c.getDeclaredField("code");
        //设置code属性的值
        fCode.set(easy,"10001");
        Object objectCode=fCode.get(easy);
        System.out.println(objectCode);

        Field fsex=c.getDeclaredField("sex");
        Field fAddress=c.getDeclaredField("address");
        fsex.set(easy,"女");

        //反射访问私有属性 必须先获取访问权限
        fAddress.setAccessible(true);
        fAddress.set(easy,"青岛");
        System.out.println(fAddress.get(easy));

        //getFields()
        //
    }

}

反射定义及API
反射:在程序运行期间,可以动态获取类中定义的属性和方法以及构造方法的机制(思想)的实现
反射的核心是Class类  程序中使用的类,每一个都有一个唯一对应的Class对象
反射的API:Field Method Constructor
反射会破坏类的封装性 

public class EasyClassC {
    
    public static <T> T getInstance(Class<T> clazz, Map values) throws InstantiationException, IllegalAccessException {
        //通过反射获取实例  创建对象
        clazz.newInstance();//通过类中的无参构造方法创建对象
        T t = clazz.newInstance();
        //通过反射获取类中定义的属性
        Field[]  farr= clazz.getDeclaredFields();
       // System.out.println(Arrays.toString(farr));
        for (Field f : farr) {
            //获取属性的名字
            String fname = f.getName();
            //获取该属性在Map中的键值对    属性对相应的值
            Object value = values.get(fname);
            //设置属性访问权限
            f.setAccessible(true);
            f.set(t, value);
        }
        return t;
    }
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        Map map = new HashMap();
        map.put("code","c293");
        map.put("name","二发");
        map.put("sex","女");
       Student stu= getInstance(Student.class,map);
       System.out.println(stu);
    }
}
class Student{
    private String name;
    private String sex;
    private String code;



    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", code='" + code + '\'' +
                '}';
    }
}

取和调用类的方法的方法。

获取类对象:
Class<Easy> c = Easy.class;
创建类的实例:
Easy easy = c.newInstance();
获取公有方法:
Method ma = c.getMethod("methodA");
ma.invoke(easy); 通过 invoke() 方法调用 methodA() 方法
获取带参数的公有方法:
Method mb = c.getMethod("methodB", int.class, int.class);
mb.invoke(easy, 23, 65); 通过 invoke() 方法调用 methodB() 方法, 并传入参数

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.Arrays;

public class EasyClassE {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IntrospectionException {
        //反射获取构造方法
        Class<Easy> c=Easy.class;
        c.newInstance();//调用无参构造方法
        //获取无参构造方法
       Constructor<Easy> con= c.getConstructor();
       con.newInstance();
       con=c.getConstructor(String.class);
       con.newInstance("饿哦");

       //修饰符   使用Modifier的方法判断方法属性和构造方法的修饰符
        Field f=c.getDeclaredField("test");
        int fmod=f.getModifiers();
        System.out.println(fmod);
       boolean bool= Modifier.isStatic(fmod);
       System.out.println(bool);
       //内省  也是通过反射来实现的  内省不会破坏封装性
        //内省 :底层是通过反射实现,内省获取属性的读方法和写方法(getter/setter)来获取和设置属性的内容,不会破坏类的封装性

        //获取BeanInfo
        BeanInfo bi=Introspector.getBeanInfo(c);
        //获取写的方法和读的方法   setter/getter
        PropertyDescriptor[] pds=  bi.getPropertyDescriptors();
        System.out.println(Arrays.toString(pds));
       String pName= pds[0].getName();//获取该属性的名字
        System.out.println("name"+pName);
        Method read=pds[0].getReadMethod();   //获取该属性的getter方法
        Method write= pds[0].getWriteMethod();//获取该属性的setter方法
        //obj.setName("张三");//面向对象
        //write.invoke(obj,"张三");//反射
        Easy easy=c.newInstance();
        write.invoke(easy,"张三");
    }
}

1. 反射获取类的构造方法
   - `Constructor<Easy> con = c.getConstructor();`
   - `con.newInstance();` 使用构造方法创建实例

2. 获取修饰符信息
   - `Field f = c.getDeclaredField("test");`
   - `int fmod = f.getModifiers();`
   - `boolean bool = Modifier.isStatic(fmod);`

3. 使用内省技术
   - `BeanInfo bi = Introspector.getBeanInfo(c);`
   - `PropertyDescriptor[] pds = bi.getPropertyDescriptors();`
   - 获取属性的读写方法(`getReadMethod()`和`getWriteMethod()`)

4. 通过内省的方式访问和设置属性值
   - `Method read = pds[0].getReadMethod();`
   - `Method write = pds[0].getWriteMethod();`
   - `write.invoke(easy, "张三");` 使用反射调用 setter 方法设置属性值

总结:

1. 反射可以用于获取类的构造方法、属性和方法的信息。
2. 内省基于反射实现,可以更方便地访问和设置类的属性,不会破坏类的封装性。
3. 反射和内省在框架开发、动态代码生成等场景下非常有用,可以提高代码的灵活性和可扩展性。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值