当前位置: 首页 > news >正文

Java bs架构/反射

bs架构

规定的格式是要换行,而打印流天然换行 

 线程池可以直接处理thread,thread继承自runnable

在Java中,线程池的pool.execute()方法用于提交一个任务给线程池执行。这个方法接受一个Runnable对象作为参数。Runnable是一个函数式接口,因此你可以直接传递一个实现了Runnable接口的类的实例,或者使用lambda表达式。

所以,pool.execute()里面填的是Runnable类型。

例如:

java

复制

// 使用匿名内部类
pool.execute(new Runnable() {
    @Override
    public void run() {
        // 任务执行的代码
    }
});

// 使用lambda表达式
pool.execute(() -> {
    // 任务执行的代码
});

在Java 8及更高版本中,还可以使用方法引用。如果有一个已经定义好的方法,其签名与Runnablerun方法相匹配,可以直接使用方法引用。

例如:

java

复制

// 假设有一个方法叫做taskMethod,它没有参数且返回void
pool.execute(this::taskMethod);

这里的this::taskMethod就是方法引用,表示将taskMethod方法作为Runnablerun方法执行。

需要注意的是,pool.execute()方法不会返回任何结果。如果你需要任务执行完成后返回一个结果,应该使用pool.submit()方法,它接受一个Callable<T>对象作为参数,并返回一个Future<T>对象,用于获取任务执行的结果。、

thread runnable

在Java中,ThreadRunnable都是用于实现多线程的机制,但它们之间有一些关键的区别和联系:

  1. Thread类

    • Thread是一个类,它直接实现了Runnable接口。
    • 你可以创建一个Thread的子类并覆盖它的run方法来定义线程的行为。
    • Thread对象表示一个线程的执行实例。

    示例:

    java

    复制

    public class MyThread extends Thread {
        @Override
        public void run() {
            // 线程执行的代码
        }
    }
    
    MyThread myThread = new MyThread();
    myThread.start(); // 启动线程
    
  2. Runnable接口

    • Runnable是一个函数式接口,它只有一个方法:run
    • 你可以实现Runnable接口并定义run方法来创建一个线程任务。
    • Runnable本身并不表示一个线程,而是线程执行的任务。

    示例:

    java

    复制

    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 线程执行的代码
        }
    }
    
    Thread thread = new Thread(new MyRunnable());
    thread.start(); // 启动线程
    

关系

  • 实现方式Thread类实现了Runnable接口,这意味着每个Thread对象都是一个Runnable
  • 多态性:你可以将一个Runnable对象传递给Thread的构造函数,这样Thread就会执行Runnable中的run方法。
  • 灵活性:通过实现Runnable接口,你可以将线程的行为与线程的创建分离,这样可以在多个线程中共享相同的任务代码,提高代码的复用性。

使用场景

  • 当你想要自定义线程的行为并且不需要继承其他类时,可以继承Thread类。
  • 当你想要多个线程共享相同的任务代码,或者需要继承其他类时,可以实现Runnable接口。

启动线程

无论你使用Thread子类还是Runnable实现,都需要创建一个Thread对象并调用它的start方法来启动线程。start方法会调用run方法,但start会在新线程中执行run,而直接调用run则会在当前线程中执行。

总结

  • Thread是线程的执行实例,可以独立运行。
  • Runnable是线程执行的任务,需要通过Thread来运行。
  • Thread类实现了Runnable接口,提供了线程的创建和启动机制。
  • Runnable接口允许你定义线程的任务,但不直接创建线程。

反射获取成员方法

在Java中,使用反射API可以获取类的成员方法(Method),包括构造方法、公共方法、受保护方法、默认(包)访问方法和私有方法。以下是如何使用反射获取成员方法以及参数说明:

获取成员方法

要获取类的成员方法,你需要使用Class类提供的getMethodgetMethods方法。getMethod用于获取指定的公共成员方法,而getMethods用于获取所有公共成员方法。如果你想要获取包括私有和受保护方法在内的所有方法,可以使用getDeclaredMethodgetDeclaredMethods

Method类

Method类对象代表一个方法,它提供了用于获取方法信息的方法,如方法名、返回类型、参数类型等,以及用于调用方法的方法。

参数说明

