Java反射学习

1. Class类
Java程序中的各个类属于同一类事物,描述这类事物的Java类名就是Class。Class类代表各个类和接口在内存中的字节码,比如ArrayList类的字节码,一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的。
如何获得各个字节码对应的实例对象?
  • 类名.class,例如,System.class
  • 对象.getClass(),例如,new Date().getClass()
  • Class.forName("类名"),例如,Class.forName("java.util.Date")
只要在Java源程序中出现的类型,都有各自的Class实例对象
        
        String str1 = "abc";
        Class cls1 = str1.getClass();
        Class cls2 = String.class;
        Class cls3 = Class.forName("java.lang.String");


        System.out.println(cls1 == cls2);//true
        System.out.println(cls1 == cls3);//true<span style="white-space:pre">	</span>


2. 反射
反射就是把Java类中的各种成分映射成相应的java类。一个类中的组成部分:成员变量、方法、构造方法、包等等信息都可以用java类来表示,它们是Field、Method、Contructor、Package。


3.Constructor

3.1 获取某个类的所有构造方法:
Constructor [] constructors = Class.forName("java.lang.String").getConstructors();

3.2 获取某一个构造方法
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class); //这个StringBuffer表示选择哪个构造方法

3.3 创建实例对象
通常方式:String str = new String (new StringBuffer("abc"));

反射方式:String str = (String) constructor.newInstance(new StringBuffer("abc"));


3.4 Class.newInstance()方法
String str = (String)Class.forName("java.lang.String").newInstance();

该方法内部会先得到默认的构造方法,然后用该构造方法创建实例对象。


问题:通过反射创建类的对象实例
public class MyTest {


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


        Class ret = Class.forName("StrObj");
        StrObj strObj = (StrObj) ret.newInstance();
        strObj.display();
    }


}


class StrObj {


    private String name = "Tom";
    private int    age  = 12;


    public StrObj() {
    }


    public StrObj(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }


    public void display() {
        System.out.println("StrObj [name=" + name + ", age=" + age + "]");
    }
}

注意:如果StrObj没有空的构造方法,则程序报错。在利用反射创建对象的实例时,一定要写无参的构造方法。


4. Field

Field类代表某个类中的一个成员变量。Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而对象可以有多个,如果是与对象关联,那关联的是哪一个对象呢?所以Field代表的是类的成员变量,而不是具体对象的。
问题:将一个对象中所有String类型的成员变量所对应的字符串内容中的"b"改为"a"?
public class MyTest {

    public static void main(String[] args) throws Exception {
        StrObj strObj = new StrObj();
        Class clazz = strObj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //处理String类型变量
            if (field.getType() == String.class) {
                if (!field.isAccessible()) {
                    //处理private成员变量
                    field.setAccessible(true);
                }
                String str = (String) field.get(strObj);
                field.set(strObj, str.replaceAll("b", "a"));//替换字符
                String newStr = (String) field.get(strObj);
                System.out.println(newStr);
            }
        }
    }

}


class StrObj {
    private String name  = "12abcb";
    public String  email = "aabbcc";
    public int     age   = 11;
}


注意:

getFields()与getDeclaredFields()区别:getFields()只能访问类中声明为公有的字段,私有的字段它无法访问,能访问从其它类继承来的公有方法。getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的方法。 


5. Method

Method类代表某个类中的一个成员方法。


5.1 得到类中的某一个方法
Method charAtMethod = Class.forName("java.lang.String").getMethod("charAt", int.class);

5.2 调用方法
通常方式:str.charAt(1)
反射方式:charAtMethod.invoke(str, 1)
如果传递给invoke()方法的第一个参数为null,说明给Method对象对应的是一个静态方法。

问题:利用反射调用一个类的静态方法?
Method m1 = Math.class.getMethod("abs", double.class);
m1.invoke(null, -2.3);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值