Java学习路线(23)——反射机制

这篇具有很好参考价值的文章主要介绍了Java学习路线(23)——反射机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述
(一)什么是反射: 反射指的是任何一个Class类,在“运行时”都可以直接得到全部成分。
(二)动态可获取的对象: 构造器对象——Constructor,成员变量对象——Field,成员方法对象——Method。
(三)反射关键: 第一步都是得到编译后的Class对象,然后可以获得Class全部成分。


二、反射相关对象的获取
(一)获取Class对象

//过程:Hello.java -> javac -> Hello.class
Class c = Hello.class;

1、Object.forName(String className) -> 源码阶段获取
2、Object.class -> 内存阶段获取
3、Object.class() -> 实例化阶段获取

public class getClassInfoDemo {
    public static void main(String[] args) {
        try {
            /*forName(类全名)*/
            Class c = Class.forName("com.zengoo.reflected.Student");
            System.out.println(c);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

        /*类获取*/
        System.out.println(Student.class);

        /*对象获取*/
        System.out.println(new Student().getClass());
    }
}

class Student{
    private String id;
    private String name;

    public Student() {
    }

    public Student(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

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

/*打印输出*/
class com.zengoo.reflected.Student
class com.zengoo.reflected.Student
class com.zengoo.reflected.Student

(二)获取构造器

1、相关API

方法 说明
Constructor<?>[] getConstructors() 获取public修饰的所有构造器对象
Constructor<?>[] getDecalaredConstructors() 获取所有构造器对象
Constructor<?> getConstructor(Class<T>… parameterTypes) 根据参数类型返回单个public构造器
Constructor<?> getDecalaredConstructor(Class<T>… parameterTypes) 根据参数类型获取单个构造器对象

2、获取构造器示例

public class getClassConstructorDemo {
    public static void main(String[] args) {

        Class c = Student.class;

        //获取所有public构造器
        Constructor[] c1 = c.getConstructors();
        System.out.println("=============获取所有public构造器=============");
        for (Constructor constructor :c1) {
            System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
        }
        //获取所有构造器
        System.out.println("=============获取所有构造器=============");
        Constructor[] c2 = c.getDeclaredConstructors();
        for (Constructor constructor :c2) {
            System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
        }

        //获取单个public构造器对象
        System.out.println("=============获取单个public构造器对象=============");
        try {
            Constructor c3 = c.getConstructor();
            System.out.println(c3.getName() + "===>" + c3.getParameterCount());
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        //获取单个构造器对象
        System.out.println("=============获取单个构造器对象=============");
        try {
            Constructor c4 = c.getDeclaredConstructor(String.class,String.class);
            System.out.println(c4.getName() + "===>" + c4.getParameterCount());
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

/*打印输出*/
=============获取所有public构造器=============
com.zengoo.reflected.Student===>0
com.zengoo.reflected.Student===>2
=============获取所有构造器=============
com.zengoo.reflected.Student===>0
com.zengoo.reflected.Student===>2
=============获取单个public构造器对象=============
com.zengoo.reflected.Student===>0
=============获取单个构造器对象=============
com.zengoo.reflected.Student===>2

3、获取构造器并调用

(1)作用: 获取构造器的作用是为了初始化一个对象返回。
(2)相关API

方法 说明
T newInstance(Object initargs) 根据指定构造器创建对象
void setAccessible(boolean flag) 设置true表示无视访问限制,暴力反射

(3)使用示例

class useConstructor{
    public static void main(String[] args) throws Exception {
        Constructor constructor = Student.class.getConstructor(String.class,String.class);
        constructor.setAccessible(true); //暴力破解私有权限,若构造器为公开权限,则不需要
        Student student = (Student) constructor.newInstance(UUID.randomUUID().toString(),"金牙齿");
        System.out.println(student);
    }
}

/*打印输出*/
Student{id='77430b37-a65f-4379-b181-437dc5544032', name='金牙齿'}

(三)获取成员变量

1、相关API

方法 说明
Field<?>[] getFields() 获取public修饰的所有成员变量
Field<?>[] getDeclaredFields() 获取所有成员变量
Field<?> getField(String name) 根据参数名称返回单个public成员变量
Field<?> getDecalaredField(String name) 根据参数名称返回单个成员变量
void set(Object obj,Object value) 给对象注入某个成员变量数据
Object get(Object obj) 根据参数名称返回单个成员变量
void setAccessible(boolean b) 暴力开权限
Class getType() 获取属性的类型,返回Class对象
String getName() 获取属性名称

2、使用示例

public class getClassFieldDemo {
    public static void main(String[] args) throws NoSuchFieldException {
        Class c = Student.class;

        //获取所有public成员变量
        Field[] fields = c.getFields();
        for (Field f :fields) {
            System.out.println(f.getType() + " " + f.getName());
        }

        //获取所有成员变量
        Field[] fields1 = c.getDeclaredFields();
        for (Field f :fields1) {
            System.out.println(f.getType() + " " + f.getName());
        }

        //获取单个public成员变量
        Field field = c.getDeclaredField("name");
        System.out.println(field.getType() + " " + field.getName());

        //获取单个成员变量
        Field field1 = c.getDeclaredField("id");
        System.out.println(field1.getType() + " " + field1.getName());
    }
}

/*打印变量*/
class java.lang.String id
class java.lang.String name
class java.lang.String name
class java.lang.String id

class useField{
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Class c = Student.class;

        Field id = c.getDeclaredField("id");
        Field name = c.getDeclaredField("name");

        id.setAccessible(true);
        name.setAccessible(true);

        Student s = new Student();
        id.set(s, UUID.randomUUID().toString());
        name.set(s, "金钟罩");

        System.out.println(id.getType() + " " + id.get(s));
        System.out.println(name.getType() + " " + name.get(s));
    }
}

/*打印输出*/
class java.lang.String d368bc5c-76c9-413a-ad2d-565729b7afe9
class java.lang.String 金钟罩

(四)获取成员方法

1、相关API

方法 说明
Method[] getMethods() 返回所有public修饰的成员方法对象的数组
Method[] getDeclaredMethods() 返回所有成员方法对象的数组
Method getMethod(String name,Class<?>… parameterTypes) 根据方法名,参数列表属性,返回单个public修饰的成员方法对象
Method getDecalaredField(String name,Class<?>… parameterTypes) 根据方法名,参数列表属性,返回单个修饰的成员方法对象
void setAccessible(boolean b) 暴力开权限

2、使用示例

public class getClassMethodDemo {
    public static void main(String[] args) throws NoSuchMethodException {
        Class c = Student.class;


        //获取所有public成员方法
        Method[] methods = c.getMethods();
        for (Method method :methods) {
            System.out.println(method.getGenericParameterTypes().toString() + " " + method.getName());
        }

        //获取所有成员方法
        Method[] methods1 = c.getDeclaredMethods();
        for (Method method :methods1) {
            System.out.println(method.getGenericParameterTypes().toString() + " " + method.getName());
        }

        //获取单个public成员变量
        Method method = c.getMethod("getName");
        System.out.println(method.getGenericParameterTypes().toString() + " " + method.getName());

        //获取单个成员变量
        Method method1 = c.getMethod("setId", String.class);
        System.out.println(method1.getGenericParameterTypes().toString() + " " + method1.getName());
    }
}

/*打印输出*/
[Ljava.lang.Class;@67b64c45 getName
[Ljava.lang.Class;@68837a77 toString
[Ljava.lang.Class;@6be46e8f setName
[Ljava.lang.Class;@3567135c getId
[Ljava.lang.Class;@327471b5 setId
[Ljava.lang.Class;@4157f54e wait
[Ljava.lang.Class;@90f6bfd wait
[Ljava.lang.Class;@47f6473 wait
[Ljava.lang.Class;@15975490 equals
[Ljava.lang.Class;@6b143ee9 hashCode
[Ljava.lang.reflect.Type;@9f70c54 getClass
[Ljava.lang.Class;@234bef66 notify
[Ljava.lang.Class;@737996a0 notifyAll
[Ljava.lang.Class;@61dc03ce getName
[Ljava.lang.Class;@50f8360d toString
[Ljava.lang.Class;@2cb4c3ab setName
[Ljava.lang.Class;@13c78c0b getId
[Ljava.lang.Class;@12843fce setId
[Ljava.lang.Class;@3dd3bcd getName
[Ljava.lang.Class;@97e1986 setId

3、方法调用

class useMethod{
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c = Student.class;
        Constructor constructor = c.getConstructor(String.class,String.class);
        constructor.setAccessible(true);

        Student student = (Student) constructor.newInstance(UUID.randomUUID().toString(),"金环法");

        System.out.println(student);

        Method method = c.getMethod("setName", String.class);

        method.setAccessible(true);
        method.invoke(student,"新名称");

        System.out.println(student);
    }
}

/*打印输出*/
Student{id='d001810b-88e7-468d-bb8c-bc4129970191', name='金环法'}
Student{id='d001810b-88e7-468d-bb8c-bc4129970191', name='新名称'}


三、反射的作用

(一)绕过编译阶段为集合添加数据(原理是泛型擦除,即强制执行)

class useClassDemo{
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();

        list1.add(1);
        list1.add(2);
        list1.add(3);

        list2.add(1);
        list2.add(2);
        list2.add(3);

        System.out.println(list1.getClass());
        System.out.println(list2.getClass());

        System.out.println(list1.getClass() == list2.getClass());

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

        Class c = list2.getClass();

        Method method = c.getMethod("add", Object.class);

        method.invoke(list2,"字符串");

        System.out.println(list1.getClass() == list2.getClass());
        System.out.println(list1);
        System.out.println(list2);
    }
}

/*打印输出*/
class java.util.ArrayList
class java.util.ArrayList
true
===========================
true
[1, 2, 3]
[1, 2, 3, 字符串]

(二)通用框架的底层原理(重点)

用反射做通用框架示例

/**
* 需求:给定任意对象,在不清楚对象字段的情况下,将对象的字段名和对应值存储到文件中去。
*/

public class useReflectedToFrame {
    public static void main(String[] args) {
      Shop shop = new Shop(UUID.randomUUID().toString(),"店名","xxx市xxx区xxx街道xxx");
      Goods goods = new Goods(UUID.randomUUID().toString(),"商品名",28.5);

      String parentPath = "D:\\JavaBase\\JavaSEpro\\src\\com\\zengoo\\outDir\\";

      TestUtil.save(shop,parentPath+"shop.txt");
      TestUtil.save(goods,parentPath+"goods.txt");
      System.out.println("打印完毕");
    }
}

/*自定义通用框架*/
class TestUtil{
    public static void save(Object obj,String pathname) {
        try(PrintStream printStream = new PrintStream(new FileOutputStream(pathname))){
            //1、提取对象的所有成员变量
            Class c = obj.getClass();

            Field[] fields = c.getDeclaredFields();
            for (Field field:fields) {
                field.setAccessible(true);
                //2、获取变量名
                String name = field.getName();
                //3、获取变量名对应的值
                String value = " = " + field.get(obj);

                printStream.println(name + value);
            }
        } catch (IllegalAccessException | FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

class Shop{
    private String id;
    private String shopName;
    private String address;

    public Shop() {
    }

    public Shop(String id, String shopName, String address) {
        this.id = id;
        this.shopName = shopName;
        this.address = address;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getShopName() {
        return shopName;
    }

    public void setShopName(String shopName) {
        this.shopName = shopName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Shop{" +
                "id='" + id + '\'' +
                ", shopName='" + shopName + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

class Goods{
    private String id;
    private String goodsName;
    private double price;

    public Goods() {
    }

    public Goods(String id, String goodsName, double price) {
        this.id = id;
        this.goodsName = goodsName;
        this.price = price;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }


    @Override
    public String toString() {
        return "Goods{" +
                "id='" + id + '\'' +
                ", goodsName='" + goodsName + '\'' +
                ", price=" + price +
                '}';
    }
}

shop.txt

id = cd23f6eb-91c3-4f19-adf5-654ef4602b2e
shopName = 店名
address = xxx市xxx区xxx街道xxx

goods.txt文章来源地址https://www.toymoban.com/news/detail-474771.html

id = 77d46cea-04ec-45dd-b806-f39179bfa37e
goodsName = 商品名
price = 28.5

到了这里,关于Java学习路线(23)——反射机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 什么是反射机制

    1.什么是类对象: 所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。 比方有一个Hero类:类对象就是用于描述这种类,都有什么属性,什么方法的。 获取类对象有3种方式 Class.forName Hero.class new Hero().get

    2024年02月05日
    浏览(13)
  • 深度学习中的正则化指的是什么?

    在深度学习中,正则化是一种技术,旨在减少模型的过拟合,提高其在未见数据上的泛化能力。过拟合是指模型在训练数据上表现得非常好,但在新数据上表现不佳的情况。正则化通过对模型添加某种形式的约束或惩罚来实现这一目标。以下是几种常见的正则化技术: L1 和

    2024年01月23日
    浏览(9)
  • Java笔记040-反射/反射机制、Class类

    Java笔记040-反射/反射机制、Class类

    目录 反射(reflection) 一个需求引出反射 反射机制 Java反射机制原理图 Java反射机制可以完成 反射相关的主要类 反射机制的优点和缺点 反射调用优化-关闭访问检查 Class类 基本介绍 代码解释部分 类加载方法 应用实例:Class02.java 获取Class类对象 代码解释部分 哪些类型有Class对象

    2024年02月09日
    浏览(13)
  • Java的反射机制

    Java 的反射机制允许在程序运行期间,借助反射 API 获取类的内部信息,并能直接操作对象的内部属性及方法。 Java 反射机制提供的功能: 在运行时,使用反射分析类的能力,获取有关类的一切信息(类所在的包、类实现的接口、标注的注解、类的数据域、类的构造器、类的

    2024年02月02日
    浏览(11)
  • Java的反射机制(2)

    目录 Class类基本介绍 Class类的常用方法 如何获取class类对象 哪些类型有Class对象 Class类基本介绍 在Java语言中,每个对象都有一个运行时类,即其所属的类。而这个运行时类在Java中是以Class类的实例形式存在的,该Class类实例就是所谓的Class对象。Class类表示一个类或接口的元

    2024年02月08日
    浏览(9)
  • Java反射机制深入详解

    一.概念 反射就是把Java的各种成分映射成相应的Java类。 Class类的构造方法是private,由JVM创建。 反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示

    2024年02月06日
    浏览(11)
  • Java反射、代理机制

    官方解释:反射允许对封装类的字段、方法和构造方法的信息进行编程访问。 虚拟机加载类文件后,会在方法区生成一个类对象,包含了类的结构信息,如字段、方法、构造方法等。反射是一种能够在程序运行时动态访问、修改类对象中任意属性的机制(包括private属性)。

    2024年02月10日
    浏览(9)
  • Java重点:反射机制的使用

    Java重点:反射机制的使用

    目录 一、概念 二、类类 1、类类的获取方式 1)类名.Class 2)对象.getClass() 3)Class.forName() 三、反射实例化 1、调用一个公有的无参构造方法 2、调用一个公有的一个参构造方法 3、调用一个公有的两个参构造方法 4、调用一个私有的一个参构造方法 四、反射:方法调用 1、公有

    2024年02月07日
    浏览(11)
  • 【JavaSE】Java的反射机制

    1.java反射机制 1.1简介 被视为动态语言的关键,允许程序在执行期间,借助于RefectionAPI取得任何类的内部信息。在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个类对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方

    2024年04月26日
    浏览(10)
  • Java安全基础之Java反射机制和ClassLoader类加载机制

    Java安全基础之Java反射机制和ClassLoader类加载机制

    目录 Java 反射机制 反射 java.lang.Runtime ClassLoader 类加载机制 URLClassLoader loadClass() 与 Class.forName() 的区别? Java 反射(Reflection)是 Java 非常重要的动态特性。在运行状态中,通过 Java 的反射机制,我们能够判断一个对象所属的类。了解任意一个类的所有属性和方法。能够调用任

    2024年04月22日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包