1.11(java高级特性)反射

前言

感谢大家的观看,如果中间遇到写的有问题的地方,请多多指教

此文章,我是通过尚硅谷的视频进行编写的。我在之后的时间会将此类文章全部编写出来。完成我的java冲刺小专栏。谢谢大家的观看

[硅谷学习路线](2021年度全网最全Java学习路线 - 哔哩哔哩 (bilibili.com))

反射(reflection)

万事万物皆对象:学完反射进一步体会到了。

上面的网络编程连URL都可以做对象。

概念

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期 借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内 部属性及方法。

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个 类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可 以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看 到类的结构,所以,我们形象的称之为:反射。

在这里插入图片描述

动态语言VS静态语言

动态语言

是一类在运行时可以改变其结构的语言:

例如新的函数、对象、甚至代码可以 被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运 行时代码可以根据某些条件改变自身结构。

主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang。

静态语言

与动态语言相对应的,运行时结构不可变的语言就是静态语言。

如Java、C、 C++。

Java不是动态语言

但Java可以称之为“准动态语言”。即Java有一定的动 态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。 Java的动态性让编程的时候更加灵活!

java反射提供的功能

  1. 在运行时判断任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时判断任意一个类所具有的成员变量和方法
  4. 在运行时获取泛型信息
  5. 在运行时调用任意一个对象的成员变量和方法
  6. 在运行时处理注解
  7. 生成动态代理

反射主要的类

  1. java.lang.Class:代表一个类
  2. java.lang.reflect.Method:代表类的方法
  3. java.lang.reflect.Field:代表类的成员变量
  4. java.lang.reflect.Constructor:代表类的构造器

反射我看来都是各种API的操作

通过(Class)(Method)(Field)(构造)等的API来完成运行时的java创建对象,修改属性,运行函数等的操作。

Class类

在Object类中定义了以下的方法,此方法 将被所有子类继承:

public final Class getClass()

该方法可以获取一个Class类,可以通过找个Class类从而获取该类下的属性和方法

在这里插入图片描述

获取类实例

想要操作一个类,首先就是获取找个类的类实例

获取Class实例

java程序中获得Class实例通常有如下3中方式,可以根据实际情况灵活选择

调用类或接口实例的getClass()方法

  1. getClass()方法是java.lang.Object类中的一个方法
  2. 所有的类和接口的实例都可以调用这个方法,该方法会返回该实例的所数类型所对应的Class实例
//创建一个Student类用来作为反射的演示
public class Student {
    
    

    private String name;
    private int 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;
    }
}

   public static void main(String[] args) {
    
    
//        创建学生类的对象
        Student student = new Student();
//        通过学生类对象获取Class实例
        Class aClass = student.getClass();
        System.out.println("我是什么类实例:"+aClass.getName());
    }

在这里插入图片描述

调用类或接口的class属性

  1. 在某些类或接口没有实例的情况下,可以通过其class属性获得对应的Class实例
  2. 这种方式需要在编译器就知道类或接口名称
 public static void main(String[] args) {
    
    

//        直接通过类的静态属性class获取类实例
        Class<Student> studentClass = Student.class;
        System.out.println("我是什么类实例:"+studentClass.getName());
    }

结果同上

使用Class.forName()方法

若编译时候无法确认具体类型,需要程序在运行时候根据情况来加载

可以使用Class类的forName()

