Java反射机制(非常重要!!!)

反射是框架设计的灵魂

(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

1.  反射的概念

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

2.  Class对象

要想了解一个类,必须先要获取到该类的字节码文件对象. 在Java中,每一个字节码文件,被加载到内存后,都存在一个对应的Class类型的对象。

3.  得到Class的几种方式

1.  如果在编写代码时, 知道类的名称, 且类已经存在, 可以通过 包名.类名.class 得到一个类的 类对象

2. 如果拥有类的对象, 可以通过 Class 对象.getClass() 得到一个类的 类对象

3. 如果在编写代码时, 知道类的名称 , 可以通过 Class.forName("包名+类名"),类不存在的时候也可以使用(代码不会报红,只身运行时报错,更适用与动态编程),找不到指定的类会报ClassNotFoundException (重点使用)

得到一个类的 类对象 上述的三种方式, 在调用时, 如果类在内存中不存在, 则会加载到内存 ! 如果类已经在内存中存在, 不 会重复加载, 而是重复利用 !

4.  Constructor 创建对象

常用方法: newInstance(Object... para)

调用这个构造方法, 把对应的对象创建出来 参数: 是一个Object类型可变参数, 传递的参数顺序 必须匹配构造方法中形式参数列表的顺 序!

setAccessible(boolean flag)

如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的方法)

5.  通过class对象 获取一个类的构造方法

1. 通过指定的参数类型, 获取指定的单个构造方法 getConstructor(参数类型的class对象数组)

例如: 构造方法如下: Person(String name,int age)

得到这个构造方法的代码如下:

Constructor c = p.getClass().getConstructor(String.class,int.class);

2. 获取构造方法数组 getConstructors();

3. 获取所有权限的单个构造方法 getDeclaredConstructor(参数类型的class对象数组)

4. 获取所有权限的构造方法数组 getDeclaredConstructors();

package bean;
 
public class Person {
    private int age;
    private String name;
    public String phoneNumber;
 
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                '}';
    }
 
    //私有的构造方法
   private Person(String name) {
       this.age = 18;
       this.name = name;
    }
 
 
    public Person() {
    }
 
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}
package test;
import bean.Person;
import java.lang.reflect.Constructor;
 
public class Test {
    public static void main(String[] args) throws Exception {
        Class<Person> aClass = (Class<Person>) Class.forName("bean.Person");
        //找到无参构造方法
        Constructor<Person> c = aClass.getConstructor();
        //使用无参构造方法,创建对象
        Person p = c.newInstance();
        System.out.println(p);
 
        //找到包含String name 和 int age 的构造方法
        Constructor<Person> c1 = aClass.getConstructor(int.class,String.class);
        //使用全参数的构造方法,创建对象
        Person p1 = c1.newInstance( 18,"李伟");
        System.out.println(p1);
 
        //获得所有权限的构造方法
        Constructor<Person> d = aClass.getDeclaredConstructor(String.class);
        //忽略权限检查
        d.setAccessible(true);
        Person p2 = d.newInstance("刘洋");
        System.out.println(p2);
        System.out.println("getDeclaredConstructors方法能获得所有权限的构造函数");
        Constructor<?>[] gdc = aClass.getDeclaredConstructors();
        for (Constructor<?> gd : gdc) {
            System.out.println(gd);
        }
        System.out.println("getConstructors方法只能得到public方法修饰的构造函数");
        Constructor<?>[] gdc1 = aClass.getConstructors();
        for (Constructor<?> gd : gdc1) {
            System.out.println(gd);
        }
 
    }
}

输出结果:

 6.   获取Method

通过class对象 获取一个类的方法

1. getMethod(String methodName , class.. clss)

根据参数列表的类型和方法名, 得到一个方法(public修饰的)

2. getMethods();

得到一个类的所有方法 (public修饰的)

3. getDeclaredMethod(String methodName , class.. clss)

根据参数列表的类型和方法名, 得到一个方法(除继承以外所有的:包含私有, 共有, 保护, 默认)

4. getDeclaredMethods();

得到一个类的所有方法 (除继承以外所有的:包含私有, 共有, 保护, 默认)

Method 执行方法

 invoke(Object o,Object... para) :

调用方法 ,

参数1. 要调用方法的对象 参数

2. 要传递的参数列表

示例:

使用上面的person类

