day52

2.反射

(1)反射定义

程序中的反射指程序运行状态中,

1、对于给定的一个类(Class)对象,可以获得这个类(Class)对象的所有属性和方法;

2、对于给定的一个对象(new XXXClassName<? extends Object>),都能够调用它的任意一

个属性和方法。

这种动态获取类的内容以及动态调用对象的方法和获取属性的机制,就叫做Java反射机制

(2)反射初识

        Class<User> clazz = User.class;

        //获取类对象对应的属性和方法

        //获取一个对象实例

        User user = clazz.newInstance();

(3)为何用反射

实例化一个User()对象,不使用反射,如果想再实例化其他对象比如new Person(),那么

就需要修改源代码,并重新编译。使用反射后就不需要修改源代码只需要灵活改动类描述就

可以了,不需要重新再编译。 如下代码所示

    //类描述,可根据需要实例化的描述而改动

    String className = "com.tledu.pojo.User";

    //使用反射中API创建对象

    Class.forName(className).newInstance();

(4)反射的优缺点

优点:

增加程序的灵活性,避免固有逻辑写死到程序中

代码相对简洁,可以提高程序的复用性

缺点:

相比于直接调用反射有比较大的性能销毁

内部暴露和安全隐患

使用反射的方式获取对象,可以看出代码灵活了很多而且不需要改动创建返回对象的源码。

b、性能测试

为什么这么慢呢?(分别查看forName()方法和newIntance()方法源码分析)

1、调用了native方法

2、每次调用newInstance()方法都会做安全检查,比较耗时

(5)、反射的操作

 

a、获取类对象的四种方式

//获取类对象的四种方式

Class<User> clazz1 = User.class;

Class<?> clazz2 = Class.forName("com.tledu.mjw.User");

Class<? extends User> clazz3 = new User().getClass();

Class<?> clazz4 = Demo3.class.getClassLoader().loadClass("com.tledu.mjw.User");

b、类中基本信息的获取

System.out.println(clazz1.getClassLoader());

System.out.println(clazz1.getSuperclass());

System.out.println(clazz1.getPackage());

System.out.println(clazz1.getModifiers()); //获取类的修饰符

System.out.println(clazz1.getName());

System.out.println(clazz1.getSimpleName());

System.out.println(clazz1.getInterfaces().length);//获取类实现的所有接口

System.out.println(clazz1.getAnnotations().length);

c、类中字段的操作

测试方法调用

public static void main(String[] args) throws Exception {

    Class<User> userClass = User.class;

    User user = userClass.newInstance();

    //getFields()获取的是本类及父类中的公共属性

    Field[] fields = userClass.getFields();

    for (Field field : fields) {

        System.out.println(field.getModifiers() + " " + field.getName());

    }

    System.out.println("---------------");

    //getDeclaredFields()获取本类中的所有属性

    Field[] fields2 = userClass.getDeclaredFields();

    for (Field field : fields2) {

        System.out.println(field.getModifiers() + " " + field.getName());

    }

    System.out.println("---------------");

    //获取name字段对应的field

    Field nameField = userClass.getDeclaredField("name");

    //如果需要修改私有属性信息那么我们要放开权限

    nameField.setAccessible(true);

    nameField.set(user,"天亮教育");

    System.out.println(nameField.get(user));

    //System.out.println(user.getName());

    System.out.println("---------------");

    //如何对静态的属性赋值

    Field addressField = userClass.getDeclaredField("address");

    addressField.set(null,"Jack");

    System.out.println(addressField.get(null));

    //System.out.println(User.address);

}

d、类中方法的操作

在User类中将eat方法改为私有的,并添加静态方法say

private void eat(){

    System.out.println("---eat---");

}

public static void say(String msg){

    System.out.println(msg);

}

在Person类中添加共有的fn1()方法和私有的fn2()方法

public void fn1(){}

private void fn2(){}

测试方法调用

public static void main(String[] args) throws Exception {

    Class<User> userClass = User.class;

    User user = userClass.newInstance();

    //获取本类及父类中的公共方法

    Method[] methods1 = userClass.getMethods();

    for (Method method : methods1) {

        System.out.println(method.getModifiers() + " " + method.getName());

    }

    System.out.println("--------------");

    //获取本类中所有的方法包括私有

    Method[] methods2 = userClass.getDeclaredMethods();

    for (Method method : methods2) {

        System.out.println(method.getModifiers() + " " + method.getName());

    }

    System.out.println("--------------");

    //调用方法执行

    Method eatMethod = userClass.getDeclaredMethod("eat");

    //调用私有方法时要先开放权限

    eatMethod.setAccessible(true);

    eatMethod.invoke(user);

    System.out.println("--------------");

    //调用静态的方法

    Method sayMethod = userClass.getDeclaredMethod("say",String.class);

    sayMethod.invoke(null,"你好");

}

e、类中构造器的操作

在User中添加如下构造方法

public User() {

}

public User(String name) {

    this.name = name;

}

private User(String name,String sex) {

    this.name = name;

    this.sex = sex;

}

通过反射操作User中的构造方

public static void main(String[] args) throws Exception {

    Class<User> userClass = User.class;

    //获取公共的构造器

    Constructor<?>[] constructors = userClass.getConstructors();

    for (Constructor<?> constructor : constructors) {

        System.out.println(constructor.getModifiers() + " " + constructor.getName());

    }

    System.out.println("------------------");

    //获取所有的构造器

    Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();

    for (Constructor<?> declaredConstructor : declaredConstructors) {

        System.out.println(declaredConstructor.getModifiers() + "  " + declaredConstructor.getName());

    }

    //1、直接通过newInstance创建对象

    User user = userClass.newInstance();

    //2、获取对应的Constructor对象获取实例

    Constructor<User> constructor = userClass.getDeclaredConstructor(String.class, String.class);

    //操作私有的构造器要先打开权限

    constructor.setAccessible(true);

    User user1 = constructor.newInstance("乔森", "男");

}

  1. 反射破局单例

单例模式

public class PersonSingle {

    private static PersonSingle instance = null;

    private PersonSingle(){}

    public static PersonSingle getInstance(){

        if(instance == null){

            instance = new PersonSingle();

        }

        return instance;

    }

}

测试单例、通过反射可以调用私有构造

public static void main(String[] args) throws Exception {

    PersonSingle instance1 = PersonSingle.getInstance();

    PersonSingle instance2 = PersonSingle.getInstance();

    PersonSingle instance3 = PersonSingle.getInstance();

    System.out.println(instance1);

    System.out.println(instance2);

    System.out.println(instance3);

    System.out.println("---------------------");

    Class<PersonSingle> personSingleClass = PersonSingle.class;

    Constructor<PersonSingle> declaredConstructor = personSingleClass.getDeclaredConstructor();

    declaredConstructor.setAccessible(true);

    System.out.println(declaredConstructor.newInstance());

}

改进单例如下

private PersonSingle(){

    if(instance != null){

        throw new RuntimeException("实例已经存在不允许再创建")

    }

}

  1. 反射使用场景

1、jdbc封装

2、SpringIOC

3、JdbcTemplate

4、Mybatis

...................

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值