thinkinginjava反射

fivefiveopen      2022-04-15     173

关键词:

前言

反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的Class,Class类用于表示字节码,字节码即是.class文件

概述

JAVA反射机制:在程序运行的过程中,对于任意一个类,都可以知道这个类的所有信息,比如:成员变量、方法、构造方法、包等信息;要想用反射机制,首先要获取到

该类的字节码文件对象Class,然后用Class类中的方法把各种成分映射成Java对象,关于.class文件,在我们new对象的时候,本地IDE自动编译,然后jvm会自动的从硬盘

读取到.class文件,并创建一个该类的Class文件,但是,如果我们new了多个该类的实例,内存中只会有一份该类的字节码文件。

API

Class 类与 java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了 Field、Method、Constructor 类 (每个类都实现了 Member 接口)该接口反映单个成员(字段

或方法)或构造方法的标识信息,正因为实现了该接口,因此可以反射相关变量、方法信息,这些类型的对象时由 JVM 在运行时创建的,用以表示未知类里对应的成员。

反射

获取字节码

在 Java 中可以通过三种方法获取类的字节码 (Class) 对象,如下:

技术分享图片
package com.oxygen.bean;

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();
        Class<?> clazz1 = student.getClass(); //方式1
        Class<?> clazz2 = Student.class; //方式2
        Class clazz3 = Class.forName("com.oxygen.student");//方式3
    }
}
View Code

获取类信息

Student类如下

技术分享图片View Code

1. 通过构造函数对象Constructor创建对应类的实例

技术分享图片
package com.oxygen.bean;

import java.lang.reflect.Constructor;

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        Student student = new Student(); //Student的带参构造函数依赖另外一个类Car
        Class<?> clazz1 = student.getClass(); //方式1
        func1(clazz1); //通过无参构造函数反射Student实例
        func2(clazz1);//通过有参构造函数反射Student实例
        func3(clazz1);//获取所有的构造函数反射Student实例
        func4(clazz1); // 反射私有构造函数
    }

    private static void func4(Class<?> clazz1) throws Exception {
        Constructor<?> declaredConstructor = clazz1.getDeclaredConstructor(String.class);
        declaredConstructor.setAccessible(true);//设置为可以访问
        System.out.println(declaredConstructor.newInstance("zhangsan"));
    }

    private static void func3(Class<?> clazz1) throws Exception {
        Constructor<?>[] constructors = clazz1.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("func3: " + constructor);
        }
    }

    /**
     * 因为Student的带参构造函数依赖另外一个类Car,因为必须保证JVM能获取到Car的字节码
     * @param clazz1
     * @throws Exception
     */
    public static void func2(Class<?> clazz1) throws Exception {
        Car car = new Car();//保证
        Constructor<?> constructor = clazz1.getConstructor(String.class, Integer.class, Car.class);
        Student student = (Student) constructor.newInstance("张三", 18, new Car());
        System.out.println(student);
    }

    public static void func1(Class<?> clazz1) throws Exception {
        Constructor<?> constructor = clazz1.getConstructor();
        Student student = (Student) constructor.newInstance();
        System.out.println(student);
    }
}
View Code

2. 获取成员方法

技术分享图片
package com.oxygen.bean;

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

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        Student student = new Student();
        Class<?> clazz1 = student.getClass();
        m1(clazz1);
        m2(clazz1);
        m3(clazz1);
        m4(clazz1);
    }

    /**
     * 获取所有的方法,包括私有的,不包括继承Object类的9个方法
     * @param clazz1
     */
    public static void m4(Class<?> clazz1) {
        Method[] declaredMethods = clazz1.getDeclaredMethods();
    }

    /**
     * 获取所有的”公有“方法,包括继承Object类的9个方法
     * @param clazz1
     */
    public static void m3(Class<?> clazz1) {
        Method[] methods = clazz1.getMethods();
    }

    /**
     * 获取私有的show4()方法
     * @param clazz1
     * @throws Exception
     */
    public static void m2(Class<?> clazz1) throws Exception {
        Method method;
        method = clazz1.getDeclaredMethod("show4", int.class);
        Student stu = func1(clazz1); // 实例化一个Student对象
        method.setAccessible(true);
        method.invoke(stu, 20);//反射私有方法show4(),第一个参数是实例,第二个参数是被反射方法的参数
    }

    /**
     * 获取公有的show1()方法
     * @param clazz1
     * @throws Exception
     */
    public static void m1(Class<?> clazz1) throws Exception {
        Method method = clazz1.getMethod("show1", String.class); //第一个参数是方法名称,第二个参数是形参类型
        Student stu = func1(clazz1); // 实例化一个Student对象
        method.invoke(stu, "lisi"); //反射公有方法show1(),第一个参数是实例,第二个参数是被反射方法的参数
    }

    public static Student func1(Class<?> clazz1) throws Exception {
        Constructor<?> constructor = clazz1.getConstructor();
        Student student = (Student) constructor.newInstance();
        return student;
    }
}
View Code

thinkinginjava整理笔记:类型信息

本章将讨论Java是如何让我们在运行时识别对象和类的信息的:一种是“传统的”RTTI,他假定我们在编译时已经知道了所有的类型;另一种是“反射”机制,它允许我们在运行时发现和实用类的信息。PS:“运行时... 查看详情

深入理解java类型信息(class对象)与反射机制

