zoukankan      html  css  js  c++  java
  • 反射之二

    生成对象

    一般可以用new关键字来创建我们想要的对象。但在特殊情况下,可能只有在程序运行时才知道要常见的对象

    所对应的类名称,这时就需要java反射了,分两种情况来讨论用反射创建对象的方式。

     

    1.用无参构造方法

    调用这个类对应的Class对象的newInstance()方法:

    Class c=Class.forName(“java.util.ArrayList”);

    List list=(List)c.newInstance();

    说明:若指定名称的类没有无参构造方法,在调用newInstance()方法是会抛出会抛出一个NoSuchMethodException

             异常。 

    import java.util.Date;
    /*使用反射调用无参构造方法创建指定名称类的对象*/
    public class NoArgsCreateInstanceTest{
        public static void main(String[] args) {
            Date currentDate=(Date)newInstance("java.util.Date");
            System.out.println(currentDate);
        }
    
        public static Object newInstance(String className){
            Object obj=null;
            try{
                /*加载指定名称的类并获取对应的Class对象,
                  再调用无参构造方法创建出一个对象*/
                  obj=Class.forName(className).newInstance();
            }catch (InstantiationException e) {
                e.printStackTrace();
            }catch (IllegalAccessException e) {
                e.printStackTrace();
            }catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return obj;
        }
    }

     

    2.用带参构造方法

    获取名称的类对应的Class对象(Class a 中的类,而a本身就是一个类),然后通过反射获取指定的参数类型的要求的构造方法信息类对象,

    调用它的newInstance方法来创建对象。

    具体分三步:

    1)获取指定类的Class对象  (获得类的对象

     

    2)通过Class对象获取满足指定参数类型要求的构造方法类对象 (通过类的对象获得对象的构造器

     

    3)调用指定Constructor对象的newInstance方法传入对应的参数值,创建出对象。(再通过类的构造器中的值的集合来获取整个对象的相关的信息

    //创建对象的示例:
    import java.lang.reflect.Constructor;
    import java.lang.reflect.IncocationTargetException;
    import java.util.Date;
    
    /**用反射对指定的带参数的构造方法创建指定类的对象*/
    import java.lang.reflect.Constructor;
    import java.lang.reflect.IncocationTargetException;
    import java.util.Date;
    
    /**用反射对指定的带参数的构造方法创建指定类的对象*/
    public class ArgsCreateIntanceTest{
        @SuppressWarnings("unchecked")
        public static void main(String[] args) {
            try{
                //1.加载指定名称的类,获取对应的Class对象
                Class clazz=Class.forName("java.util.Date");
    
                //2.获取具有指定参数的构造方法
                Constructor constructor=clazz.getConstructor(long.class);
                
                //3.给指定的构造方法传入参数值,创建出一个对象
                Date date=(Date)constructor.newInstance(1234567890L);
                System.out.println(date);
            }catch (ClassNoFoundException e) {
                e.printStackTrace();
            }catch(SecurityException e){
                e.printStackTrace();
            }catch (NoSuchMethodException e) {
                e.printStackTrace();
            }catch (IllegalArgumentException e) {
                //此异常表明向方法传递了一个不合法或不正确的参数或JDK版本不兼容。
                e.pringStackTrace();
            }catch (InstantiationException e) {
                //不在类的加载的时候,所以就会报这样的错误。
                e.printStackTrace();
            }catch(IllegalAccessException e){
                e.printStackTrace();
            }catch(InvocationTatgetException e){
                //一种包装由调用方法或构造方法所抛出异常的受查异常
                e.printStackTrace();
            }
    
        }
    }

     

    调用方法

    用反射可以取得指定类中指定方法对象代表方法对象代表就是java.lang.reflect.lang类的实例,通过Method类的

    invoke()方法可以动态调用这个方法

    method类的invoke()方法完整签名是:

    public Object invoke(Object obj, object…args)

                        throws IllegaAccessException , IllegalArgumentException,InvocationTargetException

    //invoke()的返回值代表的是指动态地调用指定方法后实际返回值

    说明:若要通过反射调用类的某个私有方法,可以在这个私有方法对应的Method对象上,先调用setAccessible(true)

    来取消java对于本方法的访问检查,然后再调用invoke()方法来真正执行这个私有方法。(方法调用方法,前一个方法

    是对象,后一个方法是具体的方法,方法(Method对象)的方法(invoke方法)去调用方法对象);

    iimport java.lang.reflect.InvocationTargetException;

    import java.lang.reflect.menthod;

    /*用反射来动态地调用指定类的指定方法*/
    @SuppressWarnings("unchecked")
    public class ReflectInvokeMethodTest{
        public static void main(String[] args) {
            try{
            Class clazz=Clazz.forName("com.qiujy.");
    
            //利用无参构造函数创建一个Product的对象?? ???
            Product prod=(Product)clazz.newInstance();
    
            //获取名为setName,带一个类型为String的成员方法所对应的对象代表
            Method menthod1=clazz.getDeclaredMethod("setName",String.class);
            //在prod对象上调用setName,并传值给它,返回值为空
            Object returnValue=method1.invoke(prod,"哇");
            System.out.println("返回值:"+returnValue);
            //获取名为displayInfo,不带参数的成员方法所对应的对象代表
            Method method2=clazz.getDeclaredMethod("displayInfo");
    
            method2.setAccessible(true);
            //取消访问调查??setAccessible不是意思为可接近的,可理解的吗?true不是表示真的意思吗?
            //在prod对象上的勇士以的displayInfo方法
            
            method2.invoke(prod);
            }catch (ClassNoFoundException e) {
                e.printStackTrace();
            }catch(SecurityException e){
                e.printStackTrace();
            }catch (NoSuchMethodException e) {
                e.printStackTrace();
            }catch (IllegalArgumentException e) {
                e.pringStackTrace();
            }catch (InstantiationException e) {
                e.printStackTrace();
            }catch(IllegalAccessException e){
                e.printStackTrace();
            }catch(InvocationTatgetException e){
                e.printStackTrace();
            }
        }
    
    }
    class Product{
        private static long count=0;
        private long id;
        private String name="无名氏";
        public Product(){
            System.out.println("默认构造方法");
            id=++count();
        }
        public long getId(){
            return id;
        }
        public void setId(long id){
            this.id=id;
        }
        public String getName(){
            return name;
        }
        private void displayInfo(){//私有方法
            System.out.println(getClass().getName+"[id="+id+",name="+name+"]");
        }
    }

    感觉反射的思维,比较跳跃,自己就是对象,任何东西都是对象,都可以调用其它的东西,其实很多东西,都是按照规则编排出来的,而至于那个东西本身其实不重要,重要的是原理和应用,

    就像是椅子,第一个人把椅子命名为椅子所以它就叫椅子,它也可以叫其它,但是它的作用和性质包括原理,不会随着这个名称的改变而改变,这个概念还有应用好像有些哲学; 

    理解了还要多练习;不然还是不能融会贯通,不能应用;

    更基础的可以参看自己的“反射之一”博客;

    什么是类类型? 

    成年人的世界没有那么多的童话,也没有那么多的逆袭。
  • 相关阅读:
    最全的机器学习资源整理
    论文写作技巧
    制造业期刊-ZT
    机器学习中的算法(2)-支持向量机(SVM)基础
    定语从句
    Digital Twin的8种解读!
    详解BOM用途分类及在汽车企业中的应用
    Intellij IDEA运行报Command line is too long解法
    计算机行业各种职业技能树
    invocationCount和invocationTimeOut
  • 原文地址:https://www.cnblogs.com/shijinglu2018/p/8371615.html
Copyright © 2011-2022 走看看