final关键字与Java编译器的小坑

Halcon 深度学习实战:PCB 缺陷检测模型的 TensorRT/OpenVino 加速推理 本文介绍了如何利用TensorRT和OpenVino对Halcon深度学习模型进行加速优化,以提升PCB缺陷检测系统的实时性能。文章详细阐述了模型加速框架的选择策略(根据硬件选用TensorRT或OpenVino)、优化流程实施(包括混合精度优化和模型导出)以及加速后的推理实现。实验结果表明,优化后的模型体积缩小40%,推理速度提升2-5倍(GPU环境下从79ms降至38ms,CPU环境下从3804ms降至2152ms),同时保持检测精度。通过完整的代码示例展示了从模型加速到实际部署的全流程,为工业视觉场景 阅读详情

一、背景引入

近期在开发一个项目的后台时,使用到了邮件发送的服务。由于考虑变化的可能性不大,将邮箱地址和发信服务器使用final static修饰符定义在一个util类中,并在发信代码中调用(而没有做成配置文件,其实后来想想,还是需要做成配置文件会更稳妥些),后面升级到服务器时发现邮箱地址需要改动,于是修改了util类中的变量内容,并将编译之后的util类的class文件覆盖到线上,结果发信地址仍然没有变化…(坑爹啊!)

组里的学长机智地将发信的程序的class文件抓取下来,本地反编译,竟然发现了:邮箱地址和发信服务器等使用final修饰的数据,在外部被引用的地方,被Java编译器直接编译成了常量,故单纯替代util类无法修正错误,后面对引用和工具类进行一并更新才解决了这个问题。


二、实操下

1、final+static

public class Link {
    public final static String linkStr = "STRING1";
}

public class MainClass {
    public static void main(String[] args) {
        String localStr = Link.linkStr;
        System.out.println(localStr);
    }
}

程序运行正常,打开编译后的class文件并反编译,可以看到:

import java.io.PrintStream;

public class MainClass
{

    public MainClass()
    {
    }

    public static void main(String args[])
    {
        String localStr = "STRING1";
        System.out.println(localStr);
    }
}


2、final修饰

public class Link {
    public final String linkStr = "STRING1";
}

public class MainClass {
    public static void main(String[] args) {
        Link link = new Link();
        String localStr = link.linkStr;
        System.out.println(localStr);
    }
}

程序运行正常,打开编译后的class文件并反编译,可以看到:

import java.io.PrintStream;

public class MainClass
{

    public MainClass()
    {
    }

    public static void main(String args[])
    {
        Link link = new Link();
        link.getClass();
        String localStr = "STRING1";
        System.out.println(localStr);
    }
}


可见,static与否并不会影响Java的编译。

3、final+static+运行时初始化

public class Link {
    public final static String linkStr;// = "STRING1";
    static{
        linkStr = "STRING1";
    }
}

public class MainClass {
    public static void main(String[] args) {
        String localStr = Link.linkStr;
        System.out.println(localStr);
    }
}

打开编译后的class文件:

import java.io.PrintStream;

public class MainClass
{

    public MainClass()
    {
    }

    public static void main(String args[])
    {
        String localStr = Link.linkStr;
        System.out.println(localStr);
    }
}

这个不难理解,因为在编译的阶段,Link的linkStr变量还没有初始化,尽管它是final修饰的。此时如果注释掉static代码块的初始化逻辑,编译器将报错,因为编译器会保证final修饰的变量必须进行初始化。


三、设计的动机

在网上查看了一些博客,没有较为切确的解释,我认为这是Java一个优化设计:即把运行时的开销提前到编译时支出,从而提高程序的运行性能。此外,对于final修饰的方法,网上有解释如下:


当一个方法被修饰为final方法时,意味着编译器可能将该方法用内联(inline)方式载入,所谓内联方式,是指编译器不用像平常调用函数那样的方式来调用方法,而是直接将方法内的代码通过一定的修改后copy到原代码中(将方法主体直接插入到调用处,而不是进行方法调用)。这样可以让代码执行的更快(因为省略了调用函数的开销)

另一方面,私有方法也被编译器隐式修饰为final,这意味着private final void f()和private void f()并无区别。

《YOLO多模态创新改进专栏目录 》全网独家创新,多模态融合改进教程,包含早期融合、中期融合、后期融合、损失函数改进、二次创新模块、独家创新等几百种创新点改进,答疑群提供完整项目,永久更新中 🔥《YOLO多模态创新改进专栏》重磅来袭!🚀 本专栏汇集最新顶会顶刊创新点,提供1000+篇YOLO多模态改进方案(涵盖v8-v26),包含: 多模态融合策略(早期/中期/后期) 损失函数优化 独家创新模块 详细改进步骤 ✨特色服务: ✔️ 配套完整可运行项目 ✔️ 专业答疑群支持(含非计算机专业指导) ✔️ 持续更新至2026年 ✔️ 适用目标检测/OBB/分割/分类等多任务 💡适合人群: 科研人员 | 研究生 | 需发SCI/CCF论文者 环境要求宽松,新手友好,助力快速产出科研成果! 📈早订优 阅读详情