以下是使用反射获取成员方法时常用的一些方法和参数说明:

  • Class<?> getDeclaringClass()

    • 返回表示声明该方法的类或接口的Class对象。
  • String getName()

    • 返回方法名。
  • int getModifiers()

    • 返回方法的修饰符,如publicprivatestatic等,返回值可以用于Modifier类的方法来分析。
  • Class<?> getReturnType()

    • 返回方法的返回类型。
  • Class<?>[] getParameterTypes()

    • 返回一个数组,包含方法的参数类型。
  • Class<?>[] getExceptionTypes()

    • 返回一个数组,包含方法抛出的异常类型。
  • Object invoke(Object obj, Object... args)

    • 在具有指定参数的指定对象上调用此Method对象表示的基础方法。
    • obj:从其上调用基础方法的对象(如果方法是静态的,则可以是null)。
    • args:用于方法调用的参数(如果方法没有参数,则可以是null)。

示例代码

以下是一个使用反射获取并调用成员方法的示例:

java

复制

import java.lang.reflect.Method;

public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // 获取Class对象
            Class<?> cls = Class.forName("java.lang.String");

            // 获取所有公共成员方法
            Method[] methods = cls.getMethods();

            // 遍历并打印方法信息
            for (Method method : methods) {
                System.out.println("方法名: " + method.getName());
                System.out.println("返回类型: " + method.getReturnType());
                System.out.println("参数类型: ");
                Class<?>[] parameterTypes = method.getParameterTypes();
                for (Class<?> parameterType : parameterTypes) {
                    System.out.println("  " + parameterType);
                }
                System.out.println("--------------------");
            }

            // 获取并调用指定的公共成员方法
            Method substringMethod = cls.getMethod("substring", int.class, int.class);
            String result = (String) substringMethod.invoke("Hello, World!", 7, 12);
            System.out.println("调用结果: " + result);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们首先获取了String类的Class对象,然后获取并打印了所有公共成员方法的信息。接着,我们获取了substring方法,并使用invoke方法调用了它,传递了字符串 "Hello, World!" 和两个整数参数 7 和 12

请注意,使用反射时可能会遇到各种异常,如ClassNotFoundExceptionNoSuchMethodExceptionIllegalAccessExceptionInvocationTargetException,因此需要适当地处理这些异常。

getDeclaredMethod 

是 Java 反射 API 中 Class 类的一个方法,用于获取类中声明的方法,包括公共、保护、默认(包)访问和私有方法。getDeclaredMethod 方法需要两个参数:方法名称和方法参数类型的 Class 对象数组。

参数说明:

  1. name (String 类型):

    • 说明:要获取的方法的名称。
    • 示例:如果方法名为 toString,则传递 "toString"
  2. parameterTypes (Class<?>... 类型,即 Class 对象的变长参数):

    • 说明:方法参数类型的 Class 对象数组。如果方法没有参数,则可以传递 null 或一个空数组。
    • 示例
      • 对于无参方法,可以传递 null 或 new Class<?>[0]
      • 对于有一个 int 类型参数的方法,可以传递 int.class
      • 对于有两个参数的方法,第一个参数为 String 类型,第二个参数为 int 类型,可以传递 new Class<?>[] {String.class, int.class}

返回值:

  • getDeclaredMethod 方法返回一个 Method 对象,该对象表示指定的方法。如果找不到该方法,将抛出 NoSuchMethodException

异常:

  • NoSuchMethodException:如果在该类中找不到指定名称和参数类型的方法。
  • SecurityException:如果请求的操作受到安全管理器的阻止。

示例代码:

java

复制

import java.lang.reflect.Method;

public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // 获取ReflectionExample类的Class对象
            Class<ReflectionExample> cls = ReflectionExample.class;

            // 获取名为"privateMethod"的私有方法,该方法接受一个String参数
            Method privateMethod = cls.getDeclaredMethod("privateMethod", String.class);

            // 输出方法信息
            System.out.println("方法名称: " + privateMethod.getName());
            System.out.println("返回类型: " + privateMethod.getReturnType());
            System.out.println("参数类型: ");
            for (Class<?> paramType : privateMethod.getParameterTypes()) {
                System.out.println(" - " + paramType.getName());
            }

        } catch (NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
    }

    // 一个私有方法,用于示例
    private void privateMethod(String param) {
        System.out.println("调用私有方法,参数: " + param);
    }
}

在这个示例中,我们尝试获取 ReflectionExample 类中名为 privateMethod 的私有方法,该方法接受一个 String 类型的参数。我们使用 getDeclaredMethod 方法来获取这个方法的 Method 对象,并打印出方法的相关信息。如果方法不存在或参数类型不匹配,将抛出 NoSuchMethodException

