栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

Java 反射机制

Java 更新时间:发布时间: 百科书网 趣学号
概述:

反射机制是动态语言的关键,可以在程序运行期间获得任何类的内部信息,并能直接操作任意对象的内部属性及方法。通俗的说就是在运行时代码可以根据某些条件改变自身结构。

主要动态语言:Javascript,PHP,Python

静态语言:Java,C,C++

Java不是动态语言,但Java可以称之为 “准动态语言” 。即Java有一定的动态性,我们可以利用反射机制,字节码操作获得类似动态语言的特性。


Java.Lang.Class类           1. 获取Class实例

程序经过Javac.exe命令后,会生成一个或多个字节码文件(.class结尾)。(编译过程)

接着我们使用Java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程称为类的加载。加载到内存中的类,我们称之为运行时类,此运行时类,就作为Class的一个实例.(运行时的类同样也可以作为一个对象,体现出了Java万事万物皆对象的思想)

public class newclass {
    //获取class实例的方式(掌握前三种方式)
    @Test
    public void test01() throws ClassNotFoundException {
        //方式一:调用运行时类的属性:.class
        Class clazz1 = Person.class;
        System.out.println(clazz1);

        //方式二:通过运行时类的对象,调用getClass()
        Person p = new Person();
        Class clazz2 = p.getClass();
        System.out.println(clazz2);

        //方式三:调用Class的静态方法:forName(String classPath) 常用
        Class clazz3 = Class.forName("newday.wangluobiancheng.Person");//抛异常
        System.out.println(clazz3);

        //方式四:使用类的加载器:Classloader
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("newday.wangluobiancheng.Person");
        System.out.println(clazz4);
    }
}

注意;

  • Class的实例只对应着一个运行时类,加载到内存中的运行时类,会缓存一段时间。在此时间内,我们可以通过不同的方式来获取此运行时类。
  • Class的对象可以是:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类。接口,数组,枚举,注解,基本数据类型,void(我们可以把void看成一个类型,相当于是没有返回值的类型),Class本身。
  • 只要数组类型相同,维度相同,那他就是一个Class。

                2. 创建运行时类的对象
使用newInstance()创建对应的运行时类的对象。  
 @Test
    public void test01() throws IllegalAccessException, InstantiationException {
        Class personClass = Person.class;
        Person person = personClass.newInstance();

    }

注意;

  • 运行时类必须提供空参的构造器。
  • 内部调用了运行时类的空参构造器。
  • 空参构造器的访问全选不可为私有。(通常设为public)

          3. 获取运行时类的属性及其权限,数据类型,名称
   @Test
   public void test(){
        Class aClass = Person.class;
        //获取属性结构
        //getFields():获取当前运行时类及其父类声明为public访问权限的属性
        Field[] fields = aClass.getFields();
        for(Field f:fields){
            System.out.println(f);
        //输出结果
        //public java.lang.String newday.wangluobiancheng.Person.name
        //public int newday.wangluobiancheng.Person.age

        }

    }
