Birdboot第五天 反射的有参 私有方法 注解

目录

annotation注解

注解参数


 

public class ReflectDemo5 {
    public static void main(String[] args) throws Exception{
        Person p = new Person();
        p.say("你好呀");

        Class cls = Class .forName("reflect.Person");
        Object obj = cls.newInstance ();
        Method method = cls.getMethod("say",String.class);
        method .invoke(obj,"大家好");

        Method method1 = cls.getMethod("say",String.class,int.class);
        method1.invoke(obj,"嘿嘿",5);
    }
}

获取私有方法  getDeclaredMethods()

//获取私有方法 getDeclaredMethods
//暴力反射
public class ReflectDemo06  {
    public static void main(String[] args)  throws Exception{
        Person p = new Person();
        Class cls = Class.forName("reflect.Person");
        Object obj = cls.newInstance();
        Method m =cls.getDeclaredMethod("hehe");
        m.setAccessible(true);//强行打开
        m.invoke(obj);
        m.setAccessible(false);
    }

//如何判断私有方法 方法名。getModifier
public class ReflectDemo7 {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("reflect.Person");
        Method[] methods = cls.getDeclaredMethods();//获取Person类定义的所有方法

        for (Method m : methods) {
            String name = m.getName();//获取方法名
            System.out.println(name);
            int modifier = m.getModifiers();//获取访问修饰符
            if(modifier== Modifier.PUBLIC){
                System.out.println("公开方法");
            }else if(modifier== Modifier.PRIVATE){
                System.out.println("私有方法");
            }

            int count = m.getParameterCount();//获取当前方法的参数个数
            System.out.println("有"+count+"个参数");
        }
    }
}

 练习1 获取person类中无参方法 名字“s"开头


public class Test {
    public static void main(String[] args) throws Exception {

        Class cls = Class .forName("reflect.Person");
        Object obj = cls.newInstance ();

        //无参包括私有
        //(m.getParameterCount()==0
        Method [] methods = cls.getDeclaredMethods();
        //fo
        for(Method m:methods){
            if(m.getParameterCount()==0&&
               m.getName().startsWith("s")){
                System.out.println("自动执行方法"+m.getName()+"()");
                m .invoke(obj);
            }
        }


    }
}

 练习2  无参加公开


//调用person所有无参公开方法
public class Test2 {
    public static void main(String[] args) throws Exception {

        Class cls= Class.forName("reflect.Person");
        Object obj = cls.newInstance();
        //
        Method[]methods = cls.getDeclaredMethods();
        for(Method m:methods){
            if(m.getParameterCount()==0&&
                    //java.lang.reflect.Modifier.isPublic(int mod)方法判断
                    // 如果给定mod参数包含public修饰符,则返回true,否则返回false。
                Modifier.isPublic(m.getModifiers())){
                System.out.println("自动执行方法"+m.getName()+"()");
                m.invoke(obj);

            }
        }
    }
}

 练习3

package reflect;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;

/**
 * 调用与Test3所在同一个包中所有类的公开的,无参的方法
 */
public class Test3 {
    public static void main(String[] args) throws URISyntaxException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //定位Test3.class文件所在的目录
        File dir = new File(
                Test3.class.getResource(".").toURI()
        );
        /*

            提示:java语法要求文件名与类名一致。
                Class.forName("包名.类名")

            思路:
            1:根据Test3所在的目录获取所有子项(对应的所有.class文件)
            2:由于文件名与类名一致,因此可以确定所有类的名字,而包名则与Test3一致
            3:利用Class.forName加载
         */
        System.out.println(dir);
        File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
        for(File sub : subs){
            //根据文件名截取类名
            String fileName = sub.getName();
            String className = fileName.substring(0,fileName.indexOf("."));
            String packageName = Test3.class.getPackage().getName();
//            Class.forName("reflect.ArgsDemo");
            Class cls = Class.forName(packageName+"."+className);
            System.out.println("加载类:"+cls.getName());
            //实例化
            Object obj = cls.newInstance();
            Method[] methods = cls.getDeclaredMethods();
            for(Method m : methods){
                if(m.getParameterCount()==0
                        &&
                        Modifier.isPublic(m.getModifiers())
                ){
                    System.out.println("自动调用方法:"+m.getName()+"()");
                    m.invoke(obj);
                }
            }
        }
    }
}

annotation注解

 //反射机制访问注解 isAnnotationPresent(Class cls)
            所有反射对象:
            Class,Method,Constructor,Field等都提供了下面的方法:
            boolean isAnnotationPresent(Class cls)
            用于判断当前反射对象表示的内容是否被参数类对象表示的注解标注了
 


public class ReflectDemo8 {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("reflect.person");
        boolean is = cls.isAnnotationPresent(AutoRunClass.class);
        if(is){
            System.out.println("被标注了");
        }else{
            System.out.println("没有被标注");
        }
    }

}

