zoukankan      html  css  js  c++  java
  • Java-反射浅谈

    这篇文章就是简简单单的介绍反射是什么、怎么用,面向初学者,老鸟勿喷。不涉及深层的原理。因为我不懂。

    1.嘛是反射?

    我在自己学习反射的时候,看到了一个说法很有意思——

    有反就有正。我们先来看看“正射”是什么:

    我们先定义一个Apple类,定义构造函数和属性:

    class Apple
    {
        private int age;
        public String name;
    
        public void setName(String name)
        {
            this.name = name;
        }
    
        private Apple()
        {
        }
    
        public Apple(int age, String name)
        {
            this.name = name;
            this.age = age;
        }
    
        public int getAge()
        {
            return age;
        }
    
        private void setAge(int age)
        {
            this.age = age;
        }
    
        
    }
    

      然后在main函数中:

    public static void main(String[] args)
    {
        Apple apple = new Apple(12, "青苹果");
    }
    

    这种我们最常用的建立对象的方式就是“正射”。来看看我们是怎么定义了这个对象的:

    1.我们知道有一个类叫做Apple。

    2.我们至少知道这个类的一个构造函数——至少要传入一个int一个String。

    我们事先知道了这个类和这个类的信息来创建对象,就是“正”。反射,就是在不知道这个类的具体信息的前提下,来创建对象、获取类的方法属性等等。一个是睁着眼一个是闭着眼,这么说你总能听明白了吧。

    2.怎么使用反射?

    我们既然想操作一个类,就至少得知道他是谁吧,也就是说我们得获取一个“类对象”。

    类对象,用来创建其他对象的对象。

    这里我们有三种方式来创建类对象:

    1.Class cls=Class.forName(String string):其中参数是类的全路径名。我们知道一个类的全路径名时可以用这种方式。

    class ReflectDemo
    {
        public static void main(String[] args)
        {
            try
            {
                Class cls = Class.forName("Practice.Apple");
            } catch (ClassNotFoundException e)//这个方法会抛出ClassNotFoundException,找不到你指定的类就会异常。
            {
                e.printStackTrace();
            }
        }
    }
    

    2.xxx.class 适合编译之前就知道class的情况。

    class ReflectDemo
    {
        public static void main(String[] args)
        {
            Class cls = Apple.class;
        }
    }
    

    3.使用对象的getClass()方法。

    class ReflectDemo
    {
        Apple apple = new Apple();
        Class cls = apple.getClass();
    }
    

    三种方式各有各的使用场景。

    好了,我们现在已经拿到了这个类的类对象,下一步我们就可以用反射建立这个类的对象了。

    建立类对象有两种方式:

    1.使用类对象的.newInstance()方法来获取一个使用无参的构造函数初始化的对象。

    try
    {
        Class cls = Class.forName("Practice.Apple");
        Apple apple = (Apple) cls.newInstance();
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e)
    //newInstance()抛出InstantiationException(如果此 Class 表示一个抽象类、接口、数组
    // 类、基本类型或 void; 或者该类没有 null 构造方法)
    //与IllegalAccessException(如果该类或其 null 构造方法是不可访问的)
    {
        e.printStackTrace();
    }
    

    我装的是java11,newInstance()似乎是被要废弃了?

    2.通过Constructor对象的newInstance()方法。这个方式我们可以指定构造方法。

    public static void main(String[] args)
    {
        try
        {
            Class cls = Class.forName("Practice.Apple");
            Constructor constructor = cls.getConstructor(int.class,String.class);
            Apple apple = (Apple) constructor.newInstance(13, "毒苹果");
        } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e)
            //getConstructor()会抛出NoSuchMethodException。
            //newInstance()抛出InstantiationException,IllegalAccessException,
            //InvocationTargetException(当被调用的方法的内部抛出了异常而没有被捕获时,将由此异常接收)
        {
            e.printStackTrace();
        }
    }
    

     在getConstructor时我们要指定参数类型。注意是class类型

    对象有了,我们现在需要调用对象的属性or方法时怎么调用呢?

    1.获取对象的属性

    Field[] fields = cls.getFields();//cls是我们的类对象
    for (Field field : fields)
    {
        System.out.println(field);
    }

    getFields可以获取到所有除private的属性。若获取指定属性可以使用getField(String name)。

    获取所有包括private的属性我们可以使用getDeclaredFields()。

    2.获取对象的方法

    Method[] methods = cls.getMethods();
    for (Method method : methods)
    {
        System.out.println(method);
    }
    

    道理同上,getDeclaredMethods()可以获取所有方法。

    有了这些,我们就可以对对象进行操作了。

    3.执行对象的方法

    Method method = cls.getMethod("setAge", int.class);
    method.invoke(apple,10);
    System.out.println(apple.getAge());
    

    分析代码:

    首先我们指定了方法名来获取指定的方法(第一个参数是方法名,第二个是方法的参数的所属类。这里注意,若参数为int型的,要么写int.class,要么写Integer。Integer.class是不行的。)

    接着我们调用方法的invoke(invoke,执行之意)。第一个参数是我们想在哪个对象上调用方法,第二个是参数值。(若方法为私有方法,我们虽然可以获取到但是不能执行。若想执行,则需要在执行前调用method.setAccessible(true))

     有了以上的知识,你就已经了解了最基本的反射知识并且能灵活使用反射了。其他的我以后补充。希望能帮助到初学者理解。

     

  • 相关阅读:
    grep
    Ubuntu配置sun jdk
    mysqldump导出数据库表结构与数据至本地
    checkbox前后台使用
    MAC OS X 命令行提交本地项目到git
    前端参数传递错误之中英文字符
    微信支付之扫码支付(java版 native原生支付)
    jquery 取消 radio checked 属性,重新选中的问题解决
    消除父级元素对子级元素的点击事件影响
    mysql 双机热备注意事项
  • 原文地址:https://www.cnblogs.com/KangYh/p/10633226.html
Copyright © 2011-2022 走看看