反射(java)

java反射机制

  • 反射机制是java的动态机制,可以在程序"运行期间"再确定实例化对象,方法调用,属性操作等。
  • 反射机制可以提高代码的灵活度,但是会带来较多的系统开销和较低的运行效率,因此不能过度依赖。
package reflect;

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

public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
            Class类
            Class类称为类的类对象。
            JVM加载一个类的class文件时,就会创建一个Class实例与该类绑定。因此每个被加载的
            类都有且只有一个Class实例,这个实例就是该加载的类的类对象。
            通过一个类的类对象我们可以获取这个类的一切信息(类名,属性,方法,构造器等)从而在
            程序运行期间进行相关的操作

            因此反射第一步就是要获取操作的类的类对象。而获取方式有三种:
            1:类名.class
            Class cls = String.class;
            Class cls = int.class;

            2:Class.forName(String className)
            Class cls = Class.forName("java.lang.String");//参数需要是完全限定名:包名.类名
            注意:基本类型不支持此种方式获取类对象

            3:ClassLoader类加载器形式获取
         */
        //获取String的类对象
//        Class cls = String.class;
//        Class cls = ArrayList.class;


//        Class cls = Class.forName("java.lang.String");
        /*
            java.util.ArrayList
            java.util.HashMap
            java.io.FileInputStream
            java.lang.String
         */
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要加载的类的名字:");
        String className = scanner.nextLine();
        Class cls = Class.forName(className);


        String name = cls.getName();//获取完全限定名:包名.类名
        System.out.println(name);

        name = cls.getSimpleName();//仅获取类名
        System.out.println(name);

        String packageName = cls.getPackage().getName();
        System.out.println("包名:"+packageName);
        /*
            reflect.Person
         */
        //获取String类的所有公开方法(包含从超类继承的方法)
//        Method[] methods = cls.getMethods();
        //获取本类自己定义的方法(包含私有方法)
        Method[] methods = cls.getDeclaredMethods();
        for(Method method : methods){
            System.out.println(method.getName());
        }
    }
}

  • 使用反射机制实例化对象
package reflect;

import java.util.ArrayList;
import java.util.Scanner;


public class ReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        ArrayList list = new ArrayList();
        System.out.println(list);

        //1获取要实例化对象的类的类对象
//        Class cls = Class.forName("java.util.ArrayList");
        /*
            java.util.HashMap
            java.util.Date
            reflect.Person
         */
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入类名:");
        String className = scanner.nextLine();
        Class cls = Class.forName(className);

        //2调用Class的newInstance()来调用无参构造器
        Object obj = cls.newInstance();
        System.out.println(obj);
    }
}

  • 使用指定的构造器实例化对象
package reflect;

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


public class ReflectDemo3 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Person p = new Person("李四",33);
        System.out.println(p);

        //1加载类对象
        Class cls = Class.forName("reflect.Person");
        //2通过类对象获取指定的有参构造器:Person(String,int)
//        Constructor c = cls.getConstructor();//不传参获取的就是无参构造器
        Constructor c = cls.getConstructor(String.class,int.class);
        Object obj = c.newInstance("王五",66);//new Person("王五",66);
        System.out.println(obj);
    }
}

  • 利用反射机制调用方法
package reflect;

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

public class ReflectDemo4 {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        p.watchTV();


        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入类名:");
        String className = scanner.nextLine();
        System.out.println("请输入方法名:");
        String methodName = scanner.nextLine();

        //1实例化
        //1.1加载类对象
//        Class cls = Class.forName("reflect.Person");
        Class cls = Class.forName(className);
        //1.2实例化
        Object obj = cls.newInstance();//Object obj = new Person();

        //2调用方法
        //2.1通过类对象获取要调用的方法
//        Method method = cls.getMethod("watchTV");
        Method method = cls.getMethod(methodName);
        //2.2通过方法对象执行该方法
        method.invoke(obj);//obj.watchTV()   前提是obj表示的是一个Person对象
    }
}

  • 调用有参方法
package reflect;

import java.lang.reflect.Method;

public class ReflectDemo5 {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("reflect.Person");
        Object obj = cls.newInstance();

        //public void say(String info){
        Method method = cls.getMethod("say",String.class);
        method.invoke(obj,"你好!");//p.say("你好!");

        //public void say(String info,int count){
        Method method2 = cls.getMethod("say",String.class,int.class);
        method2.invoke(obj,"嘿嘿",5);//p.say("嘿嘿",5)
    }
}

私有化强行打开访问权限

package reflect;

import java.lang.reflect.Method;

public class ReflectDemo6 {
    public static void main(String[] args)throws Exception {
//        Person p = new Person();
//        p.hehe();//编译不通过!hehe是私有方法!

        Class cls = Class.forName("reflect.Person");
        Object obj = cls.newInstance();
        /*
            Class的方法:
            getMethod(),getMethods()都只能获取到类对象表示的类的公开方法
         */
//        Method method = cls.getMethod("hehe");
        Method method = cls.getDeclaredMethod("hehe");
        method.setAccessible(true);//强行打开访问权限
        method.invoke(obj);//p.hehe();
        method.setAccessible(false);
    }
}