相关推荐

用FPGA驱动WS2812B点阵,手把手教你实现动态文字显示(附完整Verilog代码)

本文详细介绍了如何使用FPGA驱动WS2812B点阵实现动态文字显示,包括硬件连接、Verilog代码实现和动态效果设计。通过精确的时序控制和数据处理,读者可以掌握FPGA与WS2812B的交互技术,并实现炫酷的显示效果。附完整Verilog代码,适合硬件爱好者和工程师参考实践。

weixin_30482383的博客 669

java final 编译_final的作用(包含String的编译优化)

[java]代码库package fengke.finalandstatic;/*** final的作用** @author 锋客* 这里面就是final变量和普通变量的区别了,当final变量是基本数据类型以及String类型时,* 如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。* 也就是说在用到该final变量的地方,相当于直...

weixin_39629093的博客 374

GD32F303 Keil 工程项目从零搭建实战指南

本文是一份详细的GD32F303 Keil工程项目从零搭建实战指南。文章阐述了亲手搭建工程的重要性,并逐步指导开发者完成从环境准备、目录规划、工程创建、文件添加、关键配置到编译调试的全过程。重点讲解了如何正确选择启动文件、添加外设库、配置头文件路径和全局宏,旨在帮助开发者深入理解工程结构,掌握GD32F303开发的核心技能,实现从“会用”到“懂”的跨越。

weixin_29190651的博客 406

final的作用-编译内联优化

JVM的JIT编译优化过程会考虑全局运行情况来内联final方法提升执行效能

noob_can的博客 968

GAMES101作业3-遇到的各种问题及解决方法

记录在做作业3时遇到的一些坑!以及最后的解决办法。

qq_41835314的博客 6817

PX4开发环境搭建(Ubuntu1804+QGC+Qt Creator )

文章目录前言一、安装环境二、PX4环境搭建1. 在虚拟机中安装Ubuntu2. 安装PX4环境(1)下载PX4源码:(2) 安装工具链(3) jMAVSim仿真(4) 编译验证三、安装QGC四、安装Qt Creator 前言 在这之前作者完全没接触过PX4,安装过程遇到了很多坑,而且每安装下载一个东西都要等好久,出现问题又要重新开始,前后折腾了四天才弄好,希望此文对大家有所帮助。 一、安装环境 ...

Beyonderwei的博客 9023

JVM学习

jvm

java_xhh的博客 1216

网络安全隔离技术解析:单向网闸与双向网闸的核心差异与应用场景

本文深入解析网络安全隔离技术中的单向网闸与双向网闸,详细比较两者的核心差异与应用场景。单向网闸通过物理隔离确保数据单向流动,适用于金融交易等高风险场景;双向网闸则支持严格安检的双向数据交互,常见于医疗、政务等领域。文章还提供了选型建议和技术发展趋势,帮助读者根据安全需求和业务场景选择最适合的网闸解决方案。

weixin_29323365的博客 528

关键字之final

按照final修饰的数据类型分类:基本数据类型final域写规则:禁止final域写与对象引用赋值(构造方法执行之外)重排序。目的:确保其他线程拿到对象引用时,该对象的final域已经被正确初始化final域读规则:禁止初次读对象的引用与初次读该对象包含的final域进行重排序目的:确保读取到对象引用后,该对象的final域的值已经被正确初始化引用数据类型增加约束规则:禁止在构造函数对一个final修饰的对象的成员域的写入与随后将这个被构造的对象的引用赋值给引用变量这两个操作进行重排序。

杰尼龟的小龟壳的博客 371

使用vite+react+ts+Ant Design开发后台管理项目(四)

本文将引导开发者从零基础开始,运用、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈,构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导,文章旨在为开发者揭示如何利用这些技术工具,从项目构思到最终实现的全过程,提供清晰的开发思路和实用的技术应用技巧。使用vite+react+ts+Ant Design开发后台管理项目(一)使用vite+react+ts+Ant Design开发后台管理项目(二)

lbking666666的专栏 2007

Windows安装Pytorch3d

pytorch和pytorch3d版本对应关系如下:https://github.com/facebookresearch/pytorch3d/releasescuda和NVIDIA CUB版本对应关系如下:https://github.com/NVIDIA/cub/releases?page=1本人配置如下:GPU:1050TiCUDA:11.1python:3.8。

Snakewood的博客 4286

final+基本类型导致只编译常量类引起的错误

今天在读《高质量java 编程 150个建议》一书中,发现其中的建议20还真的值得注意, 其中说到的是,如果在一个类中定义了finial int(string等基本类型)这样的常量,那么如果final string的值变了,假如不用IDE编译的话,那么是会有问题的?(什么?不用IDE编译?是的,就是假如 不用IDE,而用手工命令行的方式),例子如下: [code="java"] pu...

jackyrongvip的专栏 183

【原理图PCB专题】Cadence 17.4版本原理图及PCB 模块复用

在我们设计复杂板卡的时候,往往会遇到一部分电路被反复使用的情况。Cadence允许设计者一开始就将复用模块设计好,以后只要直接调用复用模块就可以直接用以设计更复杂的电路板了。这对于大规模集成设计无疑是非常好的选择,它不仅让设计者不必花费时间在相同模块反复设计上,更有利于电路的模块化设计。

一点硬件 2017

java中的String自己一点小见解

StringString 类介绍创建字符串 String 类介绍 String 是引用数据类型(地址),和对象一样。 字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。 String类是用final修饰的,所以String不能被继承,而且所有的成员方法都默认为final方法。 String str="a"; 在代码中遇到字符串常量时,这里的值是 “a”,编译器会使用该值创建一个 String 对象。 和其它对象一样,可以使用关键字和

雪落无痕的博客 168

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

前端学 Java 课程笔记

面向前端开发人员:大量以前端概念类比

estrusKing的博客 230

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Final变量 编译时期就确定具体值

1. public class FinalClass { public static String str = "aaa"; static { System.out.println("hello world"); }}public class FinalTest { public static void main(String[] args) {

luojinbai的专栏 2135

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

final static 常量 编译时就已经确定

晚上因为需求,需要更改一个开源包的源码实现一个不同的功能。

xiaoli 2026

JAVA--final关键字、编译期常量与运行时常量

final关键字 基本用法:修饰类、方法、变量 1.修饰一个类时:表明该类不能被继承,final类中成员变量隐式指定为final 2.修饰方法时:锁定方法,防止继承类修改其定义(防止覆盖)(另外:为了效率,早期java版本中,final方法转为内嵌调用,这个有兴趣的可以查查,现在基本用不到了) 补充:**类中private方法会隐式的指定为final 3.修饰变量 即声明一个常量 对于final变量,若为基本数据类型,其数值初始化后不可更改,如为引用类型,则初始化后不可指向其他对象 **对于final和

sunjintaoxxx的博客 1179

JAVA编译器常量

  编译器常量的特点就是:它的值在编译期就可以确定。比如:   final int i = 5;   再傻的编译器也能在编译时看出它的值是5,不需要到运行时。对于运行时常量,它的值虽然在运行时初始化后不再发生变化,但问题就在于它的初始值要到运行时才能确定。    比如:   Random rand = new Random(47);   final int i4 = rand.nextI...

weixin_34168700的博客 273

final变量编译时期就确定具体值

当final修饰变量是基本数据类型以及Stirng类型是,如果在编译器就能知道他的确切的值,则编译器会把它当做编译期常量使用,也就是说在用到该final变量的地方,相当于直接访问的这个常量。 ...

小仙儿 802

string,final,方法区,常量池,编译时和运行时

string 不变性,有final修饰,不能被继承; intern();返回string对象在常量池中的引用(即字符串对象在常量池中的地址); ==比较的是对象的地址是否相同;(即是否是同一个对象) equals比较的是对象的内容是否一样; 对象的引用存的是对象实际位置的首地址; final从字面上理解含义为“最后的,最终的”。在Java中也同样表示出此种含义。 final可以用来修饰变量(包括类...

cuisha_的博客 1501

java中final关键字的编译问题

之前我是没有发现有这个恶心的问题的,从各种资料上看到final关键字的说明,都只是说此关键字是在程序中只允许赋值一次什么的。而在正常的运用当中这个关键字基本上也不会发现什么问题。 但是当我们把一个版本号用此关键字修饰的时候,问题就出现了。 我们在一个系统文件(SystemValue)中对版本号(PRO_CODE)进行了修饰,在我们的产品中很多地方都用到了这个版本号进行一个区分。 这段代码编译

u013521702的专栏 840

Java编译期和运行期

编译期: 是指把源码交给编译器编译成计算机可以执行的文件的过程.在Java中也就是把Java代码编成class文件的过程.编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误.运行期:是把编译后的文件交给计算机执行.直到程序运行结束.所谓运行期就把在磁盘中的代码放到内存中执行起来.在Java中把磁盘中的代码放到内存中就是类加载过程.类加载是运行期的...

qq_26225663的博客 7929

java final 编译_Java final 关键字(keyword)

例如:将变量使用final修饰,以防止变量被覆盖或修改:public class Main {final int x = 10;final double PI = 3.14;public static void main(String[] args) {Main myObj = new Main();myObj.x = 50; // 会产生一个错误: cannot assign a value t...

weixin_31983133的博客 176

java方法加final_java方法中参数要不要加final

1./*********************************************************************************************************************************/package com.pingan.credit.channel.abtest;/*** @Created 2017年12月14日 ...

weixin_36332616的博客 962

插件开发遇到的坑------final 型变量,编译过程被优化

android 插件开发遇到的坑 今天遇到一个坑,pdf 插件,调用了主工程的一个静态final 字符串,但是主工程里面已经没有这个字符串了,却没有崩溃。 后来同事说,因为字符串可能已经直接被写死了。你应该看下编译后的代码。我一同事,反编译apk 之后,发现,果然,因为provide 的jar 里面是有这个final 的字符串的,java ...

weixin_38169722的博客 204
上一篇: LongCache机制与Long等值比较
下一篇: 本地Spring容器关闭的时机
louis9212
博客等级 码龄14年 8粉丝 49原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值