练习1

 /*
        如果一个注解中只有一个参数时,参数名建议使用value.
        原因:
        实际使用注解时,传参格式为:参数名=参数值
        例如:
        如果当前注解参数定义如下:
        int sum() default 1;
        那么在使用该注解时为sum传参要写作:
        @AutoRunMethod(sum=2)

        当一个注解定义了多个参数时,上述传参机制不考虑顺序
        例如,当前注解有两个参数时:
        int sum() default 1;
        String name();
        在使用当前注解传参时,可写作:
        @AutoRunMethod(sum=1,name="xxx")
        或
        @AutoRunMethod(name="xxx",sum=1)

        但是对于仅有一个参数时,每次传参都指定名字过于累赘
        @AutoRunMethod(sum=2)
        因此,如果仅有一个参数时,若参数名为value时,则可以忽略参数名。
        int value();
        使用时:
        @AutoRunMethod(2)

        若有2个及以上参数时,就算其中一个参数名字为value也不能传参时省略
        例如,当前注解有两个参数时:
        int value() default 1;
        String name();
        在使用当前注解传参时,可写作:
        @AutoRunMethod(value=1,name="xxx")
        或
        @AutoRunMethod(name="xxx",value=1)

        @AutoRunMethod(name="xxx",1) 编译不通过!!

     */

练习2

package reflect;

import reflect.annotations.AutoRunClass;
import reflect.annotations.AutoRunMethod;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;

/**
 * 调用与当前类Test5所在同一个包中被@AutoRunClass标注的类中所
 * 有被@AutoRunMethod标注的方法
 */
public class Test5 {
    public static void main(String[] args) throws Exception {
        File dir = new File(
                Test5.class.getResource(".").toURI()
        );
        File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
        for(File sub : subs){
            String fileName = sub.getName();
            String className = fileName.substring(0,fileName.indexOf("."));
            String packageName = Test5.class.getPackage().getName();
            Class cls = Class.forName(packageName+"."+className);

            if(cls.isAnnotationPresent(AutoRunClass.class)){
                Object obj = cls.newInstance();

                Method[] methods = cls.getDeclaredMethods();
                for(Method m : methods){
                    if(m.isAnnotationPresent(AutoRunMethod.class)){
                        m.invoke(obj);
                    }
                }

            }
        }
    }
}

注解参数

 

       如果一个注解中只有一个参数时,参数名建议使用value.
       原因:
       实际使用注解时,传参格式为:参数名=参数值
       例如:
       如果当前注解参数定义如下:
       int sum() default 1;
       那么在使用该注解时为sum传参要写作:
       @AutoRunMethod(sum=2)

       当一个注解定义了多个参数时,上述传参机制不考虑顺序
       例如,当前注解有两个参数时:
       int sum() default 1;
       String name();
       在使用当前注解传参时,可写作:
       @AutoRunMethod(sum=1,name="xxx")
       或
       @AutoRunMethod(name="xxx",sum=1)

       但是对于仅有一个参数时,每次传参都指定名字过于累赘
       @AutoRunMethod(sum=2)
       因此,如果仅有一个参数时,若参数名为value时,则可以忽略参数名。
       int value();
       使用时:
       @AutoRunMethod(2)

       若有2个及以上参数时,就算其中一个参数名字为value也不能传参时省略
       例如,当前注解有两个参数时:
       int value() default 1;
       String name();
       在使用当前注解传参时,可写作:
       @AutoRunMethod(value=1,name="xxx")
       或
       @AutoRunMethod(name="xxx",value=1)

       @AutoRunMethod(name="xxx",1) 编译不通过!!


//反射机制中获取参数 getAnnotation()
public class ReflectDemo9 {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("reflect.person");
        Method method = cls.getDeclaredMethod("sayhello");
       //确定一下该方法是否被注解@AutoRunMethod标注了
        if(method.isAnnotationPresent(AutoRunMethod.class)){
            //通过方法对象获取表示的方法上的指定注解
            AutoRunMethod arm =method.getAnnotation(AutoRunMethod.class);
            //通过注解对象调用对应的参数方法获取改参数的值(这里是获取value参数的值)
            int value= arm.value();
            System.out.println("参数值:"+value);
        }


    }
}
package reflect;

import reflect.annotations.AutoRunClass;
import reflect.annotations.AutoRunMethod;

import java.io.File;
import java.lang.reflect.Method;

/**
 * 调用与当前类Test6所在同一个包中被@AutoRunClass标注的类中所
 * 有被@AutoRunMethod标注的方法@AutoRunMethod注解参数次
 */
public class Test6 {
    public static void main(String[] args) throws Exception {
        File dir = new File(
                Test6.class.getResource(".").toURI()
        );
        File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
        for(File sub : subs){
            String fileName = sub.getName();
            String className = fileName.substring(0,fileName.indexOf("."));
            String packageName = Test6.class.getPackage().getName();
            Class cls = Class.forName(packageName+"."+className);
            
            if(cls.isAnnotationPresent(AutoRunClass.class)){
                Object obj = cls.newInstance();
                Method[] methods = cls.getDeclaredMethods();
                
                for(Method m : methods){
                    if(m.isAnnotationPresent(AutoRunMethod.class)){
                        AutoRunMethod arm = m.getAnnotation(AutoRunMethod.class);
                        int value = arm.value();
                        for(int i=1;i<=value;i++) {
                            System.out.println("第"+i+"次调用方法"+m.getName()+"()");
                            m.invoke(obj);
                        }
                    }
                }

            }
        }
    }
}

V16 新建annottation类里面 contrller requeatMapping注解

在userController里加注解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值