Java 面试题:Java 的动态代理是基于什么原理?

编程语言通常有各种不同的分类角度,动态类型和静态类型就是其中一种分类角度,简单区分就是语言类型信息是在运行时检查,还是编译期检查。

与其近似的还有一个对比,就是所谓强类型和弱类型,就是不同类型变量赋值时,是否需要显式地(强制)进行类型转换。那么,如何分类 Java 语言呢?

通常认为,Java 是静态的强类型语言,但是因为提供了类似反射等机制,也具备了部分动态类型语言的能力。


文章目录

      • 1、面试问题
      • 2、问题分析
      • 3、典型回答
      • 4、问题深入
      • 5、问题拓展
        • 5.1、问题拓展:解释`InvocationHandler`和`Proxy`类的内部工作机制;
          • 5.1.1、`Proxy` 类
          • 5.1.2、`InvocationHandler` 接口
          • 5.1.3、工作机制
        • 5.2、问题拓展:论 Java 反射机制在动态代理中的作用及其性能影响以及及如何减少这些开销;
          • 5.2.1、反射在动态代理中的作用
          • 5.2.2、性能影响
          • 5.2.3、性能优化策略
        • 5.3、问题拓展:讨比较JDK动态代理与其他代理技术(如CGLIB)在性能方面的差异。
          • 5.3.1、JDK 动态代理
          • 5.3.2、CGLib
          • 5.3.3、性能比较
          • 5.3.4、应用场景
        • 5.4、问题拓展:讨论动态代理在实际开发中的具体应用,如在哪些场景下是不可替代的
          • 5.4.1、AOP(面向切面编程)
          • 5.4.2、事务管理
          • 5.4.3、远程方法调用(RMI)
          • 5.4.4、资源管理
          • 5.4.5、接口兼容性和适配器
          • 5.4.6、延迟加载
          • 5.4.7、安全访问控制
        • 5.5、问题拓展;探讨如何使用动态代理进行错误处理和异常管理
          • 5.5.1、实现动态代理的异常管理
          • 5.5.2、动态代理的异常处理优势


1、面试问题

今天的面试问题:Java 的动态代理是基于什么原理?


2、问题分析

这个面试题主要考察了以下几个关键点:

  1. 反射机制的理解:这个问题测试你是否了解 Java 中反射机制的基本概念,特别是如何在运行时动态创建代理类和对象。反射是动态代理实现的核心,允许程序在运行时查询对象的属性和调用对象的方法;
  2. 接口和代理设计模式的应用:通过动态代理的问题,面试官希望看到你是否理解代理设计模式的基本原理以及如何通过接口将代理类与实际执行类解耦,增强功能或进行访问控制;
  3. 适用场景的理解:面试官通过这个问题可能会进一步探讨你对动态代理应用场景的理解,比如在哪些情况下使用动态代理,它在 AOP(面向切面编程)、事务管理、日志记录等方面的应用。
  4. Java API 的熟悉程度:了解 java.lang.reflect.Proxy 和 ;java.lang.reflect.InvocationHandler 等关键类的使用方法和特性,显示出你对 Java API 的掌握程度。这是评估 Java 开发者技能的一个重要方面。

总体来说,这个问题不仅考察了技术细节,还考察了面试者在面对设计模式和架构选择时的决策能力。理解和应用动态代理可以帮助开发者在需要时实现代码的解耦和功能增强,是高级 Java 开发者的标志性技能之一。


3、典型回答

首先,Java 的动态代理是基于反射机制实现的高级功能,它允许我们在运行时动态创建代理类和对象,来代理实际对象,进行方法调用的中介处理。这一机制通过 Java 核心的反射 API 中的 Proxy 类和 InvocationHandler 接口实现。

其中实现的具体过程是:通过一个类加载器、一组接口及一个调用处理器作为输入参数,利用Proxy类的 newProxyInstance 方法在内存中动态创建一个实现指定接口的代理对象。该代理对象会将所有方法调用转发到实现了 InvocationHandler 接口的调用处理器的 invoke 方法中。

invoke 方法里,可以自定义方法调用前后的操作,如日志记录、权限检查和事务处理等。这使得动态代理不仅增强了程序的灵活性,而且有助于业务逻辑与系统服务的解耦。

此外,除了 JDK 内置的动态代理实现,还可以使用字节码操作技术如 ASM、CGLIB(基于ASM)和Javassist 等。这些技术提供了更底层的操作能力,比如允许直接针对类而非仅限于接口创建代理,适用于性能要求更高或需求更复杂的系统。


