反射机制超详细

    “程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”,如Python,Ruby是动态语 言;显然C++,Java,C#不是动态语言,但是JAVA有着一个非常突出的动态相关机制:Reflection。 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个 对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 java语言的反射机制,很多优秀的开源框架都是通过反射完成的。

语言根据执行的方式可以分为编译型和解释型,根据运行的情况可以分为静态语言和动态语言.

编译型:需要将源代码编译成机器可以解析的字节码。java  优点:代码安全度高 缺点:执行效率偏低。

解释型:语言解析器可以直接运行源代码。代表:js python  优点:执行效率高。缺点:代码安全度较低。

动态语言: 代码在运行期间可以动态的改变代码的结构或者变量的类型。

静态语言:代码在运行期间无法改变代码的结构或者变量的类型。

编译型语言大多属于静态语言,解释型语言动态语言偏多。

Java:准动态语言。拥有部分动态语言的特性。(反射促成了这个特征Reflection)

那什么是反射我们弄明白了,那反射的底层原理呢?

 

class就是描述类的类

接下来我们来了解class类的对象获取,总共有三种方式

package xizi.com;

import java.io.Serializable;
import java.util.Arrays;

public class Hello01Reflect {
    public static void main(String[] args) throws ClassNotFoundException {
        User user = new User();
        user.id = 100;
        user.name = "张三";
        user.login();
        //System.out.println(user.toString());

        //开始获取类对象的信息--对象获取
        Class clazz01 = user.getClass();
        //开始获取类对象的信息--类进行获取
        Class clazz02 = User.class;
        //开始获取类对象的信息--类的全名
        Class clazz03 = Class.forName("xizi.com.User");

        //判断类是否只被加载一次
        System.out.println(clazz01 == clazz02);
        System.out.println(clazz01 == clazz03);

        //Class的常见方法--获取类加载器
        System.out.println(clazz01.getClassLoader());
        //Class的常见方法--当前类的超类
        System.out.println(clazz01.getSuperclass());
        //Class的常见方法--当前类实现的接口
        System.out.println(Arrays.toString(clazz01.getInterfaces()));
        //Class的常见方法--获取修饰符(public , protected , private , final , static , abstract和interface )
        //2的次幂数进行累加得到的结果是唯一的,通过一个值可以知道多个修饰符
        System.out.println(clazz01.getModifiers());
        //Class的常见方法--包和包名信息
        System.out.println(clazz01.getPackage().getName());
        //Class的常见方法--是否为原始数据类型(8种基本数据类型+1void)
        System.out.println(clazz01.isPrimitive());
        System.out.println(Integer.class.isPrimitive());
        System.out.println(int.class.isPrimitive());
        System.out.println(Integer.TYPE.isPrimitive());
        //数组基本类型还是引用类型--引用数据类型
        System.out.println(int[].class.isPrimitive());
        
    }
}

final class User implements Serializable, Cloneable {
    public int id;
    public String name;

    public void login() {
        System.out.println();
    }
}

一个类最重要的是什么呢? 当然是属性,方法,构造器

同一个包下的两个文件,下面的代码

package xizi.com;

import java.util.Date;

public class Student extends Person implements Study {

    public int sid;
    public String sname;
    protected String sidcard;
    private Date sbirthday;
    public static int scount;

    public Student() {
        //System.out.println("Student.Student-public-0");
    }

    private Student(String name) {
        this.sname = name;
    }

    public Student(int sid, String sname, String sidcard) {
        this.sid = sid;
        this.sname = sname;
        this.sidcard = sidcard;
    }

    public void shello() {
        System.out.println("Student.shello-没有参数");
    }

    public void shello(String name) {
        System.out.println("Student.shello-一个参数" + name);
    }

    public Date shi(String name, int num) {
        System.out.println("Student.shi-两个参数" + name + "--" + num);
        return new Date();
    }

    public static void srun() {
        System.out.println("Student.run--马作的的卢飞快");
    }

    private void shi() {
        System.out.println("Student.shello-没有参数");
    }


    @Override
    public void study() {
        System.out.println("Student.study--实现接口方法");
    }
}

class Person {

    public int pid;
    public String pname;
    protected String pidcard;
    private Date pbirthday;


    public Person() {
        System.out.println("Person.Person");
    }

    public void phello() {
        System.out.println("Person.phello-没有参数");
    }

    public void phello(String name) {
        System.out.println("Person.phello-一个参数" + name);
    }

    public Date phi(String name, int num) {
        System.out.println("Person.phi-两个参数" + name + "--" + num);
        return new Date();
    }

    public static void prun() {
        System.out.println("Person.prun-跑步前进");
    }

}

interface Study {

    void study();

}
package xizi.com;

import java.lang.reflect.Field;

public class Hello02Field {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {

