Bootstrap

0基础学JAVA(第十一天)

1.反射

创建对象的四种方式:new ,clone,反序列化,反射

1.反射定义

反射就是在程序运行期间,可以动态获取类中定义的属性和方法,以及构造方法的机制(思想)的实现

反射的核心是Class类,程序中使用的类,每一个都有一个唯一对应的Class对象

反射的api就是Field Method Constructor

反射会破坏类的封装(要通过场景说明)

2.原理

有对象之前必须先有类 static来修饰类或方法

在java中存储了类的内容,这个内容也应该是对象

java中每一个类都有一个内存,这每一块内存都是一个对象

这些对象记录了这些类当中声明了哪些属性和方法以及构造方法

java将这些类抽象为Class类

注意!!!

Class类的对象是不能new的

3.获取类的对象有三种方式:

1.类.class

2.对象.getclass

3.Class.forName

    public static void main(String[] args) {
        //Class类的对象是不能new的
        //获取类的类对象
        //1.通过类名获取类对象
        Class clazz= EasyClassA.class;
        System.out.println(clazz);
        //2.通过对象获得类对象
        clazz=new EasyClassA().getClass();
        System.out.println(clazz);
        //3.通过class方法的forName方法获取
        try {
            clazz=Class.forName("com.situ.chapter725.EasyCorlor");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        System.out.println(clazz);

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

4.使用反射实例

实例1

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //类的类对象中存储了类的属性,方法,构造方法

        //获取内容:获取类中的属性
        Class c=Easy.class;//获取类对象
        c=new Easy().getClass();//获取类对象
        try {
            c=Class.forName("com.situ.chapter726.Easy");//获取类对象
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

      ///上面三种方式都可以获取类的类对象

        //java中用来记录  类的属性  的类叫Filed

        c.getField("name");

        Field flname=c.getField("name");
        //可以获取某一个Easy的对象的name属性的值
        Easy easy=new Easy();
        easy.name="zhangsan";
        System.out.println(easy.name);
        //Flname指向的对象就是Easy类中的name属性
       Object objName= flname.get(easy);
        System.out.println(objName);
        //注入该属性的值
        flname.set(easy,"lisi");
        System.out.println(easy.name);


        //Field fCode=c.getField("code");//getFiled   getFiles只能获取类中public声明的属性所以需要使用getDeclaredFiled()方法
        Field fCode=c.getDeclaredField("code");
        fCode.set(easy,"1000");
        fCode.get(easy);//通过反射获取Easy对象的属性的值
        Object objCode=fCode.get(easy);
        System.out.println(objCode);

        Field fSex=c.getDeclaredField("sex");
        Field fAddress=c.getDeclaredField("address");
        fSex.set(easy,"nan");
        //fAddress.set(easy,"我的");              //会报错IllegalAccessException
                                              //反射可以获取私有属性,必须先获取访问权限
        fAddress.setAccessible(true);//
        fAddress.set(easy,"我的");                  //现在就可以使用了
        System.out.println(fSex.get(easy));
        System.out.println(fAddress.get(easy));
        System.out.println(easy);



    }

实例2

实现将HAshMap中的数据通过反射获取出来(不知道此时都有什么属性)

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

class Student {

    private String code;
    private String name;
    private String sex;

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


}

5.反射获取方法

public class EasyClassD {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //获取类对象
        Class<Easy> c=Easy.class;//确定c是Easy的类对象
        //反射获取方法   Method
        Method methodA=c.getMethod("methodA");//只能获取public方法,想用其他权限的和属性用法一样
        Easy easy=c.newInstance();
        //调用方法   原来:对象.方法名()   反射:方法名.invoke(对象)
        methodA.invoke(easy);
        Method method=c.getMethod("menthodB", int.class, int.class);
        method.invoke(easy,23,45);
    }
}

6.反射获取构造方法

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();
         c.getConstructor(String.class);
         //con.newInstance("张三");


        //修饰符    用Modifiers()方法判断方法属性或构造方法的修饰符是什么
        Field field=c.getDeclaredField("test");
        int fot=field.getModifiers();
        boolean b=Modifier.isStatic(fot);
        System.out.println(b);


        //内省   通过反射实现但是不会破坏封装性
        //获取bininfo
        BeanInfo br=Introspector.getBeanInfo(c);
        //获取BeanInfo中写的方法和读的方法
        PropertyDescriptor[] de=br.getPropertyDescriptors();
        System.out.println(Arrays.toString(de));
        String name=de[0].getName();//获取属性的名字
        System.out.println("属性名为"+name);
        Method read=de[0].getReadMethod();//获得该属性对应属性的get方法
        Method write=de[0].getWriteMethod();//获得该属性对应属性的set方法

        //以前:obj.setName(“张三”);(面向对象)
        //反射:write.invoke(obj,"张三")
        Easy easy=c.newInstance();
        write.invoke(easy,"张三");
    }

}

JAVAse基本结束

;