笨鸟学习Java反射

前年写过一篇关于java“反射”的博客,现在看来不够深入。如今在原来的基础上再加一些东西。主要细化一下反射中主要用到的方法。还是在原来代码的基础上进行测试。

1. 获取反射class对象

在原来的博客中介绍过反射获取class对象的三种方式。如下:

//第一种方式获取Class对象 
User user1 = new User();//这一new 产生一个user对象,一个Class对象。
Class userClass = user1.getClass();
System.out.println("方式一获取的class: "+ userClass);

//第二种方式获取Class对象
Class userClass2 = User.class;
//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
System.out.println("方式二获取的class: "+ userClass2);
System.out.println("方式一和方式二获取结果比较:"+ (userClass == userClass2));

//第三种方式获取Class对象
//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
Class userClass3 = Class.forName("reflect.entity.User");
System.out.println("方式三获取的class: "+ userClass3);
System.out.println("方式二和方式三获取结果比较:"+ (userClass2 == userClass3));

打印结果为:

方式一获取的class: class reflect.entity.User
方式二获取的class: class reflect.entity.User
方式一和方式二获取结果比较:true
方式三获取的class: class reflect.entity.User
方式二和方式三获取结果比较:true

class对象内容:

区别:

三种方式常用第三种,

第一种:对象都有了还要反射干什么。可以通过一些放射方法来操作这个对象。

第二种:需要导入类的包,依赖太强,不导包就抛编译错误。

第三种:一个字符串可以传入也可写在配置文件中等多种方法。

2. 属性Field

2.1 获取属性

方法

功能

getFields()

获取所有public字段,包括父类字段

getDeclaredFields()

获取所有字段,public和protected和private,但是不包括父类字段

public Field getField(String name)

根据字段名称获取public字段

public Field getDeclaredField(String name)

根据字段名称获取自身的单个字段

代码dome

/**
* 获取属性
*/
Class userClass3 = Class.forName("reflect.entity.User");
Field[] publicFields = userClass3.getFields();
Field[] allSelfFields = userClass3.getDeclaredFields();

System.out.println("获取所有public字段,包括父类字段");
for (Field f:publicFields) {
    System.out.println("getFields---"+f.getName());
 }

System.out.println("获取所有字段,public和protected和private,但是不包括父类字段");
for (Field f:allSelfFields) {
    System.out.println("getDeclaredFields---"+f.getName());
}

System.out.println();
System.out.println("根据名称获取单个public字段,包括父类字段");
Field publicFieldByName = userClass3.getField("name");
System.out.println("getField  by name---"+publicFieldByName.getName());

System.out.println();
System.out.println("根据名称获取自身单个字段,public和protected和private,但是不包括父类字段");
Field selfFieldByName = userClass3.getDeclaredField("passWord");
System.out.println("getDeclaredField  by name---"+selfFieldByName.getName());

结果打印

:可见getFields可以获取到父类中的public字段,getDeclaredFields可以获取自身的所有字段。

获取所有public字段,包括父类字段
getFields---userId
getFields---name

获取所有字段,public和protected和private,但是不包括父类字段
getDeclaredFields---userName
getDeclaredFields---passWord
getDeclaredFields---userId
getDeclaredFields---phone
getDeclaredFields---ipAddress

根据名称获取单个public字段,包括父类字段
getField  by name---name

根据名称获取自身单个字段,public和protected和private,但是不包括父类字段
getDeclaredField  by name---passWord

2.2 属性(Field)相关方法

方法名

作用

public int getModifiers()

得到属性的修饰符(0:没有修饰符(default);1:public;2:private;4:protected)

public String getName()

得到属性的名称。

public boolean isAccessible()

判断此属性是否被外部访问

public void setAccessible(Boolean flag)

设置一个属性是否可被外部访问。

public String toString()

返回此Field类的信息

public Object get(Object obj)

得到一个对象中属性的具体内容,必须要声明一个对象

public void set(Object obj,Object value)t

设置指定对象中属性的具体内容,必须要声明一个对象

代码demo

        /**
         * 属性赋值
         */
        Class userClass3 = Class.forName("reflect.entity.User");
        Field[] allSelfFields = userClass3.getDeclaredFields();
        User setUser = new User();

        System.out.println("获取所有public字段,包括父类字段");
        int i =1;
        for (Field f:allSelfFields) {
            System.out.println("属性名称为: "+f.getName()+";是否可被访问:"+f.isAccessible()+";修饰符为: "+f.getModifiers());
            // 设为可访问
            f.setAccessible(true);
            // 赋值
            f.set(setUser,"a"+Integer.toString(i));
            // 获取属性的值
            System.out.println("属性名称为:"+f.getName()+",属性值为: "+f.get(setUser));
            ++i;
        }
        System.out.println(setUser.toString());

结果打印

name, age, sex字段为父类非public字段,所以没有被访问的,也就没被赋值。

