zoukankan      html  css  js  c++  java
  • 反射Reflect

    参考http://www.sczyh30.com/posts/Java/java-reflection-1/

    知识点:

    • Class类的使用
    • 方法的反射
    • 成员变量的反射
    • 构造函数的反射
    • Java类加载机制

    知识整理:

    • Class类的使用
      1. Java中有两样东西不是面向对象,一是普通的数据类型(例:int a=5不是面向对象,但是有封装类来弥补),二是java静态的东西(静态的东西不属于对象,而是属于类)
      2. 在面向对象的世界里,万事万物皆对象,因此:类是对象,类是java.lang.Class类的实例对象,这个对象成为该类的类类型

      举例:

    public class Test {
        public static void main(String[] args) {
            //Foo这个类的实例对象f怎么表示?
            Foo f = new Foo();
            /*Foo这个类也是Class类的一个实例对象,Class类构造方法为私有,类外部不能访问,
            只有java虚拟机能创建Class实例对象。既然不能像创建对象一样new一个实例对象,
            那么怎么Class这个类的实例对象Foo?*/
    
            //三种表示方法,下面c1,c2表示了Foo的类类型(class type)
            //第一种:任何一个类都有一个隐含的静态成员变量class
            Class c1 = Foo.class;
            System.out.println(c1); //class Foo
            //第二种,已经知道该类的对象,通过getClass()方法
            Class c2 = f.getClass();
            System.out.println(c2);//class Foo
    
            System.out.println(c1 == c2); //true
            //第三种表达方式
            Class c3 = null;
            try {
                //c3 = Class.forName("java.lang.Thread");//java.lang.Thread代表Thread这个类,乱写会抛异常
                c3 = Class.forName("Foo");//若字符串写"com.reflect.Foo",文件需打包package com.reflect;关于包知识忘记了,后续研究
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            System.out.println("***" + c3);
    
            //我们完全可以通过类的类类型创建该类的对象,通过c1,c2,或c3创建Foo的实例
            try{
                Foo fo = (Foo)c1.newInstance();//需要有无参数的构造方法
                fo.showFo();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    class Foo {
        public void showFo() {
            System.out.println("this is fo");
        }
    }

     运行结果:

      Class类动态加载类:

        Class.forName("类的全称")

      1. 不仅表示了类的类类型,还表示了动态加载类
      2. 编译时刻加载类是静态加载类、运行时刻加载类是动态加载类

    静态加载类:(编译时就需要加载所有的类,即使用不到也必须加载上,否则不能通过编译)

    public class TestReflect {
        public static void main(String[] args) {
            if("World".equals(args[0])) {
                World w = new World();
                w.start();
            }
    
            if("Excel".equals(args[0])) {
                Excel e = new Excel();
                e.start();
            }
        }
    }
    //类的静态加载,在编译时刻必须加载所有可能使用到的类,例如类Excel不存在,那么程序就不能编译
    class World{
        public void start() {
            System.out.println("World....starts!");
        }
    }
    
    // class Excel{
    //     public void start() {
    //         System.out.println("Excel....starts!");
    //     }
    // }

    动态加载类:(用哪个类加载哪个类,不用不加载)

    public class TestReflect {
        public static void main(String[] args) {
            try{
                //动态加载类,运行时刻加载类,即使没有World、Excel类,编译(javac TestReflect.java)也能通过,
                //但是执行时(java TestReflect World)会报错,因为没有这个类
                Class c = Class.forName(args[0]);
                //World w = (World)c.newInstance();//这样实例化类对象也可以,但是假如是Excel类型怎么办?
                Office o = (Office)c.newInstance();
                o.start();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    interface Office {
        public void start();
    }
    
    class World implements Office {
        public void start(){
            System.out.println("World....starts!!");
        }
    }
    
    // class Excel{
    //     public void start() {
    //         System.out.println("Excel....starts!");
    //     }
    // }

      基本的数据类型对应的类类型

    public class TestReflect {
        public static void main(String[] args) {
            Class c1 = int.class; //int的类类型
            Class c2 = String.class; //String的类类型
            Class c3 = double.class; //double数据类型的类类型
            Class c4 = Double.class; //Double类的类类型
            Class c5 = void.class;
    
            System.out.println(c1);
            System.out.println(c2.getName());
            System.out.println(c3.getSimpleName());//不包含包名的类的名称
            System.out.println(c4.getName());
            System.out.println(c5.getName());
        }
    }

    • 方法的反射
    import java.lang.reflect.Method;
    
    class ReflectUtil {
        /*
         *打印类的信息
         *包括成员函数、成员变量
         */
        public static void printClassMessage(Object obj){
            //1、要获取类的信息,首先要获取类的类类型
            Class c = obj.getClass();//传递的是哪个子类的对象,c就是该子类的类类型
            //2、获取类的名称
            System.out.println("类的名称是" + c.getName());
            /*
              *Java里面方法是Method的对象
              *getMethods()方法获取的是所有的public的函数,包括父类继承而来的
              *getDeclaredMethods方法获取的是所有该类自己声明的方法,不问访问权限,不访问父类方法
              *得到的是数组
              */
            Method[] ms = c.getMethods();//c.getDeclaredMethods(); 
            for(int i = 0; i < ms.length; i++) {
                //得到方法的返回值类型的类类型
                Class returnType = ms[i].getReturnType();
                System.out.println(returnType.getName() + " ");
                //得到方法名称
                System.out.print(ms[i].getName() + "(");
                //获取参数类型,得到的是参数猎豹的类型的类类型
                Class[] paramTypes = ms[i].getParameterTypes();
                for (Class class1:paramTypes) {
                    System.out.print(class1.getName() + ",");
                }
                System.out.println(")");
            }
        }
    }
    
    public class TestReflect {
        public static void main(String[] args) {
            String s = "hello";
            ReflectUtil.printClassMessage(s);
        }
    }

    • 成员变量的反射

         成员变量也是对象

        Java.lang.reflect.Field

        Field类封装了关于成员变量的操作

        getFields()方法获取的是所有的public的成员变量的信息

        getDeclaredFields获取的是自己声明的成员变量的信息,可以是共有的也可是私有的

    import java.lang.reflect.Method;
    import java.lang.reflect.Field;
    class ReflectUtil {
        /*
         *打印类的信息
         *包括成员函数、成员变量
         */
        public static void printClassMessage(Object obj){
            //1、要获取类的信息,首先要获取类的类类型
            Class c = obj.getClass();//传递的是哪个子类的对象,c就是该子类的类类型
            //2、获取类的名称
            System.out.println("类的名称是" + c.getName());
            /*
              *Java里面方法是Method的对象
              *getMethods()方法获取的是所有的public的函数,包括父类继承而来的
              *getDeclaredMethods方法获取的是所有该类自己声明的方法,不问访问权限,不访问父类方法
              *得到的是数组
              */
            Method[] ms = c.getMethods();//c.getDeclaredMethods(); 
            for(int i = 0; i < ms.length; i++) {
                // //得到方法的返回值类型的类类型
                // Class returnType = ms[i].getReturnType();
                // System.out.println(returnType.getName() + " ");
                // //得到方法名称
                // System.out.print(ms[i].getName() + "(");
                // //获取参数类型,得到的是参数猎豹的类型的类类型
                // Class[] paramTypes = ms[i].getParameterTypes();
                // for (Class class1:paramTypes) {
                //     System.out.print(class1.getName() + ",");
                // }
                // System.out.println(")");
    
                Field[] fs = c.getDeclaredFields();
                for(Field field:fs) {
                    //得到成员变量的类型的类类型
                    Class fieldType = field.getType();
                    String typeName = field.getName();
                    //得到成员变量的名称
                    String fieldName = field.getName();
                    System.out.println(typeName + " " + fieldName);
                }
            }
        }
    }
    
    public class TestReflect {
        public static void main(String[] args) {
            String s = "hello";
            ReflectUtil.printClassMessage(s);
        }
    }

    • 构造函数的反射
    • Java类加载机制
  • 相关阅读:
    Linux内核架构读书笔记
    Linux内核container_of 宏
    Linux内核架构读书笔记
    Linux内核架构读书笔记
    Linux内核架构读书笔记
    Linux内核架构读书笔记- 2.4.1 进程复制
    作业07:字符串索引与切片
    作业06:数字类型
    作业04:逻辑运算
    作业05:用户登录(三次机会)且每次输入错误显示剩余次数
  • 原文地址:https://www.cnblogs.com/wmjlh/p/7645980.html
Copyright © 2011-2022 走看看