//加载类
        Class<Person> aClass = (Class<Person>) Class.forName("bean.Person");
        //获取类中的构造方法
        Constructor<Person> c = aClass.getConstructor();
        //创建对象
        Person person = c.newInstance();
        //获取类的方法
        Method setName = aClass.getMethod("setName", String.class);
        //获取所有权限的方法
        Method setAge = aClass.getDeclaredMethod("setAge", int.class);
        //忽略访问权限检查
        setAge.setAccessible(true);
        //参数1. 哪个对象要执行setName方法
        //参数2. 调用方法时传递的产生 0-n
        setName.invoke(person, "张三");
        setAge.invoke(person, 18);
        System.out.println(person);

 

7.  获取Field  通过class对象 获取一个类的属性

1. getDeclaredField(String filedName)  根据属性的名称, 获取一个属性对象 (所有属性)

2. getDeclaredFields()                           获取所有属性

3. getField(String filedName)                根据属性的名称, 获取一个属性对象 (public属性)

4. getFields()                                         获取所有属性 (public)

Field 属性的对象类型

常用方法:

1. get(Object o )             参数: 要获取属性的对象 获取指定对象的此属性值

2. set(Object o , Object value)

参数1. 要设置属性值的 对象

参数2. 要设置的值 设置指定对象的属性的值

3. getName()                  获取属性的名称

4. setAccessible(boolean flag)

如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的属性)

     //加载类
        Class c = Class.forName("bean.Person");
        Constructor ct = c.getConstructor();
        
        Object o = ct.newInstance();
        Field phoneNumber = c.getField("phoneNumber");
        phoneNumber.set(o, "13843838438");
 
 
        Field name = c.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o, "张三");
        System.out.println(o);

7.  利用反射获取注解信息(ORM框架的实现原理)

获取类/属性/方法的全部注解对象

Annotation[] as = Class/Field/Method.getAnnotations();
for (Annotation a : as) {
System.out.println(a);
}

 根据类型获取类/属性/方法的注解对象

注解类型 对象名 = (注解类型) c.getAnnotation(注解类型.class);

示例:

包结构

package demo;
 
import java.lang.annotation.*;
 
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.TYPE})
@Documented
public @interface ColumnAnnotation {
    /**
     * 描述列名
     * @return
     */
    String columnName();
 
    /**
     * 描述类型
     * @return
     */
    String type();
 
    /**
     * 描述数据的长度
     * @return
     */
    String length();
}

 

package demo;
 
import java.lang.annotation.*;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface TableAnnotation {
    /**
     * 用于描述表格名称
     * @return
     */
    String value();
}
package demo;
import java.util.Objects;
//@ColumnAnnotation(columnName = "aa",type = "aa",length = "aa")
@TableAnnotation("test_book")
public class Book {
    @ColumnAnnotation(columnName = "id",type = "int",length = "11")
    private int id;
    @ColumnAnnotation(columnName = "name",type = "varchar",length = "20")
    private String name;
    @ColumnAnnotation(columnName = "info",type = "varchar",length = "500")
    private String info;
 
    public Book() {
    }
 
    public Book(int id, String name, String info) {
        this.id = id;
        this.name = name;
        this.info = info;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return id == book.id &&
                Objects.equals(name, book.name) &&
                Objects.equals(info, book.info);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(id, name, info);
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getInfo() {
        return info;
    }
 
    public void setInfo(String info) {
        this.info = info;
    }
}
package demo;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
 
public class Demo {
    public static void main(String[] args) throws Exception {
        Class c = Class.forName("demo.Book");
        //获取book类上面的所有注解  获取一组注解
        Annotation[] as = c.getAnnotations();
        for (Annotation a : as) {
            System.out.println(a);
        }
        //通过注解名称称获取值
        TableAnnotation annotation = (TableAnnotation) c.getAnnotation(TableAnnotation.class);
        //注解的名称
        System.out.println(annotation);
        //获取到注解的value值
        String value = annotation.value();
        System.out.println(value);
        //获取到到所有属性
        Field[] fs = c.getDeclaredFields();
        for (Field f : fs) {
            ColumnAnnotation ca = f.getAnnotation(ColumnAnnotation.class);
            System.out.println(f.getName()+"属性,对应数据库的字段"+ca.columnName()+",数据类型"+ca.type()+",数据的长度"+ca.length());
 
 
        }
 
    }
}

运行结果: 

 转载:AUTO_K的博客_CSDN博客-学习笔记总结,springMVC,react学习笔记领域博主

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值