4、问题深入

如果继续深入,面试官可以从各种不同的角度考察,比如可以:

  • 原理的深入理解,比如:①、解释InvocationHandlerProxy类的内部工作机制;②、讨论 Java 反射机制在动态代理中的作用及其性能影响;
  • 性能优化,比如:①、讨论动态代理的性能开销及如何减少这些开销;②、讨比较JDK动态代理与其他代理技术(如CGLIB)在性能方面的差异。
  • 实际应用场景,比如:①、讨论动态代理在实际开发中的具体应用,如在哪些场景下是不可替代的;②、探讨如何使用动态代理进行错误处理和异常管理。

5、问题拓展

5.1、问题拓展:解释InvocationHandlerProxy类的内部工作机制;

Java 的 InvocationHandlerProxy 类是实现动态代理的关键组件,广泛应用于运行时动态创建代理类的情况,如远程方法调用、事务管理、日志记录等。这种机制主要依赖 Java 反射 API,使得开发者能够在运行时动态处理方法调用。

5.1.1、Proxy

Proxy 类提供了用于创建动态代理实例的静态方法。动态代理类是在运行时生成的类,它实现了指定的一组接口。

  • 创建动态代理实例

    :最常用的方法是

    Proxy.newProxyInstance()
    

    ,这个方法需要三个参数:

    1. 类加载器(ClassLoader):用来定义代理类的类加载器。
    2. 接口数组(Class[]):这是一个接口数组,代理类将实现这些接口。
    3. InvocationHandler 实现:当代理实例的方法被调用时,将会调用此处理器的 invoke() 方法。
5.1.2、InvocationHandler 接口

InvocationHandler 是一个接口,开发者需要实现它的 invoke() 方法来定义代理实例的行为。

  • invoke() 方法

    :这个方法有三个参数:

    1. 代理实例(proxy):调用该方法的代理实例。
    2. 方法对象(Method):对应于在代理实例上调用的接口方法的 Method 实例。
    3. 参数数组(args):调用接口方法时传递的参数。
5.1.3、工作机制

当代理实例的方法被调用时,调用将被重定向到 InvocationHandlerinvoke() 方法。invoke() 方法可以根据需要进行增强处理,如日志记录、事务处理、延迟加载等,然后可能通过反射调用实际对象的相应方法。

例如,如果你有一个接口 MyInterface 和实现该接口的类 MyImpl,你可以创建一个 InvocationHandler,在调用任何 MyInterface 的方法之前和之后执行特定操作。创建动态代理后,任何对 MyInterface 方法的调用都会转发给 InvocationHandler

