Java反射(通过反射获取构造函数、方法、属性)_java 反射构造函数-程序员宅基地

技术标签: Java  java  开发语言  

目录

1.通过反射获取构造函数

2.通过反射获取方法

 3.通过反射调用成员属性


1.通过反射获取构造函数

Class类获取构造函数的方法如下:

方法名 作用
getConstructor(Class<?>... parameterTypes) 获取指定参数类型的公共构造函数
getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型的构造函数,可以是公共、私有或受保护的构造函数
getConstructors() 获取所有公共构造函数
getDeclaredConstructors() 获取所有构造函数,可以是公共、私有或受保护的构造函数

所有通过Class类获取到的构造函数都需要用到java.lang.reflect.Constructor类的对象来接收

以下是Constructor类的常用方法:

方法名 作用
newInstance(Object... initargs) 使用此构造函数对象创建一个新对象
getParameterTypes() 获取构造函数的参数类型数组
getModifiers() 获取构造函数的修饰符
getName() 获取构造函数的名称
getExceptionTypes() 获取构造函数声明抛出的异常类型数组
isAccessible() 检查构造函数是否可访问
setAccessible(boolean flag) 设置构造函数的可访问性

案例代码:

package Example1705;
import java.lang.reflect.Constructor;
class Member{
    private String str;
    Member(){
        System.out.println("无参构造");
    }
    Member(String str){
        this.str = str;
        System.out.println("单参构造方法");
    }
    Member(String str, int i,double d){
        System.out.println("多参数构造方法");
    }

    @Override
    public String toString() {
        return "Member{" +
                "str='" + str + '\'' +
                '}';
    }
}
public class javaDemo {
    public static void main(String[] args) throws  Exception{
        Class<?> clazz= Member.class;
        Constructor<?>[] cons = clazz.getDeclaredConstructors();
//        输出类中所有构造函数
        for (Constructor<?> con:cons) {
            System.out.println(con);
        }
//        获取单参构造方法
        Constructor<?> one = clazz.getDeclaredConstructor(String.class);
        Object obj = one.newInstance("我是你爷爷");
        System.out.println(obj);
    }
}

 问1:什么是构造函数的修饰符

答1:构造函数的修饰符是指用来修饰构造函数访问级别和特性的关键字。在Java中,构造函数可以使用以下修饰符:public、protected、private和默认(无修饰符)。这些修饰符决定了外部是否可以访问该构造函数以及哪些代码可以使用它来创建对象。

  • public修饰符表示构造函数对所有类可见,可以被任意代码调用。
  • protected修饰符表示构造函数对同一包内的类和所有子类可见,可以被同包内的类和子类调用。
  • private修饰符表示构造函数只对本类可见,只能在本类中调用。
  • 默认(无修饰符)表示构造函数对同一包内的类可见,但对其他包中的类不可见,只能在同包内调用。

问2:为什么代码:

Constructor<?> one = clazz.getDeclaredConstructor(String.class);

里面参数是String.class而不是直接String,那么如果调用int ,char,double又该如何表示呢?

答2:代码Constructor<?> one = clazz.getDeclaredConstructor(String.class);中的参数是String.class而不是直接String,是因为Java中的反射API通过.class来获取类的Class对象。.class是Java语言用于获取类的Class对象的语法,可以用于获取各种类型的Class对象。

如果要调用的构造函数具有int、char、double等基本数据类型的参数,可以使用相应的包装类的.class来表示,例如:

  • int:int.class
  • char:char.class
  • double:double.class

通过使用包装类的.class,可以获取对应基本数据类型的Class对象,并在获取构造函数时进行使用。


2.通过反射获取方法

Class类获取方法信息的方法如下:

方法 作用
getDeclaredMethods() 获取当前类声明的所有方法,包括公共、保护、默认和私有方法。
getMethods() 获取当前类以及从父类继承的公共方法。
getDeclaredMethod(String name, Class<?>... parameterTypes) 获取指定名称和参数类型的方法,包括私有方法。
getMethod(String name, Class<?>... parameterTypes) 获取指定名称和参数类型的公共方法,包括从父类继承的方法。

 同样Class获取的方法都需要通过java.lang.reflect.Method类对象来接收

以下是Method类的常用方法:

方法 作用
getName() 获取方法的名称。
getReturnType() 获取方法的返回类型。
getParameterTypes() 获取方法的参数类型数组。
getModifiers() 获取方法的访问修饰符,返回一个整数值,可以使用Modifier类的方法解析该值。例如,可以使用Modifier.isPublic(modifiers)检查方法是否为public。
isVarArgs() 检查方法是否使用可变参数。
isAccessible() 检查方法是否可访问(即是否可以通过反射调用)。
invoke(Object obj, Object... args) 调用方法,传入特定的对象作为方法的所有者,以及方法的参数。
setAccessible(boolean flag) 设置方法的可访问性。如果设置为true,则可以绕过Java语言访问权限检查,强制访问私有方法。
getAnnotation(Class<T> annotationClass) 获取方法上指定注解类型的注解对象。
getDeclaredAnnotations() 获取方法上声明的所有注解对象的数组。
getExceptionTypes() 获取方法声明的异常类型数组。
getDefaultValue() 获取方法的默认值(仅适用于接口方法)。
isDefault() 检查方法是否为默认方法(在接口中定义的具有默认实现的方法)。
getParameterCount() 获取方法的参数个数。

