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

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签