示例代码:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface MyInterface {void doSomething();
}class MyImpl implements MyInterface {public void doSomething() {System.out.println("Doing something...");}
}class MyInvocationHandler implements InvocationHandler {private final MyInterface original;public MyInvocationHandler(MyInterface original) {this.original = original;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method call");Object result = method.invoke(original, args);  // 调用实际对象的方法System.out.println("After method call");return result;}
}public class ProxyExample {public static void main(String[] args) {MyInterface original = new MyImpl();MyInterface proxy = (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),new Class<?>[] {MyInterface.class},new MyInvocationHandler(original));proxy.doSomething();  // 调用代理的方法,这将触发 MyInvocationHandler 的 invoke 方法}
}

这个例子中:

  • MyInterface 是一个接口,MyImpl 是这个接口的一个具体实现;
  • MyInvocationHandler 实现了 InvocationHandler 接口,用于定义在调用方法前后要执行的操作;
  • 使用 Proxy.newProxyInstance() 创建了一个 MyInterface 的代理实例。当调用 proxy.doSomething() 时,实际上会通过 MyInvocationHandlerinvoke() 方法进行调用。
5.2、问题拓展:论 Java 反射机制在动态代理中的作用及其性能影响以及及如何减少这些开销;

Java 反射机制在动态代理中的作用是核心的,但同时也会对性能产生一定的影响。下面将详细讨论这两个方面:

5.2.1、反射在动态代理中的作用
  1. 接口方法的动态调用:反射允许动态代理在运行时查找并调用方法。当代理类的一个方法被调用时,InvocationHandlerinvoke 方法就会被触发,这个方法利用反射来决定哪一个方法应该被调用,以及如何传递参数。

  2. 无需硬编码:使用反射,开发者无需在编写代码时就确定要调用哪些类和方法。这使得代码更加灵活和可扩展,因为可以在运行时动态加载和调用类和方法。

  3. 适用性广泛:反射使得动态代理不仅可以用于实现已知的接口,还可以动态地应对程序扩展中新增的接口,提高了代码的复用性和模块间的解耦能力。

5.2.2、性能影响

尽管反射在动态代理中提供了极大的灵活性和强大的功能,它也有一些性能上的不足:

  1. 性能开销:反射操作本质上比直接方法调用更慢。这是因为反射涉及到类型检查和方法调用解析等额外的处理步骤。每次通过反射调用方法时,JVM 都需要检查方法的访问权限,并且在调用前将参数类型匹配到方法的参数类型;

  2. 内存消耗:使用反射的动态代理可能会额外消耗更多内存,因为 JVM 需要为被代理的方法以及相关的数据结构(如 Method 对象)分配内存;

  3. 优化限制:使用反射调用方法通常不能享受到 JIT 编译器的一些优化,如内联展开等,这进一步影响了性能。

5.2.3、性能优化策略

尽管反射带来了性能挑战,但可以采取一些措施来缓解这些问题:

  • 缓存反射对象:可以缓存关键的反射对象(如 Method 实例),以减少查找和创建这些对象的开销;
  • 限制代理类数量:避免过度使用动态代理,特别是在性能敏感的应用场景中,因为每一个代理类都会增加额外的运行时开销;
  • 使用第三方库:例如 CGLib 或 ByteBuddy 等库可以通过生成字节码来创建代理,而不是使用 Java 原生的反射,这样可以提高性能。

总之,虽然反射和动态代理提供了极大的灵活性和强大的功能,但在使用时需要权衡其带来的性能开销。在设计系统时,合理选择使用动态代理的场景,并采取适当的优化措施,是提高系统性能的关键。


5.3、问题拓展:讨比较JDK动态代理与其他代理技术(如CGLIB)在性能方面的差异。

在 Java 中,动态代理主要有两种常见的实现方式:JDK 动态代理和第三方库,如 CGLib。这两种技术在性能和适用性方面都有各自的特点和差异。

5.3.1、JDK 动态代理

JDK 动态代理使用 Java 自带的代理类库来实现,它依赖于反射(java.lang.reflect 包)和接口:

  • 基于接口:JDK 动态代理只能代理接口,不支持类。这意味着只有实现了接口的类才可以被代理;
  • 性能影响:由于 JDK 代理基于反射实现,其性能通常不如直接方法调用。尽管 Java 的反射性能在近年有所改进,但反射调用仍然比直接调用慢;
  • 内存和加载时间:JDK 代理的加载时间相对较短,内存消耗较少,因为它只需要生成实现指定接口的代理类。
5.3.2、CGLib

CGLib(Code Generation Library)是一个强大的、高性能的代码生成库,它使用字节码增强技术(通过继承类)来实现代理,而不仅仅是基于接口:

  • 基于类的代理:CGLib 可以代理没有实现接口的类,因此它比 JDK 动态代理更为灵活;
  • 性能优势:CGLib 在运行时生成的是具体类的子类,并覆盖其中的方法。相比于 JDK 的反射机制,CGLib 通常能提供更好的性能,因为它直接操作字节码,避免了反射调用的开销;
  • 内存和加载时间:CGLib 生成的代理类比 JDK 代理更复杂,可能会导致更长的加载时间和更高的内存消耗。此外,CGLib 在生成代理类时需要处理更多的字节码操作,这在初次加载时可能导致性能开销。
5.3.3、性能比较
  1. 调用速度:CGLib 代理的方法调用通常比 JDK 代理快,因为它避免了使用反射。CGLib 直接修改字节码,减少了调用时的计算量;
  2. 启动速度:JDK 动态代理在生成代理类时较快,因为它仅涉及到简单的接口实现。而 CGLib 在启动时可能需要更多时间来生成字节码;
  3. 资源消耗:CGLib 由于在运行时创建较复杂的类,可能会消耗更多内存。JDK 动态代理则相对节省资源。
5.3.4、应用场景

如果你的类已经实现了接口,或者你只需要代理接口方法,JDK 动态代理是一个简单而高效的选择;

如果你需要代理没有实现接口的类,或者追求最佳性能,CGLib 是更好的选择。

总的来说,选择哪种代理技术取决于具体需求、性能考量和代理对象的特点。在不需要处理接口的情况下,CGLib 的性能优势通常会使它成为更受欢迎的选择。

5.4、问题拓展:讨论动态代理在实际开发中的具体应用,如在哪些场景下是不可替代的

动态代理在实际开发中扮演了非常重要的角色,尤其是在需要增强或修改原有类行为而不改变原有代码的情况下。以下是一些具体的应用场景,展示了动态代理的价值和不可替代性:

5.4.1、AOP(面向切面编程)

AOP 是动态代理应用最广泛的领域之一,尤其在如 Spring 框架中。通过动态代理,可以在不修改原有代码的基础上,为方法调用提供横切关注点(如日志记录、事务管理、安全检查等)的处理。这种方式使得关注点分离,增强了代码的可维护性和复用性。

5.4.2、事务管理

在企业应用中,事务管理是必不可少的功能,特别是在数据库操作中。通过使用动态代理,可以自动地为业务方法调用加入事务处理逻辑,如开启事务、提交或回滚事务。这样做可以避免将事务管理代码硬编码到业务逻辑中,提高代码的清晰性和可维护性。

5.4.3、远程方法调用(RMI)

动态代理常用于实现远程方法调用的客户端逻辑。在 Java RMI 或其他远程调用框架如 Spring 的 Remoting 中,客户端可以通过动态代理透明地调用远程服务。代理对象负责将本地接口调用转换为网络请求,并处理来自服务端的响应,对用户来说,远程调用与本地调用无异。

5.4.4、资源管理

动态代理可以用于智能资源管理,如数据库连接和线程池的管理。代理可以控制资源的分配和释放,确保例如数据库连接始终在使用完毕后被正确关闭,从而避免资源泄露。

5.4.5、接口兼容性和适配器

在需要适配旧版本接口到新的实现时,动态代理可以充当适配器的角色,无需修改现有代码。这种方式非常适合在升级和维护大型遗留系统时,为旧接口提供新的实现。

5.4.6、延迟加载

动态代理可以用于实现延迟加载(懒加载),特别是在处理大型对象或复杂对象关系时。例如,代理可以控制只有在实际需要时才加载对象的某些部分,从而减少系统的初始化时间和运行时的内存消耗。

5.4.7、安全访问控制

动态代理还可以用于增强安全性,通过代理控制对敏感方法的访问。代理可以在方法执行前进行安全检查,如验证用户权限,确保只有具备相应权限的用户才能执行某些操作。

这些应用场景展示了动态代理在解耦、增强方法、处理交叉关注点等方面的巨大优势。在现代软件开发中,动态代理技术是实现中间件、框架和各种库的一个不可或缺的工具,它提供了一种强大且灵活的方法来动态修改和增强对象的行为。

5.5、问题拓展;探讨如何使用动态代理进行错误处理和异常管理

使用动态代理进行错误处理和异常管理是一种增强应用程序健壮性的有效技术。通过动态代理,开发者可以在不修改原有业务逻辑代码的情况下,集中处理方法调用过程中可能发生的异常。这种模式在企业级应用中非常常见,特别是在需要统一异常处理逻辑的系统中。

5.5.1、实现动态代理的异常管理

动态代理允许开发者在一个集中的位置拦截方法调用,并在这个层面上实施异常处理策略。以下是实现此功能的基本步骤:

  1. 定义业务接口:首先定义一个或多个业务逻辑接口,这些接口包含了应用程序中需要执行的方法;

  2. 实现业务逻辑:实现这些接口,编写具体的业务逻辑;

  3. 创建动态代理:使用 JDK 动态代理或第三方库(如 CGLib),创建一个代理类,该类在内部使用 InvocationHandler

  4. 编写 InvocationHandler 实现:在 InvocationHandlerinvoke 方法中,实现异常捕获和处理逻辑。这允许你在方法执行前后添加额外的处理,比如异常日志记录、异常转换、重试逻辑等;

  5. 使用代理实例:在应用程序中,使用动态代理实例代替原始业务对象。所有对原始对象的方法调用都会通过代理,并由代理中的异常处理逻辑处理。

示例代码:

以下是使用 JDK 动态代理进行异常管理的简单示例:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface Service {void process() throws Exception;
}class ServiceImpl implements Service {public void process() throws Exception {// 模拟业务逻辑System.out.println("Processing service");throw new Exception("Something went wrong!");}
}class ExceptionHandlingInvocationHandler implements InvocationHandler {private Object target;public ExceptionHandlingInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {return method.invoke(target, args);} catch (Exception e) {handleException(e);return null;  // 根据具体需求返回适当的值或抛出自定义异常}}private void handleException(Exception e) {// 统一异常处理逻辑System.out.println("Handled exception: " + e.getMessage());}
}public class ProxyExample {public static void main(String[] args) {Service realService = new ServiceImpl();Service proxyService = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(),new Class<?>[]{Service.class},new ExceptionHandlingInvocationHandler(realService));try {proxyService.process();} catch (Exception e) {System.out.println("Exception: " + e.getMessage());}}
}
5.5.2、动态代理的异常处理优势
  • 集中管理:可以在一个地方集中管理所有异常处理逻辑,提高代码的可维护性;
  • 解耦:将异常处理逻辑从业务代码中解耦,使业务逻辑更加清晰;
  • 灵活性:可以灵活地添加或修改异常处理策略而不需要修改业务逻辑代码;
  • 重用性:相同的异常处理逻辑可以应用到多个服务或组件上。

动态代理提供了一种强大的方式来增强方法调用,包括统一的异常处理,这在构建大型、复杂的系统时尤为重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/21357.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Stage #1 无过滤的XSS注入:基础与实操

Stage #1 无过滤的XSS注入&#xff1a;基础与实操 跨站脚本攻击&#xff08;XSS&#xff09;是Web安全领域中一种常见的攻击手段。在"XSS Challenges"闯关游戏中&#xff0c;Stage #1专为初学者设计&#xff0c;用于练习无过滤的XSS注入技术。本文将详细介绍这一阶段…

Linux命令篇(六):vi/vim专项

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝您生活愉快&#xff01; 文章目录 一、什么是vim二…

Microsoft Outlook Lite 引入短信功能

随着科技的不断进步&#xff0c;我们的沟通方式也在不断演变。微软最新推出的 Outlook Lite 应用&#xff0c;不仅为我们提供了一个轻量级的电子邮件管理工具&#xff0c;现在更是带来了一项令人兴奋的新功能——短信服务。 Outlook Lite&#xff1a;轻量级&#xff0c;功能全…

【.Net】Linq的使用

文章目录 一、Linq介绍二、在两个数据源联合查询中的使用三、Linq的其他用法 一、Linq介绍 LINQ&#xff08;Language Integrated Query&#xff09;是C#中的一个强大功能&#xff0c;允许您使用统一的语法查询和操作来自不同数据源的数据。 二、在两个数据源联合查询中的使用…

今日好料推荐(ARM嵌入式)

今日好料推荐&#xff08;ARM嵌入式&#xff09; 参考资料在文末获取&#xff0c;关注我&#xff0c;获取优质资源。 给我留言&#xff0c;会帮大家寻找需要的资料。 ARM 嵌入式系统 嵌入式系统在现代电子设备中扮演着至关重要的角色&#xff0c;从智能手机到工业自动化&am…

深入了解 C 语言 Bug

目录 一、引言二、Bug的定义三、Bug的由来四、Bug的影响五、应对 Bug 的方法六、结论 一、引言 1、在 C 语言的编程世界中&#xff0c;Bug 是一个我们无法回避的话题。 2、Bug&#xff0c;简单来说&#xff0c;就是程序中存在的错误或缺陷。它可以表现为程序运行结果的异常、崩…

HALCON-从入门到入门-形态学操作-千变万化的region

1.废话 计算机视觉中的形态学操作是一种基本的数字图像处理技术&#xff0c;主要用于图像的形态结构改变&#xff0c;以便执行前后景分割、形状检测等任务。 膨胀&#xff08;Dilation&#xff09;&#xff1a; 膨胀操作是将结构元素在图像上滑动&#xff0c;如果结构元素与图…

CMakeFile.txt通过sysroot方式后生成makefile报错

报错信息如下&#xff1a; -- The C compiler identification is unknown -- The CXX compiler identification is unknown -- Check for working C compiler: /home/xj/asm/host/bin/aarch64-buildroot-linux-gnu-gcc -- Check for working C compiler: /home/xj/asm/host/bi…

Vue CLI:Vue CLI是一个强大的工具,可以帮助开发者快速地创建和管理Vue项目。我们可以讨论它的一些核心特性,比如热重载、懒加载等

Vue CLI简介 Vue CLI简介 Vue CLI,全称Vue Command Line Interface,是一个基于Vue.js进行快速开发的完整系统。它帮助开发者通过提供一整套工具来提高项目的开发效率。Vue CLI包括了从项目创建到代码调试,再到最终打包部署的全流程式的解决方案。 定义和用途 Vue CLI的…

VScode远程连接linux服务器开发,误删了文件怎么找回。

VScode远程连接linux服务器开发&#xff0c;误删了代码文件 因为远程服务器大家都在用&#xff0c;没有足够权限去折腾。找遍了没找到方法&#xff0c;就告诉我远程的文件本地没有缓存啊&#xff01;我就差点开始重写代码了。 后来被我发现了TIMELINE功能&#xff0c;这个功能…

YUM安装httpd实验配置apache

实验目的及实验要求&#xff1a; 实验目的&#xff1a; 2.实验要求&#xff1a; &#xff08;1&#xff09;完成命令的编写&#xff0c;并能正确运行&#xff1b; &#xff08;2&#xff09;从中熟练掌握命令的功能及作用。 实验设备及软件&#xff1a; pc机 配置好Lin…

【推荐系统-特征工程】把item的tag加工为特征的三种方式

1&#xff0c;高订单tag的top1-10的tag-id&#xff0c;作为user的单侧共10维特征的value 即一个list作为user单侧特征 缺点&#xff1a;丢失了user对每个tag的订单数量和tag-rank10以外的tag信息 2&#xff0c;高订单tag的top1-10的订单量&#xff0c;和高订单tag的top1-10的t…

叉积和法向量学习笔记

目录 叉积用的内积 相似点 给定平面上的两个向量 A 和 B&#xff0c;叉积和法向量相等吗 理解这点的关键&#xff1a; 结论&#xff1a; 叉积判断平面内两个向量是否相交 叉积&#xff08;Cross Product&#xff09;和法向量&#xff08;Normal Vector&#xff09;确实有…

GPT-4o能力评价与个人感受

GPT-4o是OpenAI最新推出的人工智能模型&#xff0c;与其前身GPT-4相比有了显著的提升。以下是对GPT-4o技术能力的评价以及版本间的对比分析和个人整体感受。 技术能力 1. 多模态能力&#xff1a; GPT-4o具备真正的多模态能力&#xff0c;能够处理和生成文本、音频和视觉输入和…

js 给数组对象添加多个属性

// 假设有一个数组对象 let items [{ id: 1, name: Item 1 },{ id: 2, name: Item 2 },{ id: 3, name: Item 3 } ];// 要添加的新属性 const newProps {newProp1: value1,newProp2: value2 };// 使用map方法添加新属性 let updatedItems items.map(item > ({ ...item, ..…

什么是AI应用开发

&#x1f9d9;‍♂️ 诸位好&#xff0c;吾乃斜杠君&#xff0c;编程界之翘楚&#xff0c;代码之大师。算法如流水&#xff0c;逻辑如棋局。 &#x1f4dc; 吾之笔记&#xff0c;内含诸般技术之秘诀。吾欲以此笔记&#xff0c;传授编程之道&#xff0c;助汝解技术难题。 &#…

【AR开发-开源框架】使用Sceneform-EQR快速开发AR应用,当前接入了AREngine、ORB-SLAM,可快速地适配不同的安卓设备

Sceneform-EQR Sceneform 概览 Sceneform是一个3D框架&#xff0c;具有基于物理的渲染器&#xff0c;针对移动设备进行了优化&#xff0c;使您可以轻松构建增强现实应用程序&#xff0c;而无需OpenGL。 借助 Sceneform&#xff0c;您可以轻松地在 AR 应用和非 AR 应用中渲染…

音乐版权NFT开发流程

开发音乐版权NFT&#xff08;非同质化代币&#xff09;的流程涉及多个步骤&#xff0c;从概念化和版权管理到技术实现和市场推广。以下是一个详细的开发流程指南。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.概念化与规划 定义…

使用git

解决参考如下链接 git设置全局用户名和邮箱以及删除方式

【Qt系列教程】一、认识Qt、安装Qt、运行Hello Qt

文章目录 1.1 Qt 简介1.2 Qt 的安装1.3 编写 Hello World 1.1 Qt 简介 Qt&#xff08;官网&#xff1a;https://www.qt.io&#xff09;于1995年5月首次公开发布&#xff0c;是一个跨平台的应用程序开发框架&#xff0c;也是最主流的 C 开发框架&#xff1b; Qt 具有其他编程…