java反射机制

资料视频:韩顺平-反射专题
在这里插入图片描述

OCP:开闭原则(设计模式)
对扩展开放,对修改是关闭的
对象类:

public class Cat {
    private String name="asd";
    public int age=10;

    public Cat() {
    }

    public Cat(String name) {
        this.name = name;
    }

    public void hi(){
        System.out.println("hi~~~");
    }
    public void cry(){
        System.out.println("cry cry~~~");
    }
}

properties:

classfullpath=com.company.Cat
method=hi

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

        //1. 使用properties类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));

        String classfullpath = properties.get("classfullpath").toString();
        String methodName = properties.get("method").toString();
        System.out.println("classfullpath = "+classfullpath);
        System.out.println("method = "+methodName);


        //1.加载类,返回Class类型的对象cls
        Class cls = Class.forName(classfullpath);

        //2. 通过cls得到需要加载的类com.company.Cat 的对象实例
        Object o = cls.newInstance();
        //3. 通过cls得到想要加载的类Cat的methodName“hi”的方法对象
        //反射中方法也被视为对象
        Method method1 = cls.getMethod(methodName);
        //4. 通过method1调用方法:即通过方法对象来实现调用方法
        method1.invoke(o);//传统方法:对象的实例.方法(),反射机制:方法.invoke(对象的实例)
        
        //通过cls得到你加载的类com.company.Cat
//        System.out.println(o.getClass());
    }
}

输出:

classfullpath = com.company.Cat
method = hi
hi~~~

== cls是加载类,o是对象实例,method1是方法对象==
改变properties

classfullpath=com.company.Cat
method=cry

输出也会改变:

classfullpath = com.company.Cat
method = cry
cry cry~~~

但是我们并没有改变代码,只是改变了properties

在这里插入图片描述

注意一点:Class类对象是一个对象,存在于堆中

XXX a=new XXX()
堆:存放对象实例new XXX(), 栈:存放地址信息 a,方法区(静态区):程序中唯一的元素,如class、static
Cat类的字节码二进制数据在方法区
类对象不是类而是对象,所以不在方法区,而是在堆中

  //java.lang.reflect.Field
        //反射获取类的属性值
        //getField不能获取私有属性
        Field age = cls.getField("age");
        System.out.println(age.get(o));//传统方法:对象.成员变量(),反射机制:成员变量.get(对象的实例)

        //java.lang.reflect.Field
        Constructor constructor = cls.getConstructor();
        System.out.println(constructor);


        Constructor constructor2 = cls.getConstructor(String.class);
        System.out.println(constructor2);

反射调优:

public class Reflection02 {
    public static void main(String[] args) throws Exception {
        Reflection02 reflection02 = new Reflection02();
        reflection02.m1();
        reflection02.m2();
        reflection02.m3();
    }
    public void m1(){
        Cat cat = new Cat();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 90000000; i++) {
            cat.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("传统方法时间 = "+(end-start));

    }
    public void m2() throws Exception {
        Class cls = Class.forName("com.company.Cat");
        Object o = cls.newInstance();
        Method hi = cls.getMethod("hi");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 90000000; i++) {
            hi.invoke(o);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射方法时间 = "+(end-start));

    }

    public void m3() throws Exception {
        Class cls = Class.forName("com.company.Cat");
        Object o = cls.newInstance();
        Method hi = cls.getMethod("hi");
        //在反射调用方法时,取消访问检查
        hi.setAccessible(true);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 90000000; i++) {
            hi.invoke(o);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射调优时间 = "+(end-start));

    }
}
传统方法时间 = 2
反射方法时间 = 111
反射调优时间 = 90

Class也是类,继承了Object类

Class类不是new出来的,是系统创建出来的

对于某个类的Class类对象,在内存中只有一份,因为类只加载一次

		//3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
	  	Class aClass = Class.forName("com.company.Cat");
        Class aClass2 = Class.forName("com.company.Cat");
        System.out.println(aClass2==aClass);//true

在这里插入图片描述

