• java 利用反射创建对象


    创建对象:

    1、使用Class对象的newInstance()方法创建该Class对象的实例,此时该Class对象必须要有无参数的构造方法。

    2、使用Class对象获取指定的Constructor对象,再调用Constructor的newInstance()方法创建对象类的实例,此时可以选择使用某个构造方法。如果这个构造方法被私有化起来,那么必须先申请访问,将可以访问设置为true;

    Eg:

    最简单的:

    package junereflect624;

    class User{

        /*private User(){//将默认的构造方法私有化的话就不可以再创建对象,两种方法都是这样

        }*/

        public String toString() {

            return "User对象创建成功!";

        }

    }

    public class NewInstanceDemo6 {

        public static void main(String[] args) throws Exception {

            //传统方式创建对象

             System.out.println(new User());

             

             //使用反射的方式

             Class<User> c = User.class;

             User u = c.newInstance();(直接newInstance的话必须保证默认的构造方法正常存在,也就是没有被私有化!这是前提条件)

             System.out.println(u);

        }

    }

    复杂点的:更强大的第二种:

    使用指定构造方法来创建对象:

    获取该类的Class对象。

    利用Class对象的getConstructor()方法来获取指定的构造方法。

    调用Constructor的newInstance()方法创建对象。

     

    AccessibleObject对象的setAccessible(boolean flag)方法,当flag为true的时候,就会忽略访问权限(可访问私有的成员)

    其子类有Field, Method, Constructor;

    若要访问对象private的成员?

    在调用之前使用setAccessible(true),

           Xxx x = getDeclaredXxxx();//才能得到私有的类字段.

     

    总结步骤:

     

    1. 1.        获取该类的Class对象。
    2. 2.        利用Class对象的getConstructor()方法来获取指定的构造方法。
    3. 3.        申请访问(设置为可访问)
    4. 4.  调用Constructor(构造方法)的newInstance()方法创建对象。

     

    例子

    package junereflect624;

    import java.lang.reflect.Constructor;

    class Per{

        private String name;

        private int age;

        private Per(){   

        }

        private Per(String name){

        }

        public String toString() {

            return "对象!!!";

        }

    }

    public class NewInstanceDemo7 {

        public static void main(String[] args) throws Exception {

            Class<Per> c = Per.class;

            //System.out.println(c.newInstance());;//证明利用无参的可以

           

            ////先获得需要被调用的构造器(private 修饰的构造方法)

            Constructor<Per> con = c.getDeclaredConstructor();//调用默认的,什么都不要写

            System.out.println(con);//private junereflect624.Per()

            /*con = c.getDeclaredConstructor(String.class);获取指定的构造方法

            System.out.println(con);//private junereflect624.Per(java.lang.String)*/     

            //现在只需要执行这个构造器,

            /**

             *  T newInstance(Object... initargs)

                    使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

             */

           

            //私有的成员是受保护的,不能直接访问

            //若要访问私有的成员,得先申请一下

            con.setAccessible(true);//允许访问

            Per p = con.newInstance();//成功,通过私有的受保护的构造方法创建了对象

            System.out.println("无参构造方法"+p);

           

            con = c.getDeclaredConstructor(String.class);

            System.out.println(con);//private junereflect624.Per(java.lang.String)

               

            con.setAccessible(true);//允许访问

            p = con.newInstance("liuzhao");//成功,通过私有的受保护的构造方法创建了对象

            System.out.println("String构造方法"+p);

        }

    }

    备注:对于此时的话,单例模式就不再安全了!反射可破之!!

     

     

     

    验证:对于枚举而言,反射依然没有办法重新创建对象

    对于枚举,安全!

     

    package junereflect624;

    import java.lang.reflect.Constructor;

    enum Color{

        RED,BLUE,GREEN;

        private Color(){

        }

    }

    public class EnumDemo8 {

        public static void main(String[] args) throws Exception {

            Class<Color> c = Color.class;

           

            Constructor<Color> con = c.getDeclaredConstructor();//(错误在这一行发生,就是说对枚举而言这种方法连构造器都获得不了,)编译可以通过,但是运行就通不过了!

            Color co = (Color) con.newInstance();

            System.out.println(co);//失败,证明对枚举而言不行,所以枚举的单例模式更加安全

            System.out.println(c.isEnum());//true是枚举

        }

    }

  • 相关阅读:
    一个从excel导入数据错位问题
    Chrome F12 温故而知新 :因为重定向导致清空Network信息
    export / import 温故而知新
    Chrome Debugger 温故而知新:上下文环境
    微信导出表情包教程
    Oracle中判断字段是否为数字
    获取GridView中RowCommand的当前索引行
    Oracle SQL常用内置系统函数总结
    使用Task代替ThreadPool和Thread
    Visual Studio 使用及调试必知必会
  • 原文地址:https://www.cnblogs.com/fanweisheng/p/11136819.html
Copyright © 2020-2023  润新知