反射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类加载机制
原文地址:https://www.cnblogs.com/wmjlh/p/7645980.html