Java学习--反射与类加载机制

一、反射机制
定义:在运行期间,可以获取对象的类型、类型的方法、类型的属性、类型构造方法等。
简单来说,反射机制指的是程序在运行时能够获取自身的信息。在Java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息。
1.获取对象的类型(类对象)
有三种方法:
方法1:Object .getClass();
方法2: Class.forName(“类名”);
方法3: 类名.class.

public class User {

    private String name;
    private int age;

    public User(int a) {

    }

    public User() {

    }

    private void m1() {
        System.out.println("m1被执行");

    }
    public void m1(int a) {
        System.out.println("m1(int a)被执行");
    }
    public void m1(int a, int b) {
        System.out.println("m1(int a, int b)被执行");
    }

    public void m1(char a, String b) {

    }

    @Resource
    public void m2() {

    }
    private void m3() {

    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
// 方法1
 System.out.println(new User().getClass());
// 方法2
 System.out.println(Class.forName("reflect.User"));
// 方法3
 System.out.println(User.class);
 // 注:这个类型信息在jvm仍表现为一个对象,而且只有一份
System.out.println(new User().getClass() == Class.forName("reflect.User"));

2.类对象的功能
a.用反射的方式创建对象
正常创建对象: new 类名();
反射创建对象: 类对象.newInstance();

// 反射创建对象, newInstance() 限制1: 要求对象有无参构造  限制2: 构造方法不能私有
        User user = User.class.newInstance();
        System.out.println(user);

b.获取方法信息
类对象.getMethods(); // 获取所有公共方法(public),包括继承的
类对象.getMethod(方法名, 参数类型); // 找公共方法, 包括继承的
类对象.getDeclaredMethods(); // 获取本类的所有方法不包括继承
类对象.getDeclaredMethod(方法名, 参数类型); // 找本类的,不包括继承的

 // 获取方法信息
        Method[] methods = User.class.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

c.获取属性信息
类对象.getFields(); // 获取所有公共属性包括继承的
类对象.getDeclaredFields(); // 获取本类所有属性不包括继承的
类对象.getField(“属性名”);

 Field[] fields = User.class.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

d.获取构造方法(了解)
类对象.getConstructors(); // 获取所有公共的构造方法
类对象.getDeclaredConstructors(); // 获取本类所有构造方法
类对象.getConstructor(int.class); // 获取int参数类型的构造

f.反射调用方法
正常调用方式: 对象.方法名(参数);
反射调用方式: 方法.invoke(对象, 参数);
优势:可以调用私有方法,突破正常方法的限制, 经常用在开源框架中;缺点:调用复杂,效率低。
如果方法为私有,先使用setAccessible(true)设置。
如果构造方法为私有,先使用getDeclaredConstructor(),再使用setAccessible(true)设置,最后newInstance();。

// 方法.invoke(对象, 参数);
        Method m1 = User.class.getDeclaredMethod("m1");
        m1.setAccessible(true); // 设置这个方法可以被访问,可以突破访问修饰符的限制
        m1.invoke(u); // 反射调用方法(性能低)

        // 反射调用 public void m1(int a)
        Method m12 = User.class.getDeclaredMethod("m1", int.class);
        m12.invoke(u, 1);

        Method m13 = User.class.getDeclaredMethod("m1", int.class, int.class);
        m13.invoke(u, 4, 5);

        // 调用私有构造
        Constructor<Student> cons = Student.class.getDeclaredConstructor();
        cons.setAccessible(true);
        Student s = cons.newInstance();
        System.out.println(s);

二、类加载机制
类的加载由类加载器完成,类加载器通常由JVM提供,JVM提供的类加载器通常被称为系统类加载器,除此之外,开发者可以通过继承ClassLoader基类来创建自己的类加载器。
通过使用不同的类加载器,可以从不同来源加载 类的二进制数据,一般有如下几种来源:
a.从本地文件系统加载class文件

 // 类加载器, 作用:加载一个不在classpath下的类
        ClassLoader cl = new ClassLoader() {
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                try {
                    FileInputStream in = new FileInputStream("I:\\13\\20181201\\Treasure.class");
                    byte[] bytes = new byte[1024 * 8];
                    int len = in.read(bytes);

                    // 调用父类的方法根据字节数组加载类
                    return defineClass(name, bytes, 0, len);
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        };

b.从jar包中加载class文件(常见的方式)
c.通过网络加载class文件
d.把一个java源文件动态编译,并执行加载。

类加载器无需等到“首次使用”该类时再加载该类,Java虚拟机规范允许系统预先加载某些类。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值