[Learning] Java reflection Java reflection basis

Knowledge Point

Class is used to describe the object, but can be understood as the reflection is used to describe the class.

Class attributes comprising:

  • Class class itself
  • Package class package is located
  • Field class attributes
  • Method class Method
  • Constructor class constructor
  • Annotation class notes

How to Obtain Class

1.Class static method, forName ( "full class name")

2. Class .class keywords

3. Object object reference methods in .getClass ()

The common method Class

/*
0--默认不写 1--public 2--private 4--protected 8--static 16--final 32--synchronized 64--volatile 128--transient 256--native 512--interface 1024--abstract
*/
int = getModifiers();       //获取类的修饰符(权限+特征)
String = getName();         //获取类的全类名
String = getSimpleName();    //获取简单名(只有类名 )
Class = getSuperClass();     //获取当前父类的对应Class
Class[] = getInterfaces();   //获取当前父类的接口
Package p = getPackage();    //获取当前类所在的包
        p.getName();        //获取包的名字
Class[] = getClasses();      //获取类中的内部类

Object = newInstance();     //获取当前类的对象(相当于调用了类中的无参数的构造方法)如果类中不存在无参数的构造方法,就会抛出NoSuchMethodException异常
Field = getField("属性名");          //获取类中的属性(公有的 自己类+父类)
Field[] = getFields();              //获取类中的全部属性(公有的 自己类+父类)
Field = getDeclaredField("属性名")    //获取当前类的属性(公有 + 私有 自己类)
Field = getDeclaredFields()    //获取当前类的全部属性(公有 + 私有 自己类)
    如果想修改私有的属性则需要设置属性可以被操作
        setAccessible()
public class TestMain {
    public static void main(String[] args) {

        try {
            Class<?> clazz = Class.forName("com.lili.reflect.People");
            Package aPackage = clazz.getPackage();
            int modifiers = clazz.getModifiers();
            System.out.println(modifiers);
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                System.out.println(method.getName());
            }
            System.out.println(aPackage);

            Class<?>[] interfaces = clazz.getInterfaces();
            for (Class c : interfaces) {
                System.out.println(c.getName());
            }

            ArrayList<String> list = new ArrayList<>();
            Class c = ArrayList.class;
            Class superclass = c.getSuperclass();
            while (superclass != null) {
                System.out.println(superclass.getName());
                superclass = superclass.getSuperclass();
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}

Modify the value of using the reflection type String

/*
注意只能是绕过private去修改属性的值,而不能去修改属性的长度,因为是final修饰的。
String的不可变指的是长度+值的不可变
*/
public class ChangeString {

    public static void main(String[] args) {

        try {
            String str = new String("abc");
            System.out.println(str);

            //1、利用反射技术获取String的Class
            Class clazz = str.getClass();
            //2、获取属性
            Field f = clazz.getDeclaredField("value");
            //3、设置可以修改属性的值
            f.setAccessible(true);
            //4、获取属性的值
            char[] newChar = (char[])f.get(str);
            //5、修改属性的值
            newChar[0] = 'xu';
            newChar[1] = 'Li';
            newChar[2] = 'Li';
            System.out.println(str);

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}

The method of using reflection to invoke class

Method can get common, including their own class and the parent class

It can be found in private ways, but through setAccessible(true)to the implementation of proprietary methods.

/**
 * 测试使用反射获取类中的方法
 */
public class TestMethod {

    public static void main(String[] args) {
        try {
            //1、获取People类对应的Class
            Class clazz = People.class;
            //2、获取对象
            People p = (People) clazz.newInstance();
            //3、通过clazz获取其中的方法,通过方法名以及方法的参数类型来定位方法。
            Method m = clazz.getMethod("eat", String.class);
            //4、调用方法,第一个参数是要执行方法的对象,第二个则是传进去的参数列表
            String n = (String) m.invoke(p, "lili要开始吃饭啦");
            System.out.println(n);

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

}

The constructor is executed by the reflection

/**
 * 利用反射执行构造方法
 */
public class TestConstructor {
    public static void main(String[] args) {
        try {
            //1、获取People对应的Class
            Class<People> clazz = People.class;
            //2、获取People中的构造方法,其中省去了构造方法的名称,因为是与类同名
            //无参的就是调用的无参数的构造方法
            //有参数的就是传的构造方法中形参的类型.class
            Constructor<People> constructor = clazz.getConstructor(String.class);
            //3、执行构造方法,同理参数就是要传参数的实参
            People people = constructor.newInstance("哈哈哈哈哈");
            System.out.println(people);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Design a gadget

This gadget can be used instead to create objects of our own function, by passing a string, to help us create an object, while all properties within the object assignment.

In fact, this is a simple simulation of the principles of the Spring IOC thought, IOC (Inversion Of Control) Inversion of Control: The control of the inverted object to the Spring container to deal with; DI (Dependency Injection) Dependency Injection: Create a Spring container At the same time object to help us automatically injected into the value of the property.

public class MySpring {
    //设计一个方法,将我们创建对象的过程交给该方法去执行。
    //参数String类型的全类名
    //返回值 创建出来的对象 Object类型--->再添加上DI依赖注入
    public Object getBean(String classPath) {
        Object obj = null;
        //模拟输入的实参
        Scanner scanner = new Scanner(System.in);
        System.out.println("请给"+ classPath +"的属性赋值");
        try {
            //1、获取该路径下对应的Class
            Class clazz = Class.forName(classPath);
            //2、创建一个对象
            obj = clazz.newInstance();
            //使用set方法对对象的属性进行赋值,找到每一个不同对象对应的set方法。
            //也就是字符串set+属性的名字
            //3、获取类中的属性
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //获取属性的名称
                String fieldName = field.getName();
                //改变属性名中第一个字母的大小写
                String first = fieldName.substring(0, 1).toUpperCase();
                //获取属性名中除开第一个字母的字段
                String last = fieldName.substring(1);
                //拼接set方法
                StringBuilder methodName = new StringBuilder("set");
                methodName.append(first);
                methodName.append(last);
                //4、获取属性的类型
                Class fieldType = field.getType();
                //5、获取方法
                Method method = clazz.getMethod(methodName.toString(), fieldType);
                //接收实参
                System.out.println("请给"+ fieldName +"属性赋值");
                String value = scanner.nextLine();
                /*为了解决参数类型不一致的问题,可以将参数的类型都设置未相应的包装类,
                并且将它们都转换成String的类型,除了Char类型之外需要另外的判断。
                可以利用其它包装类带String类型的构造方法进行处理。
                */
                Constructor con = fieldType.getConstructor(String.class);


                //6、执行方法
                method.invoke(obj, con.newInstance(value));

            }


        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}

Guess you like

Origin www.cnblogs.com/liliHexiaogou/p/11470593.html