反射(反射的概念、反射的使用、Class类的其他方法)

一、反射的概念

通过某种机制,动态得到这个类所有信息(属性,方法,构造方法...), 也可以动态的调用这个类所有的属性,方法,构造方法... 这种机制就是所谓的反射

反射的核心: 类的镜子, 类的字节码文件 对应的类: Class类

每一个类, 它的Class类的对象, 唯一一个, 类的Class对象, 在这个类的字节码文件加载到内存时候,JVM就会为该类的字节码文件创建一个Class对象

二、反射的使用

1.得到某个类的Class对象

(1)类名.class 得到该类的Class对象

//第一种方式: 类名.class
        Class clazz = Student.class;

(2)类的对象.getClass()

//第二种方式: 类的对象.getClass()
        Student stu = new Student();
        //Student本类, 子类 上界
         Class clazz2 = stu.getClass();

(3)通过Class类的static方法: forName(类的全限定名); 类的全限定名: 包名.类名

//第三种: 通过Class类的static方法: forName(类的全限定名)
        Class clazz3  = Class.forName("com.fs.Student");
//得到的同一个对象
        System.out.println(clazz == clazz2);//true
        System.out.println(clazz == clazz3);//true

2.通过Class对象获取某个类所有的属性,方法,构造方法,并使用和调用它

(1)获取属性

 //1.得到反射的核心对象: Class
Class clazz = Class.forName("com.fs.Student");
        //2.得到属性
        //1.根据属性名获取公开属性
        // 抛出NoSuchFieldException异常: 没有匹配的属性
Field nameFiled = clazz.getField("name");
        //打印属性名  getName()
System.out.println("属性名:"+nameFiled.getName());
System.out.println("访问修饰符:"+nameFiled.getModifiers());
System.out.println("属性数据类型:"+nameFiled.getType());
        //给属性赋值  set()
​
        //获取属性的值 get()*/
​
        //根据属性名获取属性, 不管是私有还是公开
Field nameFiled = clazz.getDeclaredField("name");
        //打印属性名  getName()
System.out.println("属性名:"+nameFiled.getName());
        // 0: 缺省的  1: public   2: private  4:protected
System.out.println("访问修饰符:"+nameFiled.getModifiers());
System.out.println("属性数据类型:"+nameFiled.getType());
​
        //给属性赋值 set(Object obj, Object value)
        //obj: 对象    value: 属性值
Student stu = (Student)clazz.newInstance();
        //给stu对象的name属性赋"王五"的值
        //设置private允许访问
nameFiled.setAccessible(true);
nameFiled.set(stu,"王五"); 
        //底层: stu.name ="王五"
​
System.out.println(stu);
​
        //获取属性的值 Object get(Object obj)  //底层: stu.name
System.out.println("属性值:"+nameFiled.get(stu));
        System.out.println("==============================");
        //获取所有的属性
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("属性名:"+field.getName());
        }
       

(2)获取方法

 //1.得到反射的核心对象: Class
Class clazz = Class.forName("com.fs.Student");
        //2.获取公开的方法
        //根据方法名获取指定方法名的方法
        //NoSuchMethodException: 没有匹配的方法
        /*Method studyMethod = clazz.getMethod("study");
System.out.println("方法名:"+studyMethod.getName());
System.out.println("返回值类型:"+studyMethod.getReturnType());
System.out.println("参数列表类型:"
                    +studyMethod.getParameterTypes());
System.out.println("参数个数:"
                    +studyMethod.getParameterCount());
System.out.println("访问修饰符:"
                    +studyMethod.getModifiers());*/
​
        //获取所有的公开方法,包括从父辈类继承
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
​
        //回获取所有访问修饰符修饰的方法,
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        Method studyMethod = clazz.getDeclaredMethod("study");
​
        //创建Student对象
        Student stu = (Student)clazz.newInstance();
        studyMethod.setAccessible(true);
        Object rs =  studyMethod.invoke(stu);
        System.out.println(rs);

(3)获取构造方法

 //1.得到该类Class对象
Class clazz = Student.class;
​
        //2.得到公开的构造方法
        //指定参数类型的构造方法
        // NoSuchMethodException异常: 没有匹配的方法的异常
Constructor c1 = clazz.getConstructor(int.class);
        //打印
        //getName() 得到方法名
System.out.println(c1.getName());
        //getModifiers() 访问修饰符
System.out.println(c1.getModifiers());*/
​
        //得到所有的公开的构造方法
Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
​
        //得到所有的 不管是公开还是私有
Constructor c1 = clazz.getDeclaredConstructor(int.class,String.class);
        //打印
        //getName() 得到方法名
System.out.println(c1.getName());
        //getModifiers() 访问修饰符   1 public  2 private
System.out.println(c1.getModifiers());
​
Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
 //创建类对象
        //1.调用Class的newInstance() 调用公开的无参构造
        //IllegalAccessException 无法访问的异常: 无参构造方法是private修饰
       Student stu =  clazz.newInstance();   // new Student()
       System.out.println(stu);
​
       //2.私有Constructor的newInstance()方法
        Constructor c1 = clazz.getDeclaredConstructor(int.class,String.class);
        Student  stu2  = c1.newInstance(1, "张三");
        System.out.println(stu2);
​
        //如果构造方法是private修饰的
        Constructor c2 = clazz.getDeclaredConstructor(int.class);
        //如果是private修饰,默认无法访问.
        //可以设置允许访问private的  setAccessible(true)
        c2.setAccessible(true);
        Student  stu3  = c2.newInstance(1);
        System.out.println(stu3);

三、Class类的其他方法:

关于注解的相关的方法:

判断 元素上是否包含某个注解: Class,Filed,Method...

// boolean isAnnotation() 如果此 类对象表示注释类型,则返回true。

获取元素上的注解 Class,Filed,Method...

getAnnotation()

Class:

getName() 获取的全限定名: 包名.类名

getSimpleName() 获取的简单名: 类名

反射: 动态操作类的方法,属性,创建对象.... 框架底层使用

如果创建对象, 确定的类, 使用 new 构造方法()

你可能感兴趣的:(java基础1,jvm,java,开发语言)