...一直是C++中的概念,至于Java中出现RRTI的说法则是源于《ThinkinginJava》一书,其作用是在运行时识别一个对象的类型和类的信息,这里分两种:传统的”RRTI”,它假定我们在 查看详情

java基础--深入理解java类型信息(class对象)与反射机制

...一直是C++中的概念,至于Java中出现RTTI的说法则是源于《ThinkinginJava》一书,其作用是在运行时识别一个对象的类型和类的信息,这里分两种:传统的”RTTI”:它假定我们在编译期已知道了所有类型(在没有反射机制创建 查看详情

thinkinginjava----readingnote

#thinkinginjava4th#readingnote#victor#2016.02.10chapter1对象入门1.1抽象的进步   (1)所有东西都是对象。   (2)程序是一大堆对象的组合,对象间通过消息联系。   (3)通过封装现有对象,可制作出新型对象。 &n... 查看详情

thinkinginjava----readingnote

#thinkinginjava4th#readingnote#victor#2016.03.13chapter3控制程序流程3.1java运算符   几乎所有运算符都只能操作"基本值类型"."=","=="和"!="能操作所有对象,String类支持"+"和"+=".3.1.1优先级   运算符的优先级决定了存在多... 查看详情

thinkinginjava-----readingnote

#thinkinginjava4th#readingnote#victor#2016.02.16chapter2一切都是对象2.1用句柄操纵对象   使用句柄作为标识符指向一个对象.但拥有句柄并不意味着有一个对象同它连接.   例如,创建一个String句柄:Strings;   此... 查看详情

java线程同步临界区:thinkinginjava421.3.5(代码片段)

java线程同步临界区:thinkinginjava421.3.5thinkinginjava4免费下载:http://download.csdn.net/detail/liangrui1988/7580155packageorg.rui.thread.critical;importjava.util.ArrayList;importjava.util. 查看详情

类的特殊获取方式——《thinkinginjava》随笔008

//:Lauch.java//学习《ThinkinginJava》的代码笔记//Soup是后面学习单例设计模式的一个基础。packagecn.skyfffire;/****@authorskyfffire**/classSoup{privateSoup(){}/***可以via这个staticmethod返回newobjecy.**@return新的对象的句柄*/publicstaticSoupm 查看详情

《thinkinginjava》阅读感想

...的话我一边实践一边记录吧,这篇文章跟大家分享一下《thinkinginjava》这本书的读后感吧,其实个人感觉分享一些学习想法和经验比分享一个技术,作用更大。   &nb 查看详情

thinkinginjava

资料:1.电子书github地址:https://github.com/quanke/think-in-java,在readme说明中有下载pdf等格式的地址,也可以下载到本地用gitbook工具自行导出。2.书中代码地址:https://github.com/niushuai/thinking_in_java.git,通过eclipse下载代码创建为JavaProje... 查看详情

thinkinginjava知识小记

知识点一(javadoc):        使用javadoc时特别注意选择encoding和charset为utf-8,要不然生成的javadoc会是乱码,命令:javadoc-encodingutf-8-charsetutf-8*.java附录(javadoc标记)@author    查看详情

构建器——《thinkinginjava》随笔001

packagecn.skyfffire;/****@authorskyffire**/classTree{intheight;Tree(){prt("无参数构造");}Tree(inti){prt("创建ClassTree使用Integer参数"+i);height=i;}Tree(Strings){prt(s);}voidinfo(){prt("Tree值:"+height);}staticvo 查看详情

thinkinginjava整理笔记:内部类

1.一般指明一个内部类对象:OuterClassName.InnerClassName2.内部类拥有其外围类的所有元素的访问权。3.如:interfaceSelector voidnext();publicclassSequence privateinti=9; publicclassSequenceSelectorimplementsSelector  pub 查看详情

主类型过载——《thinkinginjava》随笔002

packagecn.skyfffire;/****@authorskyfffire**/publicclassTest{//voidfun1(){//System.out.println("调用无返回值的方法");//}////intfun1(){//System.out.println("调用有返回值的方法");////return0;//}publicstaticvoidmain(String 查看详情

java编程思想thinkinginjava

Java编程思想【Thinkinginjava】目录:第1章对象导论1.1抽象过程1.2每个对象都有一个接口1.3每个对象都提供服务1.4被隐藏的具体实现1.5复用具体实现1.6继承1.6.1“是一个”(is-a)与“像是一个”(is-like-a)关系1.7伴随多... 查看详情

thinkinginjava对象导论

AlanKay总结的Smalltalk(java所基于的语言之一)的五个基本特征:   ①万物皆为对象     将对象看做奇特的变量,可以存储数据、对自身执行操作。   ②程序是对象的集合,它们通过发送消息... 查看详情

thinkinginjava第七章3-1

ThinkinginJava第七章研读3-1总结问题引入:如何复用代码1.新的类是由现有类的对象所组成,方法称为组合。(该方法只是复用了现有程序代码的功能,而非他的形式)2.按照现有类的类型创建新类。方法称为继承。(该方法无需改... 查看详情

java内存释放——《thinkinginjava》随笔004

1packagecn.skyfffire;23/**4*5*@authorskyfffire6*7*/8publicclassTest{9staticbooleangcrun=false;//GC是垃圾回收器10staticbooleanf=false;//终止创建对象的条件11staticintcreated=0;//对象个数计数器12staticintfinalized=0;//对象销毁13i 查看详情