获取所有public字段,包括父类字段
属性名称为: userName;是否可被访问:false;修饰符为: 2
属性名称为:userName,属性值为: a1
属性名称为: passWord;是否可被访问:false;修饰符为: 2
属性名称为:passWord,属性值为: a2
属性名称为: userId;是否可被访问:false;修饰符为: 1
属性名称为:userId,属性值为: a3
属性名称为: phone;是否可被访问:false;修饰符为: 4
属性名称为:phone,属性值为: a4
属性名称为: ipAddress;是否可被访问:false;修饰符为: 0
属性名称为:ipAddress,属性值为: a5
User{userName='a1', passWord='a2', userId='a3', phone='a4', ipAddress='a5', name='null', age=null, sex=}

3. 方法

3.1 获取方法

方法名

作用

Method[] getMethods()

获取所有public方法,包括父类public方法

Method[] getDeclaredMethods()

获取自身声明的方法,包括私有方法但不包括父类字段

Constructor<?>[] getConstructors()

获取构造函数

Method getMethod(String name, Class<?>... parameterTypes)

根据方法名称获取所有public方法,包括父类public方法

Method getDeclaredMethod(String name, Class<?>... parameterTypes)

根据方法名称获取自身声明的方法,包括私有方法但不包括父类字段

代码dome

Class userClass3 = Class.forName("reflect.entity.User");
System.out.println("获取所有public方法,包括父类public方法");
Method[]  methods = userClass3.getMethods();
for (Method m:methods) {
    System.out.println(m.getName());
}
System.out.println("获取类中声明public方法,但是不包括父类字段");
Method[] declaredMethods = userClass3.getDeclaredMethods();
for (Method m:declaredMethods) {
    System.out.println(m.getName());
}

System.out.println("获取构造函数");
Constructor[]  declaredConstructors = userClass3.getConstructors();
for (Constructor m:declaredConstructors) {
    System.out.println(m.getName());
}

System.out.println("根据方法名称获取单个方法");
Method getUserPublicMethod = userClass3.getMethod("getUserPublicMethod", String.class);
System.out.println("getMethod---"+getUserPublicMethod.getName());
Method getUserPrivateMethod = userClass3.getDeclaredMethod("getUserPrivateMethod", String.class);
System.out.println("getDeclaredMethod---"+getUserPrivateMethod.getName());

结果打印

获取所有public方法,包括父类public方法
getUserPublicMethod
toString
getPersonPublicMethod
wait
wait
wait
equals
hashCode
getClass
notify
notifyAll
获取public方法,但是不包括父类字段
getUserPublicMethod
getUserPrivateMethod
toString
获取构造函数
reflect.entity.User
reflect.entity.User
根据方法名称获取单个方法
getMethod---getUserPublicMethod
getDeclaredMethod---getUserPrivateMethod

3.2 调用方法

通过调用public Object invoke(Object obj, Object... args)来实现反射调用方法,但对于私有方法需要将私有方法访问性进行修改;

代码demo

Class userClass3 = Class.forName("reflect.entity.User");
Method getUserPublicMethod = userClass3.getDeclaredMethod("getUserPublicMethod", String.class);
System.out.print("调用方法为: "+getUserPublicMethod.getName());
getUserPublicMethod.invoke(userClass3.newInstance(), "调用公有方法");

Method getUserPrivateMethod = userClass3.getDeclaredMethod("getUserPrivateMethod", String.class);
System.out.print("调用方法为: "+getUserPrivateMethod.getName());
getUserPrivateMethod.setAccessible(true);
getUserPrivateMethod.invoke(userClass3.newInstance(), "调用私有方法");

结果打印

getDeclaredMethod---getUserPublicMethod
子类公有方法调用,参数为: 调用公有方法
getDeclaredMethod---getUserPrivateMethod
子类私有方法调用,参数为: 调用私有方法

4. 其他操作

方法名

作用

Class<? super T> getSuperclass()

获取父类

5. 反射的原理

6. 代码结构

Person

package reflect.entity;

public class Person {

    public String name;
    protected Integer age;
    char sex;
    private String address;



    public void getPersonPublicMethod(String param){
        System.out.println("父类共有方法,参数为:"+param);
    }

    private void getPersonPrivateMethod(String param){
        System.out.println("父类私有方法,参数为:"+param);
    }
    
}

User

package reflect.entity;

public class User extends Person{
    private String userName;
    private String passWord;

    public String userId;

    protected String phone;
    String ipAddress;

    public User() {}
    public User(String userName, String passWord) {
        this.userName = userName;
        this.passWord = passWord;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", passWord='" + passWord + '\'' +
                ", userId='" + userId + '\'' +
                ", phone='" + phone + '\'' +
                ", ipAddress='" + ipAddress + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }

    public void getUserPublicMethod(String param){
        System.out.println("子类公有方法调用,参数为: "+param);
    }

    private void getUserPrivateMethod(String param){
        System.out.println("子类私有方法调用,参数为: "+param);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值