java——反射入门

反射介绍

反射是java中很重要的一个高级特性,在很多框架中都有用到,动态代理也是使用反射来实现的。
通过反射,我们可以在程序运行期间就获得类或对象的所有信息。对于一个类,反射可以获得它的所有属性和方法信息,对于一个对象,我们可以调用它的所有方法和属性,可以理解反射就是对类的解剖

反射的四大核心类

1.Class类

​ Class类在JDK的 java.lang 包下,它是反射的入口。在java中,每一个类都有一个对应的Class对象。这个Class对象用于表示这个类的信息,它就保存在我们javac编译后的**字节码文件(.class)**中,当我们要new一个该类的对象时,JVM的类加载器(ClassLoader)就会把对应的Class对象加载到JVM中(Class对象存放在堆中,这也就是类的加载),然后JVM再根据这个Class对象的信息来创建我们所要的实例对象。

​ 也就是说,我们要知道这个类的所有信息,就需要得到这个Class对象。Class对象也就是Class类的实例对象,所以说Class类是反射的入口,只有获得了这个Class对象,才能进行接下来的操作。但是Class类只存私有构造函数,我们不能直接通过new运算符实例化,对应Class对象只能有JVM创建和加载。当我们获得这个Class对象后,就可以调用Class类中的方法来获得指定的信息。

获取Class对象的三种方式

// 1.字面常量的方式获取Class对象
Class stu = students.class;

/*2. 通过类的路径名来获得Class对象,这就是反射获取Class对象的方法
     Class.forName()需要捕捉一个ClassNotFoundException,因为编译器无法检测传递字符串
     对应的类是否存在
 */
Class stu1 = Class.forName("com.reflect.students");

//3.调用对象的getclass方法(继承自Object类),这个方法需要先new一个对象
students stu2 = new students();
Class stuclass = stu2.getClass();

//上面三种方法获得的对象都是同一个,因为JVM中每个类有且只有一个对应的Class对象

获取构造器

Constructor<?>[]getConstructors()获取所有该类的public构造函数
Constructor<?>[]getDeclaredConstructors()获取该类的所有构造函数
ConstructorgetDeclaredConstructor(Class<?>… parameterTypes)获取单个该类指定的任意构造函数
ConstructorgetConstructor(Class<?>… parameterTypes)获取单个该类指定的public构造函数
public class students extends person{
    public String name;
    private String id;
    public int age;
    static int score;
    public students() {
    }

    public students(String name, String id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }
    private students(int age) {
        this.age = age;
    }

    private students(String name, String id) {
        this.name = name;
        this.id = id;
    }
}
@Test
public void reflect_getConstructor() throws NoSuchMethodException, ClassNotFoundException {
    Class stu = Class.forName("com.reflect.students");
    // Constructor<?>[] getConstructors() 获取所有public的构造函数
    for (Constructor con:stu.getConstructors()) {
        System.out.println(con);
    }
    System.out.println("------------");
    //Constructor<?>[] getDeclaredConstructors() 获取所有的构造函数
    for (Constructor con:stu.getDeclaredConstructors()) {
        System.out.println(con);
    }
    System.out.println("------------");
    // Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取单个指定的构造函数
    System.out.println(stu.getDeclaredConstructor(int.class));
    System.out.println("------------");
    //Constructor<T> getConstructor(Class<?>... parameterTypes) 获取单个指定的public的构造函数
    System.out.println(stu.getConstructor(String.class,String.class,int.class));
}
//-------> 输出
public com.reflect.students(java.lang.String,java.lang.String,int)
public com.reflect.students()
------------
private com.reflect.students(java.lang.String,java.lang.String)
private com.reflect.students(int)
public com.reflect.students(java.lang.String,java.lang.String,int)
public com.reflect.students()
------------
private com.reflect.students(int)
------------
public com.reflect.students(java.lang.String,java.lang.String,int)

获取字段

Field[]getFields()获取所有该类和其所有超类的public字段
FieldgetField(String name)获取该类单个指定的public字段
FieldgetDeclaredField(String name)获取该类单个指定的字段,可以是私有的
Field[]getDeclaredFields()获取该类所有字段
public class person {

    public String name;
    private String id;
}
------------------------------------------------------------------------

public class students extends person{

    public String name;
    private String id;
    public int age;
    static int score;
}
@Test
public void reflect_getFieldNames() throws ClassNotFoundException, NoSuchFieldException {
    Class stu = Class.forName("com.reflect.students");
    // Field[] getFields()
    for (Field f:stu.getFields()) {
        System.out.println(f);
    }
    System.out.println("------------");
    // Field getField(String name)
    System.out.println(stu.getField("age"));

    System.out.println("------------");
    // Field[] getDeclaredFields()
    for (Field f:stu.getDeclaredFields()) {
        System.out.println(f);
    }
    System.out.println("------------");
    System.out.println(stu.getDeclaredField("id"));
}
//-------> 输出
public java.lang.String com.reflect.students.name
public int com.reflect.students.age
    //还返回了父类的公开的name字段