public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        String classAllPath="com.company.Cat";

        Class aClass = Class.forName(classAllPath);

        System.out.println(aClass);//class com.company.Cat,是哪个类的Class对象
        System.out.println(aClass.getClass());//输出运行类型  java.lang.Class

        System.out.println("=====================");
        
        //得到包名  com.company
        System.out.println(aClass.getPackage().getName());
        //得到全类名  com.company.Cat
        System.out.println(aClass.getName());
        //通过aClass创建对象
        Cat cat = (Cat)aClass.newInstance();
        System.out.println(cat);

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

        //通过反射获取属性 共有属性
        Field age = aClass.getField("age");
        System.out.println(age.get(cat));//10
        //通过反射给属性赋值
        age.set(cat,18);
        System.out.println(age.get(cat));//18
        //得到所有属性
        Field[] fields = aClass.getFields();
        for (Field f:fields){
            System.out.println(f.getName());
        }

    }
}

class com.company.Cat
class java.lang.Class
=====================
com.company
com.company.Cat
com.company.Cat@1b6d3586
=====================
10
18
age

在这里插入图片描述
在这里插入图片描述

四种方式获取Class对象

得到的Class对象都是同一个

public class GetClass_ {
    public static void main(String[] args) throws ClassNotFoundException {
        String classAllPath="com.company.Cat";

        //四种方式获取Class对象
        Class aClass = Class.forName(classAllPath);
        System.out.println(aClass);

        Class aClass2= Cat.class;
        System.out.println(aClass2);

        Cat cat = new Cat();
        Class aClass3 = cat.getClass();

        System.out.println(aClass==aClass2);//true
        System.out.println(aClass==aClass3);//true


        //通过类加载器获得类的Class对象
        ClassLoader classLoader = cat.getClass().getClassLoader();
        Class aClass4 = classLoader.loadClass(classAllPath);
        System.out.println(aClass==aClass4);//true
    }
}

几种基本类型的Class对象

        Class<Integer> integerClass = int.class;
        Class<Integer> integerClass1 = Integer.class;
        Class<String> stringClass = String.class;
        Class<Boolean> booleanClass = boolean.class;


        Class<Integer> type = Integer.TYPE;
        Class<Character> type1 = Character.TYPE;
        System.out.println(integerClass==type);//true

在这里插入图片描述

动态和静态加载

在这里插入图片描述
在这里插入图片描述
我们发现有一个new Dog(),它会直接编译报错,这是静态加载
case 2 中,只有“Person”字符串,并没有写Person,我们编译的是Class.forName(),并没有加载Person,
只有在我们key=2的时候,我们去找Person类,然后加载它,运行的时候才会用它,即使没有Person类,只要不运行它,就不会报错

类加载流程图

在这里插入图片描述
在这里插入图片描述

  • 加载:ClassLoader()
  • 验证:验证字节码和一些安全方面的东西
  • 准备:静态变量默认初始化
  • 解析:符号引用转为直接引用
  • 初始化:程序员写的代码,对静态变量进行初始化赋值

连接阶段-准备

  1. JVM会在该阶段对静态变量,分配内存并默认初始化
    在这里插入图片描述

class B{
    static {
        System.out.println("静态代码块已执行");
        num=100;
    }
    static  int num=300;
    public B(){
        System.out.println("构造方法已执行");
    }
}

当我们new B()的时候

  1. 加载B类,并生成B的class对象
  2. 链接 num=0
  3. 初始化阶段 -依次自动收集类中的所有静态变量的赋值动作和静态代码块,并合并
    clinit(){
    System.out.println(“静态代码块已执行”);
    //合并num为100
    num=300;
    num=100;
    }
  4. 执行构造器
    在这里插入图片描述
    加载类的时候会加锁
    保证每个类的Class类对象只有一个

获取类结构信息

public class ReflectionUtils {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        Class personCls = Class.forName("com.company.reflection.Person");
        System.out.println(personCls.getName());
        System.out.println(personCls.getSimpleName());