与越过泛型的约束 ——首先要有泛型才行

如果你原方法的参数类型是 String,那么在 getDeclaredMethod 中传入 Object 类型的 Class 对象是不行的。

getDeclaredMethod 方法要求你传入的参数类型数组必须与原方法的参数类型精确匹配。这是因为 Java 的方法重载解析是基于参数类型的,不同的参数类型对应不同的方法签名。

如果你原方法的声明是这样的:

java

复制

public void myMethod(String param) {
    // 方法实现
}

那么在调用 getDeclaredMethod 时,你应该这样传参:

java

复制

Method method = MyClass.class.getDeclaredMethod("myMethod", String.class);

如果你传入 Object.class,那么它会尝试查找一个参数类型为 Object 的方法,而不是 String。如果不存在这样的方法,就会抛出 NoSuchMethodException

java

复制

// 这将抛出 NoSuchMethodException,因为参数类型不匹配
Method method = MyClass.class.getDeclaredMethod("myMethod", Object.class);

总之,getDeclaredMethod 的参数类型数组必须与原方法的参数类型完全一致。如果你不确定原方法的参数类型,可以使用 getMethod 或 getDeclaredMethods 来获取所有方法,然后遍历并检查每个方法的参数

用户_uBiEPA

可是不是说反射可以越过泛型的约束?

ChatGLM

引用

是的,反射确实可以绕过泛型的约束,但这主要是指在处理泛型类型信息时,反射可以获取到泛型类型的具体类型参数,即使在运行时泛型信息会被擦除。然而,这并不意味着在调用 getDeclaredMethod 或其他反射方法时可以忽略方法签名中的具体参数类型。

当你使用反射来调用方法时,你仍然需要提供正确的方法名称和参数类型。泛型约束的绕过通常发生在以下情况下:

  1. 获取泛型字段的具体类型:即使字段是泛型的,反射可以告诉你它在某个具体实例中的实际类型。
  2. 绕过泛型方法参数的检查:你可以使用反射来调用一个泛型方法,并且传递不符合泛型约束的参数类型,因为泛型信息在运行时会被擦除。

例如,考虑以下泛型方法:

java

复制

public <T> void genericMethod(T param) {
    // 方法实现
}

在运行时,你可以使用反射来调用这个方法,并且传递任何类型的参数,即使它违反了泛型约束:

java

复制

Method method = MyClass.class.getDeclaredMethod("genericMethod", Object.class);
method.invoke(myObject, "String"); // 这里传递了String,即使泛型约束可能是其他类型

在这个例子中,我们传递了 Object.class 作为参数类型,并且传递了一个字符串作为参数。这之所以可行,是因为泛型信息在运行时被擦除,方法实际上接受的是 Object 类型的参数。

但是,这并不意味着你可以忽略方法签名中的具体参数类型。如果你有一个非泛型方法,其参数类型为 String,你仍然需要使用 String.class 来获取该方法:

java

复制

public void myMethod(String param) {
    // 方法实现
}

// 正确的获取方式
Method method = MyClass.class.getDeclaredMethod("myMethod", String.class);

// 错误的获取方式,将抛出 NoSuchMethodException
Method method = MyClass.class.getDeclaredMethod("myMethod", Object.class);

在这个例子中,如果你尝试使用 Object.class 来获取 myMethod,将会抛出 NoSuchMethodException,因为不存在一个接受 Object 类型参数的 myMethod

总结来说,反射可以绕过泛型约束,但在使用 getDeclaredMethod 时,你仍然需要提供与原方法签名匹配的参数类型。

框架

框架”(Framework)在计算机编程领域是一个广泛使用的概念,它指的是一套预设的代码结构和组件,用于简化特定类型应用的开发。框架提供了一种标准化的方式来构建软件,使得开发者可以专注于业务逻辑而不是底层实现。

为什么使用“框架”这个词?

  1. 结构支撑:“框架”一词来源于建筑领域,指的是建筑物的支撑结构。在软件开发中,框架同样提供了应用的支撑结构,确保开发的稳定性和一致性。

  2. 规范和约束:框架提供了一套规范和约束,指导开发者如何组织代码、如何实现功能,从而减少了出错的可能性。

  3. 复用性:框架通常包含了许多可复用的组件和库,开发者可以直接使用这些现成的功能,避免了重复造轮子。

  4. 加速开发:通过提供常见的功能和抽象复杂的底层实现,框架可以显著加快开发速度。

