7-26学习笔记

今日重点:   反射   什么是反射   Class类对象获取方式    Field(get/set)   Method(invoke)  Constructor(newInstance)     内省   BeanInfo   readMethod  writeMethod


一、反射

        在Java中,反射是指程序在运行时动态地检测、获取和操作类、对象、方法和属性的能力。通过反射,我们可以在运行时获取任意一个类的信息,包括类的名称、方法、字段等,并且可以在运行时创建对象、调用方法和访问属性。

反射:在程序运行期间,可以动态获取类中定义的属性和方法以及构造方法的机制(思想)的实现
    反射的核心是Class类  程序中使用的类,每一个都有一个唯一对应的Class对象
    反射的API:Field  Method  Constructor
        API所在包名:java.lang.reflect
    反射会破坏类的封装性  通过场景说明(没有绝对的好坏,要看具体情况)
        有对象前必须先有类, static来修饰类的属性和方法
        在Java中存储了类的内容,这个内容也应该是一个对象
        java中每一个类都有一个内存,这每一个内存都是一个对象
        这些对象记录了这些类中声明那些属性和方法以及构造方法
        java将这些类抽象为一个类型叫Class类

1、Class类

                Class类的对象是不能new的
        该类的对象中存储了类中定义的内容 属性/方法/构造方法
获取类的类对象 有3种方式
通过类名获取类对象
Class clazz= EasyClassA.class;
通过对象获取类对象
clazz=new EasyClassA().getClass();
通过Class方法的forName方法获取
clazz=Class.forName("com.easy7_25.EasyColor");

2、获取类中的属性

        Java中用来记录类的属性的类 叫做Field
        fName变量指向的对象就是Easy类中的name属性

Field fName=c.getField("name");

        获取某一个Easy类对象的name属性的值 

Object objectName=fName.get(easy);

         注入该属性的值

fName.set(easy,"李四");

 getField getFields 只能获取类中的public声明的属性

         非public属性可以用getDeclaredField()来获取  getDeclaredField即获取定义的属性

        Field fCode=c.getDeclaredField("code");
        fCode.set(easy,"10001");
        Object objCode=fCode.get(easy);//通过反射获取easy对象的code属性的值
        Field fSex=c.getDeclaredField("sex");
        fSex.set(easy,"女");

        获取父类的属性  调用类对象的getSuperclass方法通过子类的类对象创建父类的类对象 获取属性大致与子类相同

Class<?> super = c.getSuperclass();
反射访问私有属性  必须先获取访问权限  访问当前权限外的属性都需先获取权限  
权限通过setAccessible方法设置  置true即可
        Field fAddress=c.getDeclaredField("address");
        fAddress.setAccessible(true);
        fAddress.set(easy,"青岛");

完整代码: 

public class EasyClassB {
    public static void main(String[] args) throws ClassNotFoundException, 
NoSuchFieldException, IllegalAccessException {
        //类的类对象中存储了类中定义的内容  属性  方法  构造方法
        //获取类对象
        Class c=Easy.class;
        c=new Easy().getClass();
        c=Class.forName("com.easy7_26.Easy");

        //获取类的属性
        //Java中用来记录类的属性的类 叫做Field
        //fName变量指向的对象就是Easy类中的name属性
        Field fName=c.getField("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);
        System.out.println("------------------");
        //getField getFields  只能获取类中的public声明的属性
        Field fCode=c.getDeclaredField("code");
        fCode.set(easy,"10001");
        Object objCode=fCode.get(easy);//通过反射获取easy对象的code属性的值
        System.out.println(objCode);

        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));
    }
}

class Easy {
    public String name;
    protected String code;
    String sex;
    private String address;
    static int maxage;
    public static final transient String test=null;
    public Easy(){}
    public Easy(String name){
        this.name=name;
    }
}

3、用反射设置对象的属性例子

        通过反射获取实例  创建相应类的对象

 T t=tClass.newInstance();//通过类对象中的无参构造方法创建对象