public java.lang.String com.reflect.person.name
------------
public java.lang.String com.reflect.students.name
------------
public java.lang.String com.reflect.students.name
private static java.lang.String com.reflect.students.id
public int com.reflect.students.age
static int com.reflect.students.score
------------
private static java.lang.String com.reflect.students.id

获取方法

Method[]getMethods()获取该类和其所有超类的public方法
MethodgetMethod(String name, Class<?>… parameterTypes)获取该类指定的public方法
Method[]getDeclaredMethods()获取该类的全部方法
MethodgetDeclaredMethod(String name, Class<?>… parameterTypes)获取该类指定的任意方法
public class person {

    public String name;
    private String id;
    public person() {
    }
    private person(String name) {
        this.name = name;
    }

    private String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
-----------------------------------------------------------------------------
public class students extends person{

    public String name;
    private String id;
    public int age;
    static int score;
    public students() {
    }

    public students(String name, String id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }
    private students(int age) {
        this.age = age;
    }

    private students(String name, String id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "students{" +
                "name='" + name + '\'' +
                ", id='" + id + '\'' +
                ", age=" + age +
                '}';
    }
    private void ac(){
        
    }
}
@Test
public void reflect_getMethod() throws ClassNotFoundException, NoSuchMethodException {
    Class stu = Class.forName("com.reflect.students");
    // Method[] getMethods() 获取所有public方法
    for (Method f:stu.getMethods()) {
        System.out.println(f);
    }
    System.out.println("------------");
    //Method getMethod(String name, Class<?>... parameterTypes) 获取单个指定的public方法
    System.out.println(stu.getMethod("getName"));

    System.out.println("------------");
    // Method[] getDeclaredMethods() 获取所有方法
    for (Method f:stu.getDeclaredMethods() ) {
        System.out.println(f);
    }
    System.out.println("------------");
    // Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取单个指定的方法
    System.out.println(stu.getDeclaredMethod("ac"));

}
//-------> 输出
public java.lang.String com.reflect.students.toString()
public java.lang.String com.reflect.students.getName()
public java.lang.String com.reflect.students.getId()
public int com.reflect.students.getAge()
    //父类person
public void com.reflect.person.setName(java.lang.String)
public void com.reflect.person.setId(java.lang.String)
    //object类
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
------------
public java.lang.String com.reflect.students.getName()
------------
public java.lang.String com.reflect.students.toString()
public java.lang.String com.reflect.students.getName()
public java.lang.String com.reflect.students.getId()
private void com.reflect.students.ac()
public int com.reflect.students.getAge()
------------
private void com.reflect.students.ac()

2.Constructot类

通过Constructot类中的newInstance方法 创建实例对象

@Test
public void getnewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class<?> stu = Class.forName("com.reflect.students");
    // 获取所有的构造函数,每一个构造函数都是个Constructor对象
    Constructor[] constructors = stu.getConstructors();
    Constructor<?> declaredConstructor = stu.getDeclaredConstructor();
    System.out.println(constructors[0].getClass().getName());

    /*
            获取无参构造函数实例,在jdk1.9被弃用了
            取而代之的是getDeclaredConstructor().newInstance(),
            先获取对应的构造器对象然后创建实例,没有参数就获取无参构造器
            每一次创建都会有新的实例对象
        */
    students o = (students) stu.newInstance();
    students o1 = (students) stu.getDeclaredConstructor().newInstance();
    System.out.println(o == o1);//false

}

Constructot类中还可以获取构造函数的参数类型,参数个数,注解,修饰符等等,这里就不一一介绍了,主要就是对象的实例化

3.Field类

给字段赋值

@Test
public void getfield() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
    Class<?> stu = Class.forName("com.reflect.students");
	//通过无参构造器创建实例对象
    students o = (students) stu.getDeclaredConstructor().newInstance();
    //获取name字段
    Field field1 = stu.getField("name");
    System.out.println( " " + field1);
    //调用set赋值
    field1.set(o,"ss");
    Object o1 = field1.get(o);
    String name = o.getName();
    System.out.println(o1 + " " + name);
}

4.Method类

调用方法

@Test
public void getMethod() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
    Class<?> stu = Class.forName("com.reflect.students");

    students o = (students) stu.getDeclaredConstructor().newInstance();
    Method setAge = stu.getMethod("setAge", int.class);
    //调用invoke运行setAge方法,传入对象和指定的参数
    setAge.invoke(o,10);

    System.out.println(o.getAge());

}

同样Method类中也有一些获取方法修饰符,参数,返回类型等一系列方法

setAccessible

对于私有或者默认修饰的方法和成员变量默认是无法进行调用方法和修改查询变量的值的

通过setAccessible修改权限进行访问

@Test
public void setA() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException, InstantiationException, IllegalAccessException {
    Class<?> stu = Class.forName("com.reflect.students");

    students o = (students) stu.getDeclaredConstructor().newInstance();
    Field id = stu.getDeclaredField("id");

    id.setAccessible(true);
    id.set(o,"sss");

    System.out.println(id.get(o));
}

Method 的用法一样

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值