isAnnotationPresent用于检查此类中是否存在指定注释类型的注释。该方法返回一个声明相同的布尔值

package ReflectDemo;

import ReflectDemo.annotations.AutoRunClass;

public class ReflectDemo7 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class cls = Class.forName("ReflectDemo.Person");
        //返回一个是否拥有@AutoRunClass的类
        boolean flag = cls.isAnnotationPresent(AutoRunClass.class);
        if (flag){
            System.out.println("被标注了");
        }else {
            System.out.println("没有被标注");
        }
    }
}

Demo9

package ReflectDemo;

import ReflectDemo.annotations.AutoRunMethod;

import java.lang.reflect.Method;

public class ReflectDemo8 {
    public static void main(String[] args) throws Exception{
        Class cls = Class.forName("ReflectDemo.Person");
        Method method = cls.getMethod("sayHi");
        if (method.isAnnotationPresent(AutoRunMethod.class)){
            AutoRunMethod arm = method.getAnnotation(AutoRunMethod.class);
            int value = arm.value();//获取@AutoRunMethod里的value
            System.out.println(value);
        }
    }
}

Person类

package reflect;

public class Person {
    private String name = "张三";
    private int age = 22;

    public Person(){}

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void sayHello(){
        System.out.println(name+":hello!");
    }

    public void sayHi(){
        System.out.println(name+":hi!");
    }

    public void dance(){
        System.out.println(name+"正在跳舞");
    }

    public void sing(){
        System.out.println(name+"正在唱歌");
    }

    public void watchTV(){
        System.out.println(name+"正在看电视");
    }

    public void playGame(){
        System.out.println(name+"正在打游戏");
    }

    public void say(String info){
        System.out.println(name+"说:"+info);
    }

    public void say(String info,int count){
        for(int i=0;i<count;i++){
            System.out.println(name+"说:"+info);
        }
    }

    private void hehe(){
        System.out.println("我是Person的私有方法!!!");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

通过反射自动调用无参方法

package ReflectDemo;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("ReflectDemo.Person");
        Object obj = cls.newInstance();

        Method[] methods = cls.getDeclaredMethods();
        for (Method method : methods) {
            //判断是否为无参且公开且名中带a的方法
            if (method.getName().contains("a")&&method.getParameterCount()==0 && method.getModifiers()== Modifier.PUBLIC) {
                System.out.println("自动调用方法:" + method.getName() + "()");
                method.invoke(obj);
            }
        }
    }
}

  • 自动调用与当前类Test2在通过一个包中所有类中的无参且公开的方法
package ReflectDemo;

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

/**
 * 自动调用与当前类Test2在通过一个包中所有类中的无参且公开的方法
 */
public class Test2 {
    public static void main(String[] args) throws Exception {
        //定位当前类所在的包
        File dir = new File(Test2.class.getResource(".").toURI());
        //遍历所有的类名
        File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));
        for (File sub : subs) {
            //通过每一个class文件的文件名的到类名
            String fileName = sub.getName();
            String className = fileName.substring(0,fileName.indexOf("."));
            //根据Test2这个类的包名来拼接其它同包中的类的完全限定名
            className = Test2.class.getPackage().getName()+"."+className;
            //加载该类的类对象
            Class cls = Class.forName(className);
            Object obj = cls.newInstance();//实例化对象
            //根据类对象获取该类中所有定义的方法
            Method[] methods = cls.getDeclaredMethods();
            for (Method method : methods) {
                if (method.getParameterCount()==0&&method.getModifiers()== Modifier.PUBLIC){
                    System.out.println("自动调用方法:" + method.getName() + "()");
                    method.invoke(obj);
                }
            }
        }
    }
}

  • 输出与当前类Test3所在同一个包中被@AutoRunClass标注过的类的类名
  • isAnnotationPresent 用于检查此类中是否存在指定注释类型的注释。该方法返回一个声明相同的布尔值。
package ReflectDemo;

import ReflectDemo.annotations.AutoRunClass;
import ReflectDemo.annotations.AutoRunMethod;

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

/**
 * 输出与当前类Test3所在同一个包中被@AutoRunClass标注过的类的类名
 * isAnnotationPresent 用于检查此类中是否存在指定注释类型的注释。该方法返回一个声明相同的布尔值。
 */
public class Test3 {
    public static void main(String[] args) throws Exception {
        File dir = new File(Test3.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("."));
            className = Test3.class.getPackage().getName()+"."+className;
            Class cls = Class.forName(className);

            //输出该类中被所有被@AutoRunClass标注的方法
            if (cls.isAnnotationPresent(AutoRunClass.class)){
                System.out.println(cls.getName()+"被@AutoRunClass标注了");

                Object obj = cls.newInstance();

                //输出该类中被所有被@AutoRunMethod标注的方法
                Method[] methods = cls.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(AutoRunMethod.class)){
                        System.out.println(method.getName()+"被@AutoRunMethod标注了");
                        //根据方法里的参数值调用多少次方法
                        AutoRunMethod arm = method.getAnnotation(AutoRunMethod.class);
                        int value = arm.value();
                        for (int i = 0; i < value; i++) {
                            method.invoke(obj);
                        }
                    }
                }
            }
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值