Java 反射总结

Java 反射总结

概述

Java的反射是指程序在运行期可以拿到一个对象的所有信息。

Java可以通过反射实现一下功能:

  • 创建一个类的对象。
  • 访问对象的成员变量和方法。

在Android中,出于安全考虑,google对系统的某些方法使用@hideprivate修饰,导致不能正常调用该方法,这时可以借助反射进行操作。

Class实例

Class是一个类,里面包含类的所有信息,如:属性、方法、构造函数等。

定义实体类:

public class Person extends People implements Serializable {
    private String name;
    private int age;
    public String address;

    public Person() {
    }

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

    private Person(int age, String address) {
        this.age = age;
        this.address = address;
    }

    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public String setName(String name) {
        this.name = name;
        return "666";
    }

    private String setRealName(String name) {
        this.name = name;
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    private void setAddress(String address) {
        this.address = address;
    }

    public static String getCountry() {
        return "中国";
    }

    public String showDetail() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }

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

获取Class对象

//方式一:通过类名获取
Class<Person> clazz = Person.class;

//方式二:通过对象获取
Person person = new Person();
Class<? extends Person> clazz = person.getClass();

//方式三:通过Class.forName()获取
Class<?> clazz = Class.forName("com.example.myapplication.Person");

instanceof & isInstance() & isAssignableFrom()区别

  • instanceof:是一个关键字,用于判断对象是否为类的实例。
  • isInstance():是Class类中的方法,判断是否为类的实例。
  • isAssignableFrom():是Clas类s中的方法,判断继承关系。
//instanceof
System.out.println(fruit instanceof Fruit);//true
System.out.println(apple instanceof Apple);//true
System.out.println(apple instanceof Fruit);//true
//        System.out.println("hello" instanceof Fruit);//报错

//isInstance
System.out.println(Fruit.class.isInstance(fruit));//true
System.out.println(Apple.class.isInstance(apple));//true
System.out.println(Fruit.class.isInstance(apple));//true
System.out.println(Fruit.class.isInstance("hello"));//false

//isAssignableFrom
System.out.println(Fruit.class.isAssignableFrom(Fruit.class));//true
System.out.println(Apple.class.isAssignableFrom(Apple.class));//true
System.out.println(Fruit.class.isAssignableFrom(Apple.class));//true
System.out.println(Fruit.class.isAssignableFrom(String.class));//false

获取Class信息

Class<String> clazz = String.class;

//获取全类名
String name = clazz.getName();
System.out.println(name); //java.lang.String

//获取全类名
String canonicalName = clazz.getCanonicalName();
System.out.println(canonicalName); //java.lang.String

//获取类名
String simpleName = clazz.getSimpleName();
System.out.println(simpleName); //String

//获取报名
Package pkg = clazz.getPackage();
System.out.println(pkg.getName()); //java.lang

//获取父类
Class<? super String> superclass = clazz.getSuperclass();
System.out.println(superclass.getName()); //java.lang.Object

//获取当前实现的接口
Class<?>[] interfaces = clazz.getInterfaces();
for (Class i : interfaces) {
    System.out.println(i.getName());
}
/*
        java.io.Serializable
        java.lang.Comparable
        java.lang.CharSequence
         */

通过Class创建对象

//通过Class实例创建实例对象
Person person = clazz.newInstance();

访问构造函数

获取Constructor对象

//获取public构造方法
Constructor[] constructors = clazz.getConstructors();

//获取所有构造方法
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();

//获取指定参数的public构造方法
Constructor constructor = clazz.getConstructor(String.class, int.class);

//获取指定参数的非public构造方法
Constructor constructor = clazz.getDeclaredConstructor(int.class, String.class);

通过构造函数创建对象

Constructor<Person> constructor = Person.class.getConstructor(String.class, int.class, String.class);
Person p = constructor.newInstance("小白", 18, "北京市");

调用方法

获取Method对象

//获取当前类和父类的public方法
Method[] methods = clazz.getMethods();

//获取当前类的所有方法
Method[] methods = clazz.getDeclaredMethods();

//根据方法名和参数Class对象,获取当前类和父类的public方法
Method method = clazz.getMethod("setName", String.class);

//根据方法名和参数Class对象,获取当前类的方法,无限制
Method method = clazz.getDeclaredMethod("setAddress", String.class);

获取Method信息

//获取方法名
String methodName = method.getName();

//获取返回值类型
Class<?> returnType = method.getReturnType();

//获取参数类型
Class<?>[] parameterTypes = method.getParameterTypes();

//获取修饰符
int modifiers = method.getModifiers();

调用普通方法

//获取指定方法
Method method = clazz.getMethod("setName", String.class);
//调用方法并获取返回值
String ret = (String) method.invoke(p, "小红");

调用非public方法

Method method = clazz.getDeclaredMethod("setRealName", String.class);
method.setAccessible(true);
String ret = (String) method.invoke(p, "小花");

调用静态方法

静态方法无需指定实例对象,所以invoke()的第一个参数永远为null。

Method method = clazz.getMethod("getCountry");
String ret = (String) method.invoke(null);

访问字段

获取Field对象

//获取当前类和父类的public属性
Field[] fields = clazz.getFields();

//获取当前类的所有属性
Field[] fields = clazz.getDeclaredFields();

//获取当前类和父类的public属性
Field field = clazz.getField("address");

//获取当前类的属性,无限制
Field field = clazz.getDeclaredField("name");

获取Field信息

//获取字段名
String fieldName = field.getName();
//获取字段类型
Class<?> fieldType = field.getType();
//获取字段修饰符
int fieldModifiers = field.getModifiers();
//是否为private修饰
boolean isPrivate = Modifier.isPrivate(fieldModifiers);

获取字段值

Person p = new Person("小明", 18, "北京市");
Class<? extends Person> clazz = p.getClass();
Field f = clazz.getDeclaredField("name");
f.setAccessible(true);//非public设为true
Object value = f.get(p);
System.out.println(value);//小明

设置字段值

Person person = clazz.newInstance();
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);//非public设置true
name.set(person, "小白");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值