java反射详解

反射
1、反射是Java中的动态机制,它允许我们调用方法或属性,从原来的编码期确定转为在运行期,这大大增加了程序的灵活性,反射会增加程序灵活性,但是会降低性能,所以适度使用
2、Class类
    class类的每一个实例表示jvm加载的一个类,所以我们也称其为:类的类对象
    jvm加载的每一个类都有且只有一个唯一的Class实例与之对应。我们可以获取摸个类的类对象,
    通过它我们可以得知该类的一切信息,例如有类名 属性 方法等甚至可以动态的实例化这个类的
    实例,并且调用他的属性和方法。
    
3、获取一个类的类对象有以下几种方式
    1、每个类都有一个静态的属性:class;用于获取该类的类对象,当我们要获取摸个类的对象时
    可以采用这个方式,但是由于通过硬编码调用,所以不灵活
    例如: 创建一个类 Demo 获取它的信息
        Class cls = Demo.class; 
    
    2、调用Class的静态方法,动态加载类,该方法要求传入的是加载的类的完全限定名即:包名.类名
    Class cls = Class.forName("web.Demo"); // web 包下的 Demo 类

   完整案例:你可以将以下代码拷贝到你的类中运行,注意里面会有一些小的错误,自己稍作调整就好了
    package mvc;

    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.Scanner;

    /*
     * invoke执行方法
     * field 字段 属性
     * declared定义的
     */
    public class RefelectDemo {
        public static void main(String[] args) {
            /*
             * 写法一,这种写法不灵活,写死了,我们需要动态加载类
             */
            Class cls = Demo.class;
            /*
             * 写法二,动态加载类
             */
            
            try {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入一个类名(格式:包名.类名)");
                String className = sc.nextLine();
                System.out.println("请输入要执行的方法:");
                String methodName = sc.nextLine();
                
                Class cl=Class.forName(className);
                //获取类名
                String clname = cl.getName();
                System.out.println("类名:"+clname);
                //获取包名
                Package clpackage = cl.getPackage();
                System.out.println("包名:"+clpackage);
                //获取所有方法,包括从父类继承的方法
                Method[] methods = cl.getMethods();
                for(Method o : methods) {
                    System.out.println("所有方法,包含从父类继承的方法:"+o.getName());
                }
                //获取当前类自己定义的方法,不包含继承父类的方法
                Method[] methods2 = cl.getDeclaredMethods();
                for(Method m : methods2) {
                    System.out.println("获取自己定义的方法,不包含继承父类的方法"+m.getName());
                }
                //获取当前类定义的属性
                Field[] fields = cl.getDeclaredFields();
                for(Field f : fields) {
                    System.out.println("==="+f.getName());
                }
                //获取所有的属性,包括继承父类的属性
                Field[] fields2 = cl.getFields();
                for(Field f : fields2) {
                    System.out.println(f.getName());
                }
                //当我们加载好类的时候,就相当于我们创建了一个类,这时候,我们要实例化对象
                //当我们创建好了对象之后,我们需要对他进行实例化操作,也就是所谓的new对象
                //这里为什么不new呢?因为我们不知道要加载什么类,这个类是我们事先不知道的
                //而且实例化的类型是一个Object类型
                //类的实例化要求该类必须有无参构造方法,记住,反射的类必须有无参构造方法
                Object object = cl.newInstance();
                //这里调用的是一个无参方法
                Method method = cl.getDeclaredMethod(methodName);    
                //调用有参方法
                //Java 在JDK5 之后推出了一个新特性,可变长参数
                //Method method = cl.getDeclaredMethod(methodName, String.class,int.class,....一直加参数.class....);
            
                /*
                 * 调用该方法
                 * private void say(){
                 *        syso("hello"); 
                 * }
                 */
                //对于成员方法而言,调用时必须指定该方法所属的对象
                method.invoke(object);
                
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    小结: 以上是所有反射的基本认识,需要熟练掌握,反射一般是不常用,他的作用在: 很多框架的底层都是用反射实现的,我们需要掌握原理
    
    
    3、可变长参数讲解
    package reflect;
    
    import java.util.Arrays;
    
    /**
     * JDK5之后推出了一个特性:可变长参数
     * @author ta
     *
     */
    public class ArgDemo {
        public static void main(String[] args) {
            dosome(1,1.1);
            dosome(1,1.1,"a");
            dosome(1,1.1,"a","b");
            dosome(1,1.1,"a","b","c");
            dosome(1,1.1,"a","b","c","a","b","c","a","b","c","a","b","c","a","b","c");
        }
        
        public static void dosome(int a,double d,String... s) {
            System.out.println("length:"+s.length);
            System.out.println(Arrays.toString(s));
        }
    }


    

    4、使用类加载器 ClassLoader 加载类
    
    5、 细说反射
        我们之前所有的类都是预先创建一个类,然后呢,给他设置属性方法,这个类是我们需要的,预先知道的类,而且是我们自己定义的
        但是,当我们需要使用一些其他的类,而且这个类是我们不知道的类呢?我们不知道它定义的属性和方法,这时候,我们就需要用反射,而且反射提供了动态加载类的方法,这使得我们在用的时候更加灵活方便。而且反射可以强行读取该类的私有属性和方法,不过不建议使用。
        package mvc;

        import java.lang.reflect.Method;
        import java.util.Scanner;

        public class ReflectDemo {
            public static void main(String[] args) throws Exception{
                /*
                 * 反射最好的地方就是不知道类 不知道方法名的情况下可以执行,较为常用
                 * 利用反射调用方法步骤 1、加载类 2、在类中找到方法 3、创建对象 4、在对象上执行方法
                 * 反射可以强行读取私有属性和方法 ,不建议
                 */
                Scanner sc = new Scanner(System.in);
                System.out.println("输入一个类名");
                String className = sc.nextLine();
                
                //Class 是所有反射的入口
                //动态加载类
                Class<?> cls = Class.forName(className);
                //输入方法名
                System.out.println("输入方法名");
                String methodName=sc.nextLine();
                //动态找到类上申明的方法 如果找不到就抛出异常
                Method method=cls.getDeclaredMethod(methodName);
                //创建动态对象: 现在还不知道类怎么创建对象呢,反射有专门的方法 实例化对象,以前是知道类名才能创建对象,现在是不知道类也可以创建对象
                //newInstance的使用前提是类型必须包含无参构造器
                Object obj = cls.newInstance();
                //在对象上调用方法 如果方法有参数就这样写 method.invoke(obj,方法参数);
                //如果参数错误或者对象上没有方法,或者方法执行期间出现故障,都会抛出异常
                //Access访问, Accessable 权限可访问的 也就是属性和方法如果是私有的,那么设置了如下代码后会强行访问私有属性和方法
                method.setAccessible(true);
                Object val = method.invoke(obj);
                System.out.println(val);
            }
        }

总结:每个学习Java的人,都需要好好的做笔记,勤于练习,有人说,每天学习基础,很枯燥,很无聊,但是你需要知道,每个无聊的基础,组合成了一个完整的项目。当你的代码足够熟练,自然就能孰能生巧。QQ2951960165

    
    

基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤树)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值