反射之二

 

生成对象

一般可以用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+"]");
    }
}

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

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

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

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

什么是类类型? 

posted @ 2018-01-28 16:51  贰零一八  阅读(162)  评论(0编辑  收藏  举报