package reflect;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * java反射机制
 *
 * 反射是java的动态机制,可以允许我们在程序[运行期间]再确定实例化,调用某个方法,操作某个属性。
 * 反射机制大大的提高了代码的灵活度,但是会有更高的系统开销和较慢的运行效率。
 * 因此反射机制不能被过度的使用
 *
 *
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
            类对象  Class的实例
            JVM在加载一个类的class文件时,就会同时创建一个Class的实例,使用该实例记录加载的
            类的一切信息(类名,有哪些属性,哪些方法,哪些构造器等)。并且每个被JVM加载的类都有
            且只有一个Class的实例与之对应。
            反射的第一步就是获取要操作的类的类对象,以便程序在运行期间得知要操作的类的一切信息
            然后对其进行响应的操作。

            获取一个类的类对象的常见方式:
            1:类名.class
            例如:
                Class cls = String.class;
                Class cls = int.class;
                注意:基本类型获取类对象只有这一种方式。

            2:Class.forName(String className)
            例如:
                Class cls = Class.forName("java.lang.String");
                这里传入的类名必须是类的完全限定名,即:包名.类名

            3:还可以通过类加载器形式完成
         */

        //获取String的类对象
//        Class cls = String.class;
//        Class cls = ArrayList.class;

//        Class cls = Class.forName("java.lang.String");

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入类名:");
        String className = scanner.nextLine();
        /*
            java.util.ArrayList
            java.util.HashMap
            java.io.ObjectInputStream
            java.lang.String
         */
        Class cls = Class.forName(className);



        //获取当前类对象所表示的类的完全限定名
        String name = cls.getName();
        System.out.println(name);
        //仅获取类名(不包含包名)
        name = cls.getSimpleName();
        System.out.println(name);
        /*
            Package getPackage()
            获取当前类对象所表示的类的包,返回的Package实例表示该包信息
         */
        Package pack = cls.getPackage();
        String packName = pack.getName();
        System.out.println("包名"+packName);
        /*
            Method[] getMethods()
            获取当前类对象所表示的类中定义的所有公开方法,包含从超类继承下来的方法

            java.lang.reflect.Method类,方法对象
            该类的每一个实例用于表示某个类中定义的一个方法,通过它可以获取其表示的方法中的
            相关信息(方法名,参数个数,参数类型,返回值类型等等,并且还可以调用这个方法)
         */
        Method[] methods = cls.getMethods();
        for(Method method : methods){
            System.out.println(method.getName()+"()");
        }

   //类对象直接提供了可以通过公开的无参构造器实例化的功能
        Object obj = cls.newInstance();
        System.out.println(obj);
    }
}