        Field[] fields = personCls.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        System.out.println("===========================");

        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }
        System.out.println("==========获取本类所有方法===========");
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        System.out.println("==========获取本类构造方法(公有的)===========");
        Constructor[] constructors = personCls.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName());
            
        }
        System.out.println("==========获取本类所有构造方法(包括私有)===========");
        Constructor[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName());
        }
        System.out.println("=============================");
        System.out.println(personCls.getPackage());

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

        Class[] interfaces = personCls.getInterfaces();
        for (Class anInterface : interfaces) {
            System.out.println(anInterface);
        }
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

    }
}

class A{
    public String hobby;
    public void AAA(){

    }
}

interface  IA{

}
interface  IB{

}

@Deprecated
class Person extends A implements IA,IB{
    public String name;
    protected int age;
    String job;
    private double sal;

    public Person() {
    }

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

    public  void m1(){

    }
    protected  void m2(){

    }
    void m3(){

    }
    private void m4(){

    }
}
com.company.reflection.Person
Person
name
hobby
===========================
name
age
job
sal
==========获取本类所有方法===========
m1
AAA
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
==========获取本类构造方法===========
com.company.reflection.Person
==========获取本类所有构造方法(包括私有)===========
com.company.reflection.Person
com.company.reflection.Person
=============================
package com.company.reflection
class com.company.reflection.A
interface com.company.reflection.IA
interface com.company.reflection.IB
@java.lang.Deprecated()

Field和Method都有getModifiers()方法
在这里插入图片描述

反射可以访问私有属性,构造器

public class ReflecCreateInstance {
    public static void main(String[] args) throws Exception {
        Class userClass = Class.forName("com.company.reflection.User");
        //通过public的无参构造创建实例
        Object o = userClass.newInstance();
        System.out.println(o);

        //通过public有参构造器创建实例
        //先得到构造器
        Constructor constructor = userClass.getConstructor(String.class);
        //创建实例,并传入实参
        User o1 =(User) constructor.newInstance("你好");
        System.out.println(o1);


        //通过非public的有参构造器创建实例
        //得到private构造器
        Constructor declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
        declaredConstructor.setAccessible(true);//暴力破解
        //创建对象
        Object hello = declaredConstructor.newInstance(11, "hello");
        System.out.println(hello);

    }
}

class User{
    private int age;
    private String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

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

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

访问静态属性和方法

public class ReflecAccessProperty {
    public static void main(String[] args) throws Exception {
        Class<?> stuClass = Class.forName("com.company.reflection.Student");

        Object o = stuClass.newInstance();
        System.out.println(o);

        //反射获取age属性
        Field age = stuClass.getField("age");
        //反射操作属性
        age.set(o,11);
        System.out.println(o);
        System.out.println(age.get(o));

        //使用反射操作name
        Field name = stuClass.getDeclaredField("name");
        name.setAccessible(true);
//        name.set(o,"hhh");
        //只有静态属性才可以写null
        name.set(null,"hhh");
        System.out.println(name.get(null));
    }
}
class Student{
    public int age;
    private static String name;

    public Student() {
    }

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

爆破

public class ReflecAccessMethod {
    public static void main(String[] args) throws Exception {
        Class<?> bossClass = Class.forName("com.company.reflection.Boss");

        Object o = bossClass.newInstance();

        //调用普通方法  只能获取public
        Method hi = bossClass.getMethod("hi",String.class);
        //可以获取private
        hi = bossClass.getDeclaredMethod("hi",String.class);
        Object jiaoyu = hi.invoke(o, "jiaoyu");
        System.out.println(jiaoyu);//null

        Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
        //因为say是私有的,需要爆破
        say.setAccessible(true);
        System.out.println(say.invoke(o,666,"hhh",'q'));

        //返回值
        System.out.println(say.getReturnType());
    }
}
class Boss{
    public int age;
    private static String name;

    public Boss() {
    }

    private static String say(int n, String s, char c){
        return n+" "+s+" "+c;
    }
    public void hi(String s){
        System.out.println("hi "+s);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值