反射全面详解

Java源码系列:下方连接
http://t.csdn.cn/Nwzed



前言


一、反射是什么?

在这里插入图片描述

package tanchishell.reflection;

import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;

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

        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));

        String classfullpath = (String) properties.get("classfullpath");
        String methodName = (String)properties.get("method");

        System.out.println(classfullpath +"===" +methodName);
        //使用反射生成对象

        Class<?> aClass = Class.forName(classfullpath);

        //拿到class调用方法创建实例
        Object o = aClass.newInstance();

        //打印 o 的运行时类型
        System.out.println("o的类型是==="+ o.getClass());
        Cat cat = (Cat) o;
        System.out.println(""+ cat);

        //使用反射调用方法
        Method method = aClass.getMethod(methodName);
        method.invoke(cat);
        //方法调用对象
        System.out.println("======"+method);


    }
}

Catpackage tanchishell.reflection;

public class Cat {

    private String name="招财狗";

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

    public void hi(){
        System.out.println("你好"+name);
    }
    public void hello(){
        System.out.println("很不好"+name);
    }
}





配置文件
classfullpath=tanchishell.reflection.Cat
method=hello


在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

//更详细的代码

public class Cat {

    private String name="招财狗";
    public String catName="招财猫";



    public Cat() {
    }

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

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

    public void hi(){
        System.out.println("你好"+name);
    }
    public void hello(){
        System.out.println("很不好"+name);
    }
}



//反射获取所有基本属性


package tanchishell.reflection;

import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

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

        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));

        String classfullpath = (String) properties.get("classfullpath");
        String methodName = (String)properties.get("method");

        System.out.println(classfullpath +"===" +methodName);
        //使用反射生成对象

        Class<?> aClass = Class.forName(classfullpath);

        //拿到class调用方法创建实例
        Object object = aClass.newInstance();

        //打印 o 的运行时类型
        System.out.println("o的类型是==="+ object.getClass());
        Cat cat = (Cat) object;
        System.out.println(""+ cat);

        //使用反射调用方法
        Method method = aClass.getMethod(methodName);
        method.invoke(cat);
        //方法调用对象
        System.out.println("方法调用对象======"+method);

        //使用反射获取成员变量  getField不能获取私有属性和受保护的属性,只能获取public
        Field cat1 = aClass.getField("catName");
        cat1.get(object);//反射反过来调用方法。是方法调用对象
        System.out.println("反射获取成员属性"+cat1);

        //使用反射获取构造器,默认获取无参
        Constructor<?> constructor = aClass.getConstructor();
        System.out.println("默认获取无参"+constructor);
        //获取有参
        Constructor<?> stringConstructor = aClass.getConstructor(String.class);
        System.out.println("获取有参"+stringConstructor);
        //获取双参
        Constructor<?> SSConstructor = aClass.getConstructor(String.class,String.class);
        System.out.println("获取双参"+SSConstructor);

        /**
         * 获取构造器后还可以通过构造器创建对象
         */
    }
}




二、反射机制的优化

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

三、Class类

同一个类只会通过类加载器加载一次,如果使用传统的 new 方式创建对象,在使用反射的方式就不会进行类加载了。
在这里插入图片描述

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

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

三、获取Class对象的六种方式

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

在这里插入图片描述

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

哪些类有Class对象

在这里插入图片描述

在这里插入图片描述

四、类的加载

动态和静态加载

在这里插入图片描述

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

类的加载流程

在这里插入图片描述
在这里插入图片描述
加载和连接阶段是由jvm虚拟机控制的,初始化程序员可以写在类中。

在这里插入图片描述

加载阶段

在这里插入图片描述

连接阶段

在这里插入图片描述
在准备阶段只是对成员变量进行默认初始化,而在初始化阶段才会对成员变量进行赋值。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

初始化阶段

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

五、通过反射获取类的结构信息

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

在这里插入图片描述

六、反射爆破实例