        //获取类
        Class clazz = Class.forName("xizi.com.Student");
        //获取类的属性--获取类或接口的所有可访问公共字段(public)
        Field[] fs = clazz.getFields();
        //Arrays.stream(fs).forEach(System.out::println);

        //获取类的属性--获取类或接口声明的所有字段
        Field[] dfs = clazz.getDeclaredFields();
        //Arrays.stream(dfs).forEach(System.out::println);

        //开始操作Field
        //for (Field field : dfs) {
        //    System.out.println(field.getModifiers() + "--" + field.getType() + "--" + field.getName());
        //}
        //设置和获取属性对应的值
        Student student = new Student();
        Field sid = clazz.getField("sid");
        Field sname = clazz.getField("sname");
        Field sbirthday = clazz.getDeclaredField("sbirthday");

        //属性隶属于对象
        sname.set(student, "张三丰");
        System.out.println(sname.get(student));

        //常见错误--空指针
        //sname.set(null,"张翠山");
        //常见错误--变量的类型不匹配
        //sname.set(student, new Date());
        //sid.set(student, Integer.valueOf(128));

        //静态属性隶属于类
        Field scount = clazz.getField("scount");
        scount.set(null, 100);
        System.out.println(scount.get(null));


    }
}

下面是方法 

package xizi.com;

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

public class Hello03Method {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //获取类的属性
        Class clazz = Class.forName("xizi.com.Student");
        //获取方法--公共方法
        //Method[] ms = clazz.getMethods();
        //Arrays.stream(ms).forEach(System.out::println);
        //获取方法--声明方法
        //Method[] dms = clazz.getDeclaredMethods();
        //Arrays.stream(dms).forEach(System.out::println);
    }

    /**
     * 方法的调用
     *
     * @param clazz
     * @throws NoSuchMethodException
     */
    private static void methodInvoke(Class clazz) throws NoSuchMethodException {
        //获取指定方法--一定要记住加上形参类型列表
        Method shello0 = clazz.getMethod("shello");
        Method shello1 = clazz.getMethod("shello", String.class);
        Method shi = clazz.getMethod("shi", String.class, int.class);
        Student student = new Student();
        //通过反射动态的调用方法
        //shello0.invoke(student);
        //shello1.invoke(student, "zhangsan");
        //Date date = (Date) shi.invoke(student, "张翠山", 18);
        //System.out.println(date);
        //调用静态方法
        //Method srun = clazz.getMethod("srun");
        //srun.invoke(null);
    }

    /**
     * 关于方法的常见错误
     *
     * @param clazz
     * @throws NoSuchMethodException
     */
    private static void methodException(Class clazz) throws NoSuchMethodException {
        //常见的错误--NoSuchMethodException: com.xxxx.Student.shello(int)
        //Method method = clazz.getMethod("shello", int.class);
        //Method method =clazz.getMethod("hello");

        //Method method = clazz.getMethod("shello", String.class);
        //常见的错误--java.lang.NullPointerException
        //method.invoke(null);
        //常见的错误--java.lang.IllegalArgumentException: argument type mismatch
        //method.invoke(new Student(), 18);
        //常见的错误--java.lang.IllegalArgumentException: wrong number of arguments
        //method.invoke(new Student(), "abcd", 18);
        //常见的错误--java.lang.IllegalArgumentException: object is not an instance of declaring class
        //method.invoke(new Object(), "abcd", 18);

        //常见的错误--公共方法调用私有方法
        Method method = clazz.getDeclaredMethod("shi");
        //常见的错误--java.lang.IllegalAccessException: class com.xxxx.Hello03Method cannot access a member of class com.xxxx.Student with modifiers "private"
        //method.invoke(new Student());

        //如果设置为true,则不进行封装型修饰符的检测,那么可以进行私有方法的调用,但是大家尽量不要这么去使用
        //method.setAccessible(true);
        //method.invoke(new Student());
    }
}

下面是构造器

package xizi.com;

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

public class Hello04Constructor {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取类
        Class clazz = Class.forName("xizi.com.Student");
        //获取构造器--公共的
        //Constructor[] cs = clazz.getConstructors();
        //Arrays.stream(cs).forEach(System.out::println);
        //获取构造器--私有的
        Constructor[] dcs = clazz.getDeclaredConstructors();
        //Arrays.stream(dcs).forEach(System.out::println);
        //for (Constructor constructor : dcs) {
        //    System.out.print(constructor.getModifiers() + "--" + constructor.getName() + "--");
        //    System.out.println(Arrays.toString(constructor.getParameterTypes()));
        //}
        //创建对象
        Constructor constructor0 = clazz.getConstructor();
        Student student = (Student) constructor0.newInstance();

        Constructor constructor1 = clazz.getConstructor(int.class, String.class, String.class);
        Student student1 = (Student) constructor1.newInstance(18, "name", "idcard");
        System.out.println(student1.sname + "--" + student1.sidcard);


    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值