该方法是静态方法,需要传入字符串参数,该字符串的参数是某个类的完全限定类名,包括包名(相当于路径了)

  public static void main(String[] args) {
    
    

        try {
    
    
//            通过Class类静态方法指定类路径获取指定Student类实例
            Class aClass = Class.forName("Reflection.Student");
            System.out.println("我是什么类实例:"+aClass.getName());
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }

获取到类实例之后,可以调用Class方法进行获取类实例的信息

Class的常用方法

方法 返回值 说明
getName() String 以字符串形式返回类型的名称(类名)
getSimpleName() String 一字符串形式返回该类的简称
getPackage() Package 获取该类所在包
getSuperclass() Class 返回该类的父类
getInterfaces() Class[] 返回该类实现的接口
getModifiers() int 返回该类型所有修饰符 由public,private,protected等对应的int常量组成 返回整数使用Modifier工具进行解码,判断访问修饰符的组成
getDeclaredClasses() Class[] 返回该类型中包含的全部内部类的Class实例
getDeclaringClass() class 返回该类型中的外部类的Class实例
newInstance Object 通过类实例创建对象

动态创建对象的两种方式

  1. 通过类实例的newInstance
  2. 通过构造函数的newInstance

Modifier(修饰符类)

该类表示的是修饰符类。

每个修饰符都对应Modifier的一个静态常量属性

在这里插入图片描述

根据其他反射API的getModifiers()来判断访问修饰符

Constructor(构造函数)

想要创建一个类的对象离不开构造函数。

获取构造函数

我们可以通过Class实例来获取构造函数对象,从而创建对象

返回值 方法名 说明
Constructor getConstructor(Class…params) 返回该类型指定参数列表的public构造函数 构造函数的参数列表为params eg:Constructor co = 类实例.getConstructor(String name,list.class)
Constructor[] getConstructors() 返回该类型的所有public构造方法
Constructor getDeclaredConstructor(Class…params) 返回该类型指定参数列表的构造函数,返回类型不限
Constructor[] getDeclaredConstructors() 返回该类型的所有构造函数访问级别不限

Constructor的常用方法

方法 描述
public int getModifiers() //得到构造方法的修饰符
public String getName() //得到构造方法的名称
public Class<?>[] getParameterTypes() //得到构造方法中参数的类型
public String toString() //返回此构造方法的信息
public T newInstance(Object.class…initargs) //向构造方法中传递参数,实例化对象

示例

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

//        通过Student类的class属性获取指定的类实例
        Class studentClass = Student.class;


//            通过类实例获取构造函数
        Constructor constructor = studentClass.getConstructor();
        System.out.println("构造函数名字:" + constructor.getName());
        System.out.println("构造函数的访问修饰符:" + constructor.getModifiers());

//        通过Constructor创建对象
        Object stu = constructor.newInstance();
        System.out.println("该对象是否属于Student类型"+ (stu instanceof Student));

    }

在这里插入图片描述

Field(属性类)

获取对应类型包括的属性的方法,通过反射获取类实例的属性信息

获取属性

返回值 方法名 描述
FieId getFieId(String name) 返回该类型中指定名称为public属性,name参数为指定属性名称、 eg:类实例.getFieId(“age”) 获得类的age属性
FieId[] getFieIds() 返回该类型中所有的publi修饰的
FieId getDeclaredFieId(String name) 返回该类型中指定名称的属性,与访问修饰符无关
FieId[] getDeclaredFieIds() 返回该类型中全部属性,与属性访问修饰符无关

Field常用的方法

返回值 方法名 描述
String getName() 获取属性的名
String getType() 获取属性的数据类型(int,String等)

示例

 public static void main(String[] args) throws Exception {
        //        通过Student类的class属性获取指定的类实例
        Class studentClass = Student.class;

//        获取指定的属性
//        不加上DeclareField的就是找public修饰的
        Field name = studentClass.getDeclaredField("name");

        System.out.println("属性的名字是:"+name.getName());
        System.out.println("属性的类型是:"+name.getType());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lOoijajj-1637986761777)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20211127114225257.png)]

Field的操作属性API

返回值 方法名 描述
xxx getXXX(Object obj) xxx表示8中基本数据类型之一 obj表示该属性所在类的实例(对象)
Object get(Object obj) 以Object类型返回obj中相关属性的值
void setXxx(Object obj,xxx val) 将Obj中相关属性的值设置为val,Xxx为8中基本数据类型之一
void set(Object obj,Object val) 将Obj中相关属性的值设置为val
void setAccessible(boolean flag) 对相关属性设置访问权限,设置为true可以禁止java语言访问检查(就是可以访问)

Method(方法类)

获取方法

返回值 方法名 描述
Method getMethod(String name,Class params) 返回该实例中指定public方法,name参数用于指定方法的名称,params表示的指定的参数列表
Method[] getMethods() 返回该类实例中的public方法
Method getDeclaredMethod(String name,Class params) 返回该类实例指定方法,与方法访问修饰符无关
Method[] getDeclaredMethods() 返回该类实例中的全部方法

Method常见的方法

返回值 方法名 描述
String getName() 获取方法名
String getReturnType() 获取返回值类型
Class[] getParameterTypes() 获取参数列表
int getModifiers() 获取访问修饰符
Class getDeclaringClass() 获取方法所属与的接口或方法
Class[] getExceptionTypes() 获取该方法抛出的异常

示例

下面都是基本的API调用。

只要思想不滑坡,利用这些API就可以做很多java动态代码

Method调用函数

Object invoke(Object obj ,Object args)
  1. obj是执行该方法的对象,表示的就是实例(对象)
  2. args是执行时候带入的参数
  3. 调用者就是方法,表示obj调用这个方法带入arge参数
  4. 若Method是静态方法,则obj可以为null
  5. args也可以是null

这一篇文章没有安装硅谷的写,是自己学习中的总结。

反射这一章节讲述的就是API。

おすすめ

転載: blog.csdn.net/weixin_46401545/article/details/121575292