Java基础知识整理三(反射机制详解…

N、Java的反射机制

    Java程序中许多对象都在运行时会出现两种类型:编译时类型和运行时类型。Java提供了反射机制来获取运行时类的相关信息,如获知这个类中多有的方法和属性,包括私有的方法和属性,在运行时判断一个对象所属的类、创建一个类的实例,在运行时调用一个类的方法或者修改类的某个属性值等,甚至可以在运行时获取和修改这个类中私有属性的值,这些功能在普通机制中是没有办法实现的。

    每个类被加载之后,系统就会为该类生成一个对应的且唯一的Class对象,通过该Class对象可以访问到JVM中的这个类,并获取与之相关的信息。获取一个类的Class对象有以下几种方式:一是使用Class的静态方法forName(),该方法需要传入一个字符串参数,该字符串参数的值应该是某个类的全限定类名;而是调用对象的getClass()方法,该方法是Object类中的一个方法,返回一个Class对象。三是调用否个类的class属性来获取与之相关的Class对象。

    从Class中获取信息:Class类中提供了大量的实例方法来获取某个类的相关信息。在这里就不一一列举了,在后面的实例程序中将有介绍。

    实例1、ReflectionTest

   

package reflectionTest;

import java.lang.reflect.*;

public class ReflectionTest{

    //定义一个加法运算方法和一个普通方法

    public int add(int a1,int a2){

        return a1+a2;

    }

    public String encho(String name){

        return "hello:"+name;

    }

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

        //获取某一个类对应的Class对象的方式之一,命令行参数指定:

        Class<?> classType=Class.forName(args[0]);

        //每一个方法都会有与之对应的一个Method对象

        Method[] methods=classType.getDeclaredMethods();

        for(Method me:methods)

        {

            System.out.println(me);

        }

       

       

       

        //获取某个类对应的class对象的第二种方式:通过 类名.class 语法获得

        Class<?> classType2=ReflectionTest.class;

        //获取add方法对用的Method对应对象,需要传入方法名和参数列表对应的Class对象

        Method addMethod=classType2.getMethod("add",new Class[]{int.class,int.class});

        //通过这个相关Class对象获得对应类的实例

        Object instance1=classType2.newInstance();

        //通过该method对象来调用add方法,需要传入调用者对象和参数值,返回一个Object对象

        Object result1=addMethod.invoke(instance1,new Object[]{100,200});

        //以上的方式通过反射来调用方法,其效果与通过创建对象来调用一样

        System.out.println((Integer)result1);

       

        //同理获encho方法对应的Method对象

        Method enchoMethod=classType2.getMethod("encho",new Class[]{String.class});

        //通过Method对象来调用方法

        Object result2=enchoMethod.invoke(instance1,new Object[]{"Hello World!"});

        System.out.println((String)(result2));

}

}

    实例2、ReflectionTest2.java

package reflectionTest;

import java.lang.reflect.Method;

import java.lang.reflect.Field;

import java.lang.reflect.Constructor;

 

public class ReflectionTest2{

    public Object copy(Object object) throws Exception{

        //获取某一类的对应的Class对象的第三种方式,通过getClass()方法来获得运行时的Class对象

        Class<?> classType=object.getClass();

        //打印出获取的Class对象所关联的类型名

        System.out.println("所要复制的类名为:"+classType.getName());

       

       

       

        Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});

        //通过Class对象获得关联类中的所有属性

        Field[] fields=classType.getDeclaredFields();

        //循环调用类中的方法

        for(int i=0;i<fields.length;i++){

            Field field=fields[i];

            //获取某个属性的名称

            String fieldName=field.getName();

            //提取首字母

            String firstLetter = fieldName.substring(0,1).toUpperCase();

            //提取首字母的目的就是拼接成目标类中存在的方法的名称以供后面的程序获取Method对象时使用

            //因为在Customer这个JavaBean中,set、get方法时有规律的

            String getMethodName="get"+firstLetter+fieldName.substring(1);

            String setMethodName="set"+firstLetter+fieldName.substring(1);

           

            //通过getMethod()方法来获取关联类中所具有的方法对应的Method对象

            //get方法不需要参数

            Method getMethod=classType.getMethod(getMethodName,new Class[]{});

            //set方法需要传入参数,指定参数类型

            Method setMethod=classType.getMethod(setMethodName,new Class[]{field.getType()});

           

            //通过Method对象调用invoke()方法来执行具体的参数,调用时要指定由哪个对象类调用和传入的参数值

            Object value=getMethod.invoke(object,new Object[]{});

            System.out.println("执行get方法,得到属性值为:"+value);

            //调用set方法为副本对象的相关属性赋值

            setMethod.invoke(objectCopy,new Object[]{value});

        }

        return objectCopy;

    }

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

        Customer cs=new Customer();

        Customer csCopy=(Customer)new ReflectionTest2().copy(cs);

        System.out.println(csCopy.getName()+csCopy.getAge()+"");

}

}

class Customer{

    private Long id;

    private String name;

    private int age;

   

    //使用getConstructor()来调用newInstance()时,自定义的构造方法必须声明为public权限

    public Customer(){

        this.id=1l;

        this.name="zhangsan";

        this.age=20;

    }

   

    public void setId(Long id){

        this.id=id;

    }

    public Long getId(){

        return id;

    }

   

    public void setName(String name){

        this.name=name;

    }

    public String getName(){

        return name;

    }

   

    public void setAge(int age){

        this.age=age;

    }

    public int getAge(){

        return age;

    }

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值