在这里插入图片描述

在这里插入图片描述

反射暴力破解创建类的实例

package tanchishell.reflection;

import java.lang.reflect.Constructor;

/**
 * 反射爆破对象
 */
public class ReflectionTest {
    public static void main(String[] args) throws  Exception{
        //1、先获取 User 类的 Class对象
        Class<?> userClass = Class.forName("tanchishell.reflection.User");
        //2、通过午餐狗杂创建实例
        Object user = userClass.newInstance();
        System.out.println(user);
        //3、获取public有参构造创建实例

        //获取有参构造器
        Constructor<?> constructor = userClass.getConstructor(String.class);
        Object hello = constructor.newInstance("hello");
        System.out.println(hello);

        //4、通过私有的有参构造创建实例
        Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
        //爆破私有构造
        declaredConstructor.setAccessible(true);
        Object no = declaredConstructor.newInstance(20, "很不好");
        System.out.println(no);


    }
}

class User{
    private int age = 10;
    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 + '\'' +
                '}';
    }
}

反射爆破访问成员属性

在这里插入图片描述

package tanchishell.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * 反射爆破对象
 */
public class ReflectionTest {
    public static void main(String[] args) throws  Exception{
        //1、先获取 User 类的 Class对象
        Class<?> userClass = Class.forName("tanchishell.reflection.User");
        //2、通过午餐狗杂创建实例
//        Object user = userClass.newInstance();

        //通过无参构造创建实例,并爆破
        Constructor<?> constructor = userClass.getConstructor();
        constructor.setAccessible(true);
        Object user = constructor.newInstance();
        System.out.println(user);


        //2 通过反射获取属性

        //获取所有public属性
        Field[] fields = userClass.getFields();
        for (int i = fields.length - 1; i >= 0; i--) {
            Field field = fields[i];
            field.setAccessible(true);
            System.out.println(field);
            field.set(user,60);
            System.out.println(user);
        }

        //获取public属性,并赋值  调用这个方法属性必须是 public
        Field age = userClass.getField("age");
        age.setAccessible(true);
        System.out.println(age);
        age.set(user,100);
        System.out.println(user);

        //获取任意属性 但静态属性和私有属性不能赋值  IllegalAccessException 需要爆破
        Field name = userClass.getDeclaredField("name");
        name.setAccessible(true);
        System.out.println(name);
        name.set(user,"不是如风");
        System.out.println(user);

        //获取任意属性的值,也需要先进行爆破
        System.out.println(name.get(user));
        System.out.println(age.get(user));

    }
}

class User{
    public int age = 10;
    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 + '\'' +
                '}';
    }
}

反射爆破访问方法

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

package tanchishell.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 反射爆破对象
 */
public class ReflectionTest {
    public static void main(String[] args) throws  Exception{
        //1、先获取 User 类的 Class对象
        Class<?> userClass = Class.forName("tanchishell.reflection.User");
        //2、通过午餐狗杂创建实例
//        Object user = userClass.newInstance();

        //通过无参构造创建实例,并爆破
        Constructor<?> constructor = userClass.getConstructor();
        constructor.setAccessible(true);
        Object user = constructor.newInstance();
        System.out.println(user);


        //2 通过反射获取方法  getMethod("hi",String.class); 一定要注意
        Method method = userClass.getMethod("hi",String.class);
        method.invoke(user,"钢铁侠");

        //3、通过反射获取任意方法 私有方法需要爆破
        Method hello = userClass.getDeclaredMethod("hello", int.class,String.class);
        hello.setAccessible(true);
        hello.invoke(user,10,"钢铁侠");


    }
}

class User{
    public int age = 10;
    private  String name = "你好";


    public void hi(String name){
        System.out.println("你好!" +name);
    }

    private void hello(int age,String name){
        System.out.println("你好!" +name+"我——" +age +"岁了");
    }

    public User() {
    }

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

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

    private  User(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值