Java-反射

在运行中允许java加载类的结构,创建对象,得到其属性和方法并执行方法。
这个流程与正常流程相反,是一种动态编程。

类加载器

BootStrapClassLoader
引导启动类加载器 是通过C++语言编写的,它用来加载JAVA_HOME/lib下的类库
ExtensionClassLoader
扩展类加载器 通过Java语言编写,用来加载JAVA_HOME/lib/ext下的类库
App ClassLoader
应用类加载器 用来加载classpath路径下的JAVA_HOME下的jar和class文件

双亲委派模型

当子加载器收到了一个类加载的请求,子加载器不会直接去加载这个类,而是将此请求上抛给父加载器由父加载器去加载。因此所有都应该传递到最顶层的启动类加载器,只有父加载器反馈自己无法完成加载这个类的请求,子类加载器才会尝试去加载。双亲委派的好处是避免有些类被重复加载。

类的类型

一个类是如何加载到内存的过程,java文件通过编译器编程.class的字节码文件,文件被jvm加载到内存中后。例如Person.class在内存中是一个class类型的person对象。此时可以用Class c = Person.class获取类 的类型。
当使用Person person = new Person();时,在堆中开辟一个空间存储一个Person类型的对象。

得到Class的几种方式

  1. 如果在编写代码时, 指导类的名称, 且类已经存在, 可以通过
    包名.类名.class 得到一个类的 类对象
  2. 如果拥有类的对象, 可以通过
    Class 对象.getClass() 得到一个类的 类对象
  3. 如果在编写代码时, 知道类的名称 , 可以通过
    Class.forName(包名+类名): 得到一个类的 类对象

在调用时, 如果类在内存中不存在, 则会加载到内存 。 如果类已经在内存中存在, 不会重复加载, 而是重复利用 。

反射中的构造方法
通过private修饰的无参构造方法创建对象

public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.加载类
        Class<Person> pClass = (Class<Person>) Class.forName("com.java.Demo2.Person");
        //2.获取所欲权限的无参构造方法
        Constructor<Person> c1= pClass.getDeclaredConstructor();
        //3.设置访问权限为true
        c1.setAccessible(true);
        //4.通过无参构造方法创建对象
        Person p1 = c1.newInstance();
        System.out.println(p1);
    }
}

通过private修饰的有参构造方法创建对象

public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        //1.加载类
        Class<Person> pClass = (Class<Person>) Class.forName("com.yuzhao.Demo2.Person");
        //2.获得全部权限的有参构造方法
        Constructor<Person> c2 = pClass.getDeclaredConstructor(String.class,int.class);
        //3.设置访问权限为true
        c2.setAccessible(true);
        //4.通过有参构造方法创建对象
        Person p2 = c2.newInstance("钱富贵",20);
        System.out.println(p2);
    }
}

反射中的方法

public class Person {
    private String name;
    private int age;

    private Person(){

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

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

    public String getName() {
        return name;
    }

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

    private int getAge() {
        return age;
    }

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

public class Demo2 {
    public static void main(String[] args) throws Exception {
        Class pClass =  Class.forName("com.java.Demo2.Person");
        Constructor c1 = pClass.getDeclaredConstructor();
        c1.setAccessible(true);
        Object o = c1.newInstance();
        //获取setname()方法
        Method setName = pClass.getMethod("setName",String.class);
        //获取setAge()方法
        Method setAge = pClass.getDeclaredMethod("setAge",int.class);
        //忽略权限检查
        setAge.setAccessible(true);
        //执行setname()方法 参数1.执行此方法的对象。参数2。调用方法时传递的参数。
        setName.invoke(o,"钱富贵");
        //执行setAge()方法
        setAge.invoke(o,18);
        System.out.println(o.toString());
        
    }
}

反射中的属性

public class Demo3 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        Class<Person> pClass = (Class<Person>) Class.forName("com.yuzhao.Demo2.Person");
        Constructor<Person> c1 = pClass.getDeclaredConstructor();
        c1.setAccessible(true);
        Object o = c1.newInstance();
        //获取对象中的属性
        Field phoneNo = pClass.getField("phoneNo");
        //修改属性值
        phoneNo.set(o,"1326921XXXX");
        System.out.println(o.toString());

        Field name = pClass.getDeclaredField("name");

        name.setAccessible(true);
        name.set(o,"钱长贵");
        System.out.println(o.toString());
    }
}

反射与注解
ORM(object relational mapping)

public class Demo4 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c = Class.forName("com.java.Demo2.Book");
        //获取类上的注解
        TableAnnotation tableAnnotation = (TableAnnotation) c.getAnnotation(TableAnnotation.class);
        String value = tableAnnotation.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()+"\t数据类型:"+ca.type()+"\t数据长度:"+ca.length());
        }

    }
}

@TableAnnotation("test_Book")
public class Book {
    @ColumnAnnotation(columnName="id",type="int",length="11")
    private int id;
    @ColumnAnnotation(columnName="name",type="varchar",length="50")
    private String name;
    @ColumnAnnotation(columnName="info",type="varchar",length="1000")
    private String info;

    public Book() {
    }

    @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;
    }
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented

public @interface TableAnnotation {
    /**
     * 用于标注类对应的表格名称
     * @return
     */
    String value();
}

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnAnnotation {
    /**
     * 描述列名
     * @return
     */
    String columnName();

    /**
     * 描述类型
     * @return
     */
    String type();

    /**
     * 描述长度
     * @return
     */
    String length();

}

内省

Introspector
基于反射 , java所提供的一套应用到JavaBean的API
一个定义在包中的类 , 拥有无参构造器,所有属性私有, 所有属性提供get/set方法,并实现了序列化接口这种类, 我们称其为 bean类

如果属性是boolean类型,set方法要写成set+属性名称 首字母大写,get方法要写成is+属性名称 首字母大写()
通过内省获取类中的方法

public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, IntrospectionException {
        Class<Express> expressClass = (Class<Express>) Class.forName("com.java.introspector.Express");
        BeanInfo bi = Introspector.getBeanInfo(expressClass);
        PropertyDescriptor[] pds = bi.getPropertyDescriptors();
        for (PropertyDescriptor p : pds){
            Method get = p.getReadMethod();
            Method set = p.getWriteMethod();
            System.out.println(get);
            System.out.println(set);
            System.out.println(p.getName());
            System.out.println(p.getPropertyType());
        }

    }

}

public class Express implements Serializable {
    private String number;
    private String name;
    private String phoneNo;
    private String address;



    public Express() {
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

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

    public String getPhoneNo() {
        return phoneNo;
    }

    public void setPhoneNo(String phoneNo) {
        this.phoneNo = phoneNo;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Express{" +
                "number='" + number + '\'' +
                ", name='" + name + '\'' +
                ", phoneNo='" + phoneNo + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值