Java反射机制

在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制

类加载机制

反射机制

 

获取Class实例的三种常见方式

  1. Class class1=类名.class;(这种情况写死类名,体现不出反射的动态性,一般不推荐)
  2. Class class2=对象.getClass();(联想equals()方法重写中的判断)
  3. Class class3=Class.forName(String classPath);(最常用,体现反射的动态性)

Class类的理解

Class的实例对应着加载到内存中的一个运行时类。 该类作为Class类的一个对象,我们可以根据Class的实例来调用运行时类的结构。

创建Class对应运行时类对象的通用方法

class.newInstance();

  • 必须有空参构造器
  • 权限修饰符的权限要够。通常设为public

Class类的常用方法

获取属性

getFields() -所有可访问的公共字段
getDeclaredFields() -所有字段
getField(String name) -返回一个特定的公共Field对象

Field.getName()-显示为该类的属性名字,前面没有“class”修饰

获取方法

getMethods()-所有公共方法,包括从超类和超接口继承的声明
getDeclaredMethods() -所有方法,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法
getMethod(String name, Class[] parameterTypes)-返回一个方法对象

Method.getName()-显示为该类的方法名字,前面没有“class”修饰

获取构造器

getConstructor(Class[] parameterTypes)-返回一个构造方法对象

 调用运行时类结构

定义的Person类:

public class Person extends Creature<String>implements Comparable<String>,MyInterface{
    private String name;
     int age;
     public int id;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                '}';
    }

    public Person(){

    }
private Person(String name){
        this.name=name;
}
Person(String name,int age){
        this.name=name;
        this.age=age;
}
private String show(String nation){
    System.out.println("我的国籍是:"+nation);
    return nation;
}
public String display(String interests){
        return interests;

}
    @Override
    public void info() {
        System.out.println("为人");
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }
    private static void showDesc(){
        System.out.println("你好可爱!");
    }
}

反射测试类:

//调用运行时类中指定的结构:属性、方法、构造器
public class ReflectionTest {
    @Test
    public void testField() throws Exception {
        Class pClass = Person.class;
        Person p = (Person) pClass.newInstance();
        //获取指定的属性:要求运行时类中的属性声明为public,通常不采用此方法。
        Field id = pClass.getField("id");
/*
设置当前属性值
set():参数1:指明哪个对象的属性   参数2:设置此属性值
*/
        id.set(p, 1001);
/*
设置当前属性值
set():参数1:获取哪个对象的属性
*/
        int i = (int) id.get(p);
        System.out.println(i);
    }
    //如何操作运行时类中的指定的属性
    @Test
    public void testField1() throws Exception {
        Class pClass = Person.class;
        Person p = (Person) pClass.newInstance();
        Field name = pClass.getDeclaredField("name");
        //保证当前属性是可访问的;
        //name.setAccessible(true);
        name.set(p,"Sam");
        System.out.println(name.get(p));//会报错!访问权限只能为public和上面方法一样。怎样解决这个问题?
    }
    //如何操作运行时类中的指定的属性
    @Test
    public void testField2() throws Exception {
        Class pClass = Person.class;
        //非静态方法必须要创建运行时类对象
        Person p = (Person) pClass.newInstance();
        //获取指定的方法
        //getDeclaredMethod() 参数1:指明获取的方法的名称  参数2:指明获取方法的形参列表类型
        //invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参。invoke() 方法的返回值即为对应类中调用方法的返回值。
        Method show = pClass.getDeclaredMethod("show", String.class);
        //保证当前属性是可访问的;
        show.setAccessible(true);
        String returnValue = (String)show.invoke(p, "CHN");//同样是权限原因报错!
        System.out.println(returnValue);

        System.out.println("**********如何调用静态方法************");
        Method showDesc = pClass.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        String showD = (String) showDesc.invoke(Person.class);
//        String showD = (String) showDesc.invoke(null);
        System.out.println(showD);//调用的方法无返回值,输出为null
    }

    //如何操作运行时类中的指定的构造器
    //getDeclaredConstructor() 参数:指明获取构造器的形参列表类型。比方法少一个形参,因为构造器和类名同名。
    @Test
    public void testField3() throws Exception {
        Class pClass = Person.class;
        Constructor declaredConstructor = pClass.getDeclaredConstructor(String.class);
        //保证此构造器可访问
        declaredConstructor.setAccessible(true);
        //调用此构造器创建运行时类的对象
        Person p = (Person) declaredConstructor.newInstance("Jerry");
        System.out.println(p);

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值