万事万物皆对象

在java中类也是对象,是Class类的实例对象,这个对象称为该类的类类型

例如:现在有个类叫SmartTalk

 class SmartTalk {

   public String name;
   public int age;

   public void sayHello() {
       System.out.println("hello");
   }

   private void sayHello(String hello){
       System.out.println(hello);
   }
 }

如何去获取这个类的类类型呢?有以下三种方式:

  public class ClassDemo {
      public static void main(String[] args) {
        //第一种方式,说明每一个类都默认含有一个静态的class对象
        Class c1 = SmartTalk.class;
        //第二种方式
        SmartTalk smartTalk = new SmartTalk();
        Class c2 = smartTalk.getClass();
        System.out.println(c1 == c2);//true
        //第三种方式
        Class c3 = null;
        try {
            c3 = Class.forName("包名+SmartTalk");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c2 == c3);//true
        //通过类类型获得实例对象
        try {
            SmartTalk smartTalk1 = (SmartTalk) c1.newInstance();
            smartTalk1.sayHello();//hello
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
      }
  }

获取了类类型有什么用处呢?我们可以获取一个类的所有信息包括类名,属性,方法等,可以通过Field,Method等类来实现。

  public class ClassUtil {
    /**
     * 打印该类的信息,通过反射机制,我们可以获得一个类的信息
     *
     * @param object 该类对象所属类的信息
     */
    public static void printClassInfo(Object object) {
        //要获取类的信息,首先获取类的类类型
        Class c = object.getClass();
        c.getName();//类的全称(包括包名)
        System.out.println(c.getName());

        Field[] fields = c.getDeclaredFields();//获取所有该类自己声明的属性(实例域)
        for (Field filed : fields) {
            Class fc = filed.getType();//获取属性类型的类类型
            System.out.print(fc.getName()+" ");
            System.out.println(filed.getName());
        }


        Method[] methods = c.getDeclaredMethods();//获取所有的public方法,包括父类继承而来的
        c.getDeclaredFields();//获取所有该类自己声明的方法,不管访问去权限,不包含父类的方法
        for (Method m : methods) {
            Class returnType = m.getReturnType();//得到方法返回值类型的类类型
            System.out.print(returnType.getName() + " ");
            m.getName();//获取方法名称
            System.out.print(m.getName() + "(");
            Class[] params = m.getParameterTypes();//获取方法参数列表中的类的类类型
            for (Class param : params) {
                System.out.print(param.getName() + ",");
            }
            System.out.println(")");
        }
    }
  }  

当然了,我们还可以获得一个属性的或者方法的访问权限,通过getModifiers()方法。还有许多特性可以在官方文档里查阅。下面介绍如何通过反射进行方法调用:

  public static void main(String[] args) {
        ...

        Class c1 = SmartTalk.class;//获得类类型
        try {
            /**
             * 访问共有方法
             */
            Method method1 = c1.getMethod("sayHello"/*方法名*/);//获得Method对象,或者使用c1.getDeclaredMethod("sayHello")
            method1.invoke(c1.newInstance()/*类对象*/);//方法调用
            /**
             * 访问非共有方法
             */
            Method method2 = c1.getDeclaredMethod("sayHello"/*方法名*/,String.class/*参数类类型*/);//不可使用getMethod(获取不到对象,抛出method not found)
            method2.setAccessible(true);//调用私有方法时需要设置为true
            method2.invoke(c1.newInstance()/*类对象*/,"hello,SmartTalk"/*参数对象*/);//方法调用
        } catch (Exception e) {
            e.printStackTrace();
        }
  }  

通过代码里的注释,很清楚的展示出了反射机制方法调用的基本流程,java反射机制可以获取正在运行的java对象,改变其属性和行为,非常的灵活。这是一篇反射机制的学习笔记,如有错误,感谢批评指正。