案例代码:

package Example1707;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

class Test{
    public void FUnction1(){}
    public String Function2(){
        return "调用return type为String函数";
    }
    private void Function3(){
        System.out.println("private修饰符的方法");
    }
    private String Funtion4(){
        return "私有化返回String的函数";
    }
}
public class javaDemo {
    public static void main(String[] args) {
        Class<?> clazz = Test.class;
        Method methods[] = clazz.getDeclaredMethods();
        for (Method m:methods) {
//            输出修饰符
            int x = m.getModifiers();
            System.out.println(Modifier.toString(x)+" "+m.getReturnType().getSimpleName()+" "+m.getName()+"()");
        }
    }
}

 问1:在类中构造方法是否也算是其中的方法,在代码中定义构造函数是否也会被输出?

构造方法也算作类中的一种方法。在使用反射获取类的所有方法时,构造方法也会被包含在内,并可以通过反射的方式获取和操作。

在你提供的示例代码中,使用反射获取了 Test 类的所有方法,并输出了每个方法的修饰符、返回类型和名称。注意,这里的方法包括普通方法和构造方法。

所以,如果 Test 类中定义了构造方法,那么在你的示例代码中输出部分会包含构造方法的信息。构造方法的输出格式与普通方法相同,只是返回类型是 void,方法名与类名相同。

如果你想要单独输出构造方法的信息,可以通过判断 Method 对象是否为构造方法来实现。可以使用 m.getName().equals("<init>") 来判断一个方法是否是构造方法(构造方法的特点是方法名为 <init>)。


 3.通过反射调用成员属性

通过反射获取成员属性与一般获取并不相同,一般来说当一个成员的属性的修饰符为private私有后在主类之中并不能进行调用。但是通过反射是可以得到将私有化的成员属性的

下面介绍Class类获取类中成员属性的方法:

方法 描述
getDeclaredFields() 返回类中所有声明的成员属性(不包括继承的属性),包括公共、受保护、默认(包)访问和私有属性。
getDeclaredField(String name) 根据属性名获取类中指定的成员属性(不包括继承的属性),包括私有属性。
getField(String name) 根据属性名获取类中指定的公共成员属性(包括继承的公共属性),无法获取私有属性。

和前面都一样对于class获取到的成员属性,需要用java.lang.reflect.Field类的实例进行接收

下面介绍Field类的常用方法:

方法 描述
Class<?> getType() 返回属性的类型。返回值为 Class 对象,可以使用 getName() 方法获取类的名称。
void set(Object obj, Object value) 设置给定对象上此属性的值。
Object get(Object obj) 获取给定对象上此属性的值。
int getModifiers() 返回属性的修饰符。可以通过 java.lang.reflect.Modifier 类的静态方法来解析修饰符的信息。
void setAccessible(boolean flag) 设置访问标志,使得私有属性可被访问。

案例:

package Example1708;

import java.lang.reflect.Field;

class Person{
    public String name;
    private int age;
    public String sex;
    
}
class Student extends Person{
    private String School;
}

public class javaDemo {
    public static void main(String[] args) throws Exception{
//        输出School中的成员属性
        Class<?> clazz= Student.class;
        Field fields[] = clazz.getDeclaredFields();
        for (Field f:fields) {
            System.out.println(f);
        }
//        输出子类父类其中的成员属性
        Class<?> parent = clazz.getSuperclass();
        Field fieldss[] = parent.getDeclaredFields();
        for (Field f:fieldss) {
            System.out.println(f);
        }
        Object obj = clazz.getDeclaredConstructor().newInstance();
        Field secreat = clazz.getDeclaredField("School");
//        设置私有允许访问
        secreat.setAccessible(true);
        secreat.set(obj,"东方红小学");
        System.out.println(secreat.get(obj));
    }
}

 

 注意:在实际的项目开发过程中很少有直接使用反射来对成员进行操作的,而一般都会用setter,getter方法。但是在项目开发过程中getType方法是用得比较多的,用来确定属性类型,下面是案例代码

假设有一个名为 Person 的类,它具有属性 nameage

public class Person {
    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;
    }
}

在使用反射时,可以使用 getType 方法来获取属性的类型。例如,我们想要获取 Person 类中的所有属性的类型:

import java.lang.reflect.Field;

public class ReflectionExample {
    public static void main(String[] args) {
        Person person = new Person();

        Class<? extends Person> clazz = person.getClass();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            Class<?> fieldType = field.getType();
            System.out.println("属性名:" + field.getName());
            System.out.println("属性类型:" + fieldType.getName());
            System.out.println("-------------------------");
        }
    }
}

以上代码使用反射获取了 Person 类中的所有属性,并打印出了每个属性的名称和类型。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dogxixi/article/details/132024441

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法