ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java的反射机制

2022-02-26 10:58:28  阅读:174  来源: 互联网

标签:反射 java String class Person 注解 机制 Class cls


一.什么是反射

 反射是java中的动态机制,它允许我们在程序运行期间再确定对象的实例化,方法的调用,
 属性的操作等。使得程序的灵活度大大提升,但是同时也带来了更多的资源开销和较低的
 运行效率。
 程序不能过度的依赖反射机制。

2.反射获取方式

Class 类对象
Class的每一个实例用于表示JVM中加载的一个类,并且每个被JVM加载的类都
有且只有一个Class的实例。
通过Class我们可以得知其表示的类的一切信息:类名,包名,有哪些构造器,方法
属性等。并在运行期间获取后进行相关操作。

因此反射操作的第一步就是获取要操作的类的类对象。
获取一个类的类对象方式有:

1: 类名.class
  例如:
  Class cls = String.class;
  Class cls = int.class;
注:基本类型只能通过上述方式获取类对象
2: Class.forName(String className)
  使用Class的静态方法forName传入要加载的类的完全限定名(包名.类名)
  例如:
  Class cls = Class.forName("java.lang.String")
3:类加载器ClassLoader形式

3.常用方法

 Class cls = Class.forName("reflect.Person");

 //通过类对象获取其表示的String的相关信息
        String name = cls.getName();  //获取包名和类名
        
        name = cls.getSimpleName();  //获取类名

         
        System.out.println(cls.getPackage().getName());  //获取包名



 //类对象提供了方法newInstance()可以调用无参且公开的构造器实例化
        Object o = cls.newInstance();

 2获取对应的构造器  Person(String name,int age)
//        cls.getConstructor();//不传参获取的为无参构造器

//3通过构造器实例化对象 new Person("王五",22);
        Object o = cls.newInstance("王五",22);

 //获取当前类对象所表示的类的所有公开方法(包含从超类继承的方法)
        Method[] methods = cls.getMethods();

 //获取私有方法
        Method method = cls.getDeclaredMethod("secret");

 //强行打开访问权限
        method.setAccessible(true);

利用反射机制调用方法: invoke

1.调用无参方法

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

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入类名:");
        String className = scanner.nextLine();
        System.out.println("请输入方法名:");
        String methodName = scanner.nextLine();
        //实例化
//        Class cls = Class.forName("reflect.Person");
        Class cls = Class.forName(className);
        Object o = cls.newInstance();//Person o = new Person();
        //获取要调用的方法
        //仅传入方法名时,是获取该无参方法
//        Method method = cls.getMethod("sayHello");//表示的Person的成员方法sayHello()
        Method method = cls.getMethod(methodName);
        method.invoke(o);//o.sayHello()

    }
}

2. 调用有参方法

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

        Method method = cls.getMethod("dosome",String.class);//dosome(String)
        method.invoke(o,"玩游戏");//p.dosome("玩游戏");

        Method method1 = cls.getMethod("dosome",String.class,int.class);
        method1.invoke(o,"看电视",5);
    }
}

4.反射中使用的注解

 

  定义@AutoRunClass 注解

该注解是用来标注那些可以被反射机制自动调用的类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AutoRunClass {

}
 定义注解时,我们通常会使用java内置的两个注解来加以修饰

1.@Retention 用来指定当前注解的保留级别。有三个可选值,
对应:
  RetentionPolicy.SOURCE          表示当前注解仅保留在源码中
  RetentionPolicy.CLASS(默认值)   表示注解会保留在字节码中,但是反射机制不可用
  RetentionPolicy.RUNTIME         表示保留在字节码文件中,但是可以被反射机制使用
  通常我们定义的注解都会指定为RUNTIME级别,辅助反射机制的操作。
2.@Target用于表示当前注解可以在什么位置上使用。可选项都定义在ElementType上
 常见的有:
   ElementType.TYPE     在类上使用
   ElementType.FIELD    在属性使用
   ElementType.METHOD   在方法上使用
       ...

 判断是否被注解标注 :  isAnnotationPresent(注解名.class)

public class ReflectDemo7 {
    public static void main(String[] args) throws Exception {
        //判断一个类是否有被@AutoRunClass标注
//        Class cls = Class.forName("reflect.Person");
//        Class cls = Class.forName("reflect.Student");
        Class cls = Class.forName("reflect.Test2");
        /*
            出了Class之外,像Method,Filed等其他反射对象也支持isAnnotationPresent
            方法,用来表示是否被指定注解标注。
            比如:
            Method的这个方法就是判断其表示的方法是否有被指定注解标注。
            Constructor的这个方法就是判断其表示的构造器是否被指定注解标注。
         */
        if(cls.isAnnotationPresent(AutoRunClass.class)){
            System.out.println(cls.getName()+":被@AutoRunClass标注了!");
        }else{
            System.out.println(cls.getName()+":没有被@AutoRunClass标注了!");
        }
    }
}

 

标签:反射,java,String,class,Person,注解,机制,Class,cls
来源: https://blog.csdn.net/feifeier120/article/details/123132813

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有