zoukankan      html  css  js  c++  java
  • 笔试:通过反射机制访问私有化构造器例子

    问题:实例化对象时一定要用new调用构造方法吗?
    答案:用普通的创建方法(new)是要调用构造方法,如果使用反射或者克隆这些就可以绕过构造函数直接创建对象
    实例:

    /*
     * ClassTest.java -- JDK 1.8
     */
    package T20190328;
    
    import java.io.File;
    import java.io.IOException;
    import java.lang.reflect.AccessibleObject;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Type;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import org.junit.Test;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    
    /**
     * Description:
     * <p>
     * 通过反射访问私有构造方法 例如:
     * 
     * <pre>
     * <code>
     * // 1.获取类A中声明的构造器
     * Class clazz = Class.forName("T20190328.A");
     * Constructor constructor = clazz.getDeclaredConstructor(); // 假设A中只有一个私有构造方法
     * // 2.设置私有访问权限
     * constructor.setAccessible(true); 
     * constructor.newInstance();
     * </code>
     * </pre>
     * <p>
     * @author shuvidora
     * @date 2019-03-28 Thu PM 14:22:07
     */
    
    public class ClassTest {
    
        static List<A> list = new ArrayList<A>();
    
        @SuppressWarnings("unchecked")
        public static <T> T[] cast(Object[] obj) {
            return (T[]) obj;
        }
    
        public static void showTypes(Type[] arr) {
            int len = arr.length;
            if (len == 0) {
                System.out.print("无元素");
                return;
            }
            for (int i = 0; i < len; i++) {
                if (i == 0)
                    System.out.print("(");
    
                if (i == len - 1)
                    System.out.print(arr[i] + ")");
                else
                    System.out.print(arr[i] + ",");
            }
    
        }
    
        @SuppressWarnings("unchecked")
        @Test
        public void test()
                throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            Constructor<A> constructor = null;
            try {
                constructor = (Constructor<A>) Class.forName("T20190328.A")
                        .getDeclaredConstructor(String.class, String.class);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            constructor.setAccessible(true);
            constructor.newInstance("x", "y");
        }
    
        String clsPathFromXml() throws ParserConfigurationException, SAXException, IOException {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 创建DOM解析器工厂对象
            DocumentBuilder builder = factory.newDocumentBuilder(); // 创建DOM解析器对象
            String path = this.getClass().getResource("om.xml").getPath();
            Document doc = builder.parse(new File(path)); // 解析XML文档,并获取该XML文档的Document对象
            Element component = doc.getDocumentElement(); // 获取根节点元素的Element对象
            NodeList nodeList = component.getElementsByTagName("package");
    
            Node pkg = nodeList.item(0);
            Node pkgAttr = pkg.getAttributes()
                    .getNamedItem("name");
            String pkgName = pkgAttr.getNodeValue();
            Node cls = pkg.getFirstChild();
            String clsName = cls.getNodeValue();
    
            return pkgName + "." + clsName;
        }
        
        @Test
        public void testXml() {
            try {
                System.out.println(clsPathFromXml());
            } catch (ParserConfigurationException | SAXException | IOException e) {
                e.printStackTrace();
            }
        }
        
        public static void main(String[] args) {
            String className = null;
            ClassTest ct = new ClassTest();
            try {
                className =ct.clsPathFromXml();
            } catch (ParserConfigurationException | SAXException | IOException e1) {
                e1.printStackTrace();
            }
            Constructor<A>[] constructors = null;
            try {
                constructors = cast(Class.forName(className) // 从类路径下加载并连接类T20190328.A
                        .getDeclaredConstructors());
            } catch (SecurityException | ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            AccessibleObject.setAccessible(constructors, true); // 批量授予访问私有访问权限
    
            // 按类中定义的顺序输出构造器
            for (int i = 0; i < constructors.length; i++) {
                Constructor<A> constructor = constructors[i];
                System.out.print(constructor + "--->");
    
                // 构造器参数全部类型
                Type[] types = constructor.getGenericParameterTypes();
    
                int typeNum = types.length;
    
                showTypes(types);
                System.out.print("===>");
    
                // constructor.setAccessible(true); // 允许私有访问权限, 否则无法实例化对象
    
                // 实例化对象
                A a;
                try {
                    if (typeNum == 1) {
                        a = (A) constructor.newInstance(1);
                        a.b();
                    } else if (typeNum == 2) {
                        a = (A) constructor.newInstance("hello", "world");
                        a.b();
                    } else {
                        a = (A) constructor.newInstance();
                        a.b();
                    }
                    list.add(a);
                } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                        | InvocationTargetException e) {
                    e.printStackTrace();
                }
    
            }
    
            // 打印生成对象的内存地址哈希值
            for (A a : list) {
                System.out.println(a);
            }
        }
    
    }
    
    class A extends B {
    
        private A(String x, String y) {
            System.out.println("has two params : " + x + "," + y);
        }
    
        private A(int i) {
            System.out.println("has one param : " + i);
        }
    
        private A() {
            System.out.println("has zero param");
        }
    
    //    private A(String... strings) {
    //        System.out.println(strings);
    //    }
    
        public void a() {
            System.out.println("A");
        }
    }
    
    class B {
        String name;
        int age;
        
        public void b() {
            System.out.println("B");
        }
    }
    

    om.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <component>
        <package name="T20190328">
            <class>A	</class>
        </package>
    </component>
    

    问题来源:
    https://www.nowcoder.com/questionTerminal/a3f14638ac2e432b884351840f42d80f?toCommentId=1111154

  • 相关阅读:
    c语言程序设计(学生成绩管理系统)————提供给计算机系c语言初学者参考
    C语言之指针排序
    C语言之冒泡法一
    C语言之统计字符
    C语言之while输出菱形
    C语言之do_while输出菱形
    C语言之素数的判断
    C语言之输出菱形
    基于RT-THREAD的定时鱼缸喂食器设计
    dx/dy=1/y’求其二阶导
  • 原文地址:https://www.cnblogs.com/xsjzhao/p/11006784.html
Copyright © 2011-2022 走看看