public class EasyClassC {
    public static  <T> T getInstance(Class<T> tClass, Map values) throws 
InstantiationException, IllegalAccessException {
        //通过反射获取实例  创建相应类的对象
        T t=tClass.newInstance();//通过对象类中的无参构造方法创建对象
        //通过反射获取类中定义的属性
        Field[] farr=tClass.getDeclaredFields();
        //System.out.println(Arrays.toString(farr));
        for (Field fitem:farr){
            //获取属性的名字
            String fname=fitem.getName();
            //获取该属性在Map中的键值对  属性对应的值
            Object value=values.get(fname);
            //设置属性访问权限
            fitem.setAccessible(true);
            //注入
            fitem.set(t,value);
        }
        return t;
    }

    public static void main(String[] args) throws 
InstantiationException, IllegalAccessException {
        Map map=new HashMap<>();
        map.put("code","C1001");
        map.put("name","张三");
        map.put("sex","女");
        Student stu=getInstance(Student.class,map);
        System.out.println(stu);
    }
}
class Student{
    private String code;
    private String name;
    private String sex;

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

4、 获取类中的方法

获取public方法getMethod()      getDeclaredMethod获取无权限方法

Method ma=c.getMethod("methodA");
Method mb=c.getMethod("methodB",int.class,int.class);

调用方法  对象.方法名()  面向对象    method.invoke(对象)  反射 
invoke的返回值都是Object

ma.invoke(easy);
mb.invoke(easy,23,45);

完整代码: 

public class EasyClassD {

    public static void main(String[] args) throws NoSuchMethodException, 
InstantiationException, IllegalAccessException, InvocationTargetException {
        //获取类对象
        Class<Easy> c= Easy.class;
        //反射获取方法  Method
        Easy easy=(Easy) c.newInstance();
        //获取public方法      getDeclaredMethod获取无权限方法
        Method ma=c.getMethod("methodA");

        //调用方法  对象.方法名()
        //method.invoke(对象)  反射
        ma.invoke(easy);

        Method mb=c.getMethod("methodB",int.class,int.class);
        //easy.methodB(12,34)
        mb.invoke(easy,23,45);
    }
}
public class Easy {
    public String name;
    protected String code;
    String sex;
    private String address;
    static int maxage;
    public static final transient String test=null;
    public Easy(){}
    public Easy(String name){
        this.name=name;
    }

    public void methodA(){
        System.out.println("methodA");
    }
    public void methodB(int a,int b){
        System.out.println("methodB");
        System.out.println("两个参数分别为:"+a+","+b);
    }
}

5、获取构造方法

(1)无参构造

   类对象.newInstance()        先Constructor<Easy> con=c.getConstructor(); 再con.newInstance();

以上两种均可

(2)有参构造
        Constructor<Easy> con=c.getConstructor(String.class);
        Easy a=con.newInstance("张三");

只有这一种, 传入的参数是可变参数

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);

        Easy a=con.newInstance("张三");
        //System.out.println(a.name);
    }
}

6、 修饰符

  使用Modifier的方法判断方法、属性、构造方法的修饰符
        Field f=c.getDeclaredField("test");
        int fmod=f.getModifiers();
        System.out.println(fmod);
        boolean bool=Modifier.isStatic(fmod);
        System.out.println(bool);

 二、内省

也是通过反射来实现的  内省不会破坏封装性

1、 获取BeanInfo

BeanInfo bi=Introspector.getBeanInfo(c);

其中c是类对象

2、 获取属性的写方法和读方法 setter/getter

        PropertyDescriptor[] pds=bi.getPropertyDescriptors();
        String pName=pds[0].getName();//获取属性名字
        System.out.println("属性名是:"+pName);
        Method read=pds[0].getReadMethod();//对应属性的getter方法
        Method write=pds[0].getWriteMethod();//对应属性的setter方法

 3、创建对象并调用获取的方法

        Easy easy=c.newInstance();
        write.invoke(easy,"张三");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值