获取属性的相关方法
Field[ ]  getFields( )获取当前运行时类及其父类中声明为public的属性,并返回数组
Field[ ]  getDeclaredFields( )获取当前运行时类的所有属性,包括私有权限的属性。(不包括父类中的属性)
   @Test
   public void test(){
        Class aClass = Person.class;
        //获取属性结构
        //getFields():获取当前运行时类及其父类声明为public访问权限的属性
        Field[] fields = aClass.getFields();
        for(Field f:fields){
            //获取当前属性的权限
            int modifier = f.getModifiers();
            System.out.println(Modifier.toString(modifier));
            //获取数据类型
            Class type = f.getType();
            System.out.println(type);
            //获取变量名
            String name = f.getName();
            System.out.println(name);
        }

    }
                   4. 获取运行时类的方法及内部结构
        //获取运行时类及其父类的public方法        
        Method[] methods = clazz.getMethods();
        for(Method m:methods){
            System.out.println(m);
        }
        //获取运行时类的所有方法
        Method[] methods1 = clazz.getDeclaredMethods();
        for (Method m:methods){
            System.out.println(m);
            //获取注解
            Annotation[] a = m.getAnnotations();
            for(Annotation an:a){
                System.out.println(an);
            }
            //权限修饰符
            System.out.println(Modifier.toString(m.getModifiers()));
            //返回值类型
            System.out.println(m.getReturnType().getName());
            //方法名
            System.out.println(m.getName());
            //形参列表
            Class[] parameterTypes = m.getParameterTypes();
            if(!(parameterTypes == null && parameterTypes.length ==0)){
                for (Class p:parameterTypes){
                    System.out.println(p.getName());//此处获取的是形参类型,无法获取形参名。
                }
            }
            //抛出的异常
            Class[] exceptionTypes = m.getExceptionTypes();
            if (!(exceptionTypes == null && exceptionTypes.length ==0)){
                System.out.println("throws");
            for(Class ex:exceptionTypes) {
                System.out.println(ex.getName());
            }
            }
            
        }
    }
                  5. 获取运行时类的构造器
    @Test
   public void test() {
        Class clazz = Person.class;
        //获取当前运行时类的public的构造器
        Constructor[] constructors = clazz.getConstructors();
        for(Constructor con : constructors){
            System.out.println(con);
        }
        //获取当前运行时类的所有构造器
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for(Constructor con : declaredConstructors){
            System.out.println(con);
        }
    }
                6. 获取运行时类的父类及其泛型
    @Test
    public void test66(){
        Class aClass = Person.class;
        //获取运行时类的父类
        Class superclass = aClass.getSuperclass();
        System.out.println(superclass);
        //获取运行时类带泛型的父类
        Type genericSuperclass = aClass.getGenericSuperclass();
        System.out.println(genericSuperclass);
        //获取运行时类带泛型的父类的泛型
        Type genericSuperclass1 = aClass.getGenericSuperclass();
        ParameterizedType pararmeterizedType = (ParameterizedType) genericSuperclass1;
        Type[] actualTypeArguments = pararmeterizedType.getActualTypeArguments();
        System.out.println(actualTypeArguments[0].getTypeName());
    }
                7. 获取运行时类实现的接口
@Test
    public void test89(){
    //获取运行时类的接口
    Class personClass = Person.class;
    Class[] interfaces = personClass.getInterfaces();
    for(Class inter:interfaces){
        System.out.println(inter);
    }
    //获取运行时类所在的包
    Package aPackage = personClass.getPackage();
    System.out.println(aPackage);
    //获取运行时类的注解
    Annotation[] annotations = personClass.getAnnotations();
    for (Annotation ann:annotations){
        System.out.println(ann);
    }
}

调用运行时类指定结构(重点)           1. 操作指定属性
@Test
    public void mytools() throws IllegalAccessException, InstantiationException, NoSuchFieldException {

    Class aClass = Person.class;
    Object per = aClass.newInstance();
    //获取指定属性:运行时类的属性声明为public(不常用)
    Field age = aClass.getField("age");
    //设置参数 set(指定对象,属性值)
    age.set(per,100);

    //获取指定对象的属性值
    int age1 = (int)age.get(per);




    Class personClass = Person.class;
    Object pers = personClass.newInstance();

    Field age2 = personClass.getDeclaredField("age");
    //保证当前属性是可访问的。
    age2.setAccessible(true);
    
    age2.set(pers,10025);
    int myAge = (int)age2.get(pers);


}
                       2. 操作指定方法
@Test
    //操作非静态的方法
    public void mytest() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
    Class clazz = Person.class;
    Object p = clazz.newInstance();
    //获取指定方法 getDeclaredMethod(“指定的方法”,形参类型.class)
    Method show = clazz.getDeclaredMethod("show", String.class);
    //保证当前方法的可访问性
    show.setAccessible(true);
    //调用指定方法,invoke(对应的实例,实参),invoke()的返回值即为对应方法的返回值,无返回值时返回null
    Object invoke = show.invoke(p, "myfavorite");

    //操作静态方法
    Method showmoney = clazz.getDeclaredMethod("showmoney", String.class);
    showmoney.setAccessible(true);
    Object invoke1 = showmoney.invoke(Person.class);

}
                         3. 调用指定构造器
@Test
  //获取指定构造器
  public void testconstructer() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

    Class clazz = Person.class;

    Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
    declaredConstructor.setAccessible(true);

    Person jack = (Person)declaredConstructor.newInstance("jack");
    System.out.println(jack);


}

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/295289.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号