具体框架例子:

  • Spring Boot框架:是一个用于快速构建Java应用的框架。它简化了基于Spring的应用开发,使得开发者可以更轻松地创建、配置和运行应用。

  • PyTorch框架:是一个开源的机器学习库,主要用于构建和训练神经网络。它提供了丰富的API和工具,使得研究人员和开发者可以更高效地进行深度学习实验和开发。

为什么这些工具被称为“框架”?

  • Spring Boot:它提供了一个完整的架构,包括依赖注入、数据访问、安全性等功能,开发者只需要按照框架的规则填充具体的业务逻辑。

  • PyTorch:它为深度学习提供了一套完整的工具和组件,包括自动微分、神经网络层、优化器等,研究者可以在此基础上构建和训练模型。

总的来说,“框架”这个词在软件开发中用来描述那些提供结构、规范、复用性和加速开发能力的工具集。它们就像建筑的骨架一样,为软件的构建提供了坚实的基础

获取不同对象的所有字段

一个对象有4个成员变量,但构造器允许只有三个成员变量创建对象。我用反射作用在三变量的对象上,getdeclaredfields有几个?

ChatGLM

引用

如果一个对象有4个成员变量,但构造器允许只有三个成员变量创建对象,那么使用 getDeclaredFields() 方法反射获取这个类的成员变量时,返回的 Field 数组将包含所有声明的成员变量,即4个。

getDeclaredFields() 方法返回的是类中声明的所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。构造器中初始化的字段数量不会影响 getDeclaredFields() 返回的结果。

示例:

假设有一个类 MyClass,它有四个成员变量 abc 和 d,但构造器只接受三个参数:

java

复制

public class MyClass {
    private int a;
    private int b;
    private int c;
    private int d; // 这个字段在构造器中未被初始化

    public MyClass(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
        // d未被初始化,将保持默认值0
    }
}

使用反射获取所有声明的字段:

java

复制

MyClass obj = new MyClass(1, 2, 3);
Field[] fields = MyClass.class.getDeclaredFields();

System.out.println("Number of declared fields: " + fields.length); // 输出将是4

在这个例子中,getDeclaredFields() 将返回一个包含4个 Field 对象的数组,分别对应 abc 和 d 这四个成员变量。即使 d 在构造器中未被初始化,它仍然是类的一个声明字段,因此会被包含在返回的数组中。

注意事项:

  • getDeclaredFields() 返回的是类中声明的所有字段,不受构造器初始化字段数量影响。
  • 字段的访问修饰符(如私有、公共等)不会影响 getDeclaredFields() 的返回结果。
  • 如果需要获取继承的字段,可以使用 getFields() 方法,但它只返回公共字段,包括继承的公共字段。

总之,无论构造器如何初始化对象,getDeclaredFields() 总是返回类中声明的所有字段的数量。

 

相关文章:

  • 数据结构与算法之3.1 符号表
  • DeepSeek开源周开源的五个项目分析
  • openharmony—release—4.1开源鸿蒙源码编译踩坑记录
  • springboot中如何处理跨域
  • ZYNQ笔记(一):hello world
  • 如何在CentOS部署青龙面板并实现无公网IP远程访问本地面板
  • UE5中如何修复后处理动画蓝图带来的自然状态下的metablriger身体绑定形变(如耸肩)问题
  • SQL入门篇,数据库基础语法与核心操作
  • YOLOv8主干网络升级——融合ResNet18/34/50/101的高效特征提取架构设计
  • 天梯集训笔记整理
  • Git分布式版本控制系统从入门到精通(B站黑马)学习笔记
  • Spark-Core编程
  • Java 如何实现类的热加载和热部署?
  • jQueryHTML与插件
  • MySQL切换PolarDB-X方案
  • GOT-OCR2: 通用OCR理论:通过统一端到端模型迈向OCR-2.0时代
  • NSS#Round30 Web
  • c# 找到字符串中,固定字符串的位置
  • Ant Design X 和 Element-Plus-X
  • 人工智能图像识别spark安装
  • 做网站分什么软件/html网页设计模板
  • 网站设计属于什么经营范围/aso优化怎么做
  • 数据库支持的网站怎么做/山东大学经济研究院
  • 情人做网站/加快实施创新驱动发展战略
  • 手机网站的文本排版是怎么做的/竞价是什么意思
  • 东莞市做网站/找网络公司做推广费用