[java] System类深度解析

Java格式化输出深度解析:String.format()与System.out.printf()全面对比 本文详细介绍了Java中两种主要格式化输出方法:String.format()和System.out.printf()。String.format()返回格式化字符串,适合构建复杂字符串;System.out.printf()直接输出到控制台,适合调试。两者共享基于%的格式说明符语法,支持参数索引、宽度控制等高级功能。性能测试显示String.format()比System.out.printf()更高效,但都低于手动拼接。文章还分析了内存使用、实现原理、类结构,并提供了日期格式化、数值本地化等实用技巧。最 阅读详情

概述

大部分写的第一个java功能,应该都是如下这行代码:

System.out.println("hello world");

这里即用到了System类,本篇文章就将分析System类的实现原理。在java里面System类是一个final修饰的类,意味着它的方法和属性都不能被修改。

System 类包含了多个有用的字段和方法,它不能被实例化。在system类提供的功能当中,有标准输入、标准输出和错误输出流,访问外部定义的属性和环境变量;加载文件和库的方法;以及用于快速复制数组的一部分的实用方法。

构造方法如下:

 /** Don't let anyone instantiate this class */
    private System() {
    }

注释里写的非常清楚:不让任何人实例化这个类。

关于System.out.println()实现原理

System是一个类,而out则是该类的一个成员变量,定义如下:

 /**
     * The "standard" output stream. This stream is already
     * open and ready to accept output data. Typically this stream
     * corresponds to display output or another output destination
     * specified by the host environment or user.
     * <p>
     * For simple stand-alone Java applications, a typical way to write
     * a line of output data is:
     * <blockquote><pre>
     *     System.out.println(data)
     * </pre></blockquote>
     * <p>
     * See the <code>println</code> methods in class <code>PrintStream</code>.
     *
     * @see     java.io.PrintStream#println()
     * @see     java.io.PrintStream#println(boolean)
     * @see     java.io.PrintStream#println(char)
     * @see     java.io.PrintStream#println(char[])
     * @see     java.io.PrintStream#println(double)
     * @see     java.io.PrintStream#println(float)
     * @see     java.io.PrintStream#println(int)
     * @see     java.io.PrintStream#println(long)
     * @see     java.io.PrintStream#println(java.lang.Object)
     * @see     java.io.PrintStream#println(java.lang.String)
     */
    public final static PrintStream out = null;

可以看到,out实际上是类PrintSteam的一个实例, 而println()就是PrintStream类的一个方法而已。PrintStream类是“标准”输出流。此流已经打开并准备接受输出数据。通常,该流对应于主机环境或用户指定的显示输出或另一输出目的地。而在我们的编辑器里面,它就是输出在console上的。

但是这里的out变量是null并没有实例化,那么它是在哪里实例化的呢?答案在System类的initializeSystemClass方法里:

 /**
     * Initialize the system class.  Called after thread initialization.
     */
    private static void initializeSystemClass() {

        ...
        props = new Properties();
        initProperties(props);  // initialized by the VM

        ...
        sun.misc.VM.saveAndRemoveProperties(props);


        lineSeparator = props.getProperty("line.separator");
        sun.misc.Version.init();

        FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
        FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
        FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
        setIn0(new BufferedInputStream(fdIn));
        setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
        setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));

        // Load the zip library now in order to keep java.util.zip.ZipFile
        // from trying to use itself to load this library later.
        loadLibrary("zip");

        // Setup Java signal handlers for HUP, TERM, and INT (where available).
        Terminator.setup();

        ...
        sun.misc.VM.initializeOSEnvironment();

        // The main thread is not added to its thread group in the same
        // way as other threads; we must do it ourselves here.
        Thread current = Thread.currentThread();
        current.getThreadGroup().add(current);

        // register shared secrets
        setJavaLangAccess();

        ...
        sun.misc.VM.booted();
    }

在上面的代码当中,有一行调用了setOut0()方法,该方法就是对out属性初始化的方法。不出意外,它又是一个native方法。在open jdk当中,有它的实现代码,如下:

JNIEXPORT void JNICALL
Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
{
    jfieldID fid =
        (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
    if (fid == 0)
        return;
    (*env)->SetStaticObjectField(env,cla,fid,stream);
}

setOut0(PrintStream ps)的作用,就是将PrintStream设置为System类的out静态变量。

而在PrintSteam类里面,println方法有多个重载的实现,它们最终都是调用的一个write方法,实现如下

 private void write(String s) {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.write(s);
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush && (s.indexOf('\n') >= 0))
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }

该write方法调用的是PrintSteam类的成员变量BufferedWriter类的一个实例,在BufferedWriter类里面,我们可以看到write方法的实现:

 /**
     * Writes a portion of an array of characters.
     *
     * <p> Ordinarily this method stores characters from the given array into
     * this stream's buffer, flushing the buffer to the underlying stream as
     * needed.  If the requested length is at least as large as the buffer,
     * however, then this method will flush the buffer and write the characters
     * directly to the underlying stream.  Thus redundant
     * <code>BufferedWriter</code>s will not copy data unnecessarily.
     *
     * @param  cbuf  A character array
     * @param  off   Offset from which to start reading characters
     * @param  len   Number of characters to write
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void write(char cbuf[], int off, int len) throws IOException {
        synchronized (lock) {
            ensureOpen();
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                ((off + len) > cbuf.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return;
            }

            if (len >= nChars) {
                /* If the request length exceeds the size of the output buffer,
                   flush the buffer and then write the data directly.  In this
                   way buffered streams will cascade harmlessly. */
                flushBuffer();
                out.write(cbuf, off, len);
                return;
            }

            int b = off, t = off + len;
            while (b < t) {
                int d = min(nChars - nextChar, t - b);
                System.arraycopy(cbuf, b, cb, nextChar, d);
                b += d;
                nextChar += d;
                if (nextChar >= nChars)
                    flushBuffer();
            }
        }
    }

因此,实例化了PrintStream对象,然后借助它去调用println方法,这就是大致的思想。

System.gc方法

 /**
     * Runs the garbage collector.
     * <p>
     * Calling the <code>gc</code> method suggests that the Java Virtual
     * Machine expend effort toward recycling unused objects in order to
     * make the memory they currently occupy available for quick reuse.
     * When control returns from the method call, the Java Virtual
     * Machine has made a best effort to reclaim space from all discarded
     * objects.
     * <p>
     * The call <code>System.gc()</code> is effectively equivalent to the
     * call:
     * <blockquote><pre>
     * Runtime.getRuntime().gc()
     * </pre></blockquote>
     *
     * @see     java.lang.Runtime#gc()
     */
    public static void gc() {
        Runtime.getRuntime().gc();
    }

代码如上,又是一个native方法,结合注释即可理解它的含义。另外值得注意的是,这个方法并不是强制让虚拟机回收不用的对象,这个方法只是提醒虚拟机,程序员希望你在这回收一下对象,但回不回收还是虚拟机来决定,也就是说程序员对回不回收没有绝对的控制权。关于这个问题在我的另一篇博客里也有提到。

System.exit方法

定义如下:

 /**
     * Terminates the currently running Java Virtual Machine. The
     * argument serves as a status code; by convention, a nonzero status
     * code indicates abnormal termination.
     * <p>
     * This method calls the <code>exit</code> method in class
     * <code>Runtime</code>. This method never returns normally.
     * <p>
     * The call <code>System.exit(n)</code> is effectively equivalent to
     * the call:
     * <blockquote><pre>
     * Runtime.getRuntime().exit(n)
     * </pre></blockquote>
     *
     * @param      status   exit status.
     * @throws  SecurityException
     *        if a security manager exists and its <code>checkExit</code>
     *        method doesn't allow exit with the specified status.
     * @see        java.lang.Runtime#exit(int)
     */
    public static void exit(int status) {
        Runtime.getRuntime().exit(status);
    }

这个方法的作用是结束当前正在执行的Java虚拟机,int类型的status表示退出的状态码,非零表示异常终止。注意:无论status为何值程序都会退出,和return 相比有不同的是:return是回到上一层,而System.exit(status)是回到最上层。

 

Java核心源代码深度解析与实战学习 Java源码不仅是理解Java语言底层运行机制的关键路径,更是每一位资深Java开发者进阶的必经之路。通过阅读源码,开发者能够深入理解JVM的类加载机制、对象生命周期、线程管理等核心内容,从而在实际开发中写出更高效、更稳定的代码。例如,以Object类中的hashCode()与equals()方法为例,其契约关系直接影响到集合类(如HashMap)的性能表现:// native方法,底层由JVM实现。 阅读详情

相关推荐

香橙派5B-RK3588-NPU内核升级至0.9.8:RKLLM多模态部署实战

本文详细介绍了香橙派5B-RK3588设备NPU内核升级至0.9.8版本的完整流程,重点讲解了升级的必要性、两种升级方案(预编译包安装与自行编译内核)以及RKLLM SDK的安装配置。通过实战演示多模态模型转换与推理,显著提升AI计算性能,为嵌入式AI部署提供实用指南。

salt9的博客 1026

(Java)System 类

文章目录一、认识 System 类二、垃圾对象的回收三、对象的生命周期 一、认识 System 类 System 类是一些与系统相关属性和方法的集合,而且在 System 类中所有的属性都是静态的,要想引用这些属性和方法,直接使用 System 类调用即可。 System 类的常用方法: System 类 中的方法都是使用 static 定义的,所以在使用时直接使用类名称就可以调用,如System...

南淮北安的博客 1806

通信原理期末考试试题及答案

五、(总分12分)设某信道具有均匀的的双边噪声功率谱密度在该信道中传输抑制载波的单边带(上边带)信号,并设调制信号m(t)的频带限制在5K HZ,而载波为100 K HZ,已调信号的功率为10KW。:(1)单边带信号的载频为100kHz,带宽B=5kHz,为使信号顺利通过,理想带通滤波器的中心频率为。8、对最高频率为fH的调制信号m(t)分别进行AM、DSB、SSB调制,相应已调信号的带宽分别为。7、设调制信号为f(t)载波为,则抑制载波双边带调幅信号的时域表达式为,频域表达式为。

qq_67692062的博客 2393

【Java基础教程】(三十五)常用类库篇 · 第五讲:System类——解析系统辅助工具System类,一个系统操作与资源管理工具类 ~

System类是Java标准库提供的重要工具类,可用于访问与系统相关的操作、信息和资源。它提供了易于使用且跨平台的接口,使得开发者可以更方便地与底层系统进行交互。合理并正确地使用System类,可以帮助实现更灵活、高效和可移植的Java应用程序。

Technology changes the world of life 3950

WRF后处理:python cartopy绘制土地利用/土地分类图//python绘制WRF下垫面类型(以北极为例)

下垫面类型对于WRF的地表过程十分重要,而在我们研究WRF的地表过程之前,需要对输入的土地利用类型进行一些绘制,以便后续的修改。LU_MODIS21函数定义了绘制的土地类型、标签与对应色标,我们使用时,直接引用LU_MODIS21()即可返回。其实很简单,只要将你拥有的土地类型数据提取出来,将原本函数中的labels和C切片,重新定义色标再绘制即可。在这里,我将以北极地区为例,绘制北极地区的WRF下垫面数据,我使用的MODIS21这类。

weixin_43750300的博客 3859

解决银河麒麟V10分辨率问题:xrandr命令详解与常见错误排查

本文详细解析了在银河麒麟V10系统中使用xrandr命令调整屏幕分辨率的方法,包括核心功能解析、常见问题排查及持久化配置技巧。通过实战指南帮助用户解决分辨率缺失、配置失效等典型问题,提升多显示器环境下的工作效率。

weixin_30642561的博客 504

System类详解

特点 1、是java.lang包的一个类,我们知道java.lang里放的都是一些java编程的基础类; 2、该类是final的,即:不可以被继承,没有子类,其内部的方法默认也都是final的; 3、该类不能被实例化,内部全是一些static变量和方法,可以方便的被调用; 4、System代表系统,系统级的很多属性和方法都放置在该内内部; 5、内部有很多方法属性都是native的,即:涉...

tobearc的专栏 1591

Windows10 搭建 FTP 服务器

问题: 有这么一个需求,博主需要对班级同学的信息进行收集,同学的信息是一个个的文件, 正常是每个同学将自己的信息打包压缩通过 QQ 或者邮箱方式发送给博主, 博主一个个接收这些压缩包,然后进行解压,再统一放到一个文件夹下, 但是博主觉得这样子实在是太麻烦了,如果某一个同学的信息来回变动,就需要接收很多次,更改很多次, 另外如果消息过多还会产生漏掉某个同学的信息的问题。 解决方法: 如果可以使...

assiduous_me的博客 3965

sun.misc包找不到的解决方法

jdk有不同的厂商,jdk标准库中是没有sun开头的包,

敲码农的小代码   ; 14万+

山景BP10_128DBG开发板通过蓝牙连接手机放歌实验回顾

最近在学习上海山景公司的BP10_128DBG的开发板,因为网上关于BP10开发板的帖子也比较少,在学习的时候也没有太多的参考资料,基本上都是官方的历程。蓝牙放歌这个demo对我来说也比较复杂,特写下此博客进行记录、总结,大家有需要的可以参考。

weixin_56646002的博客 2020

Token 费用爆炸?教你用 Semantic Cache(语义缓存)把 API 成本降低 80%

本文介绍了语义缓存(Semantic Cache)技术在大模型应用中的关键作用。传统Redis缓存基于精确匹配,无法处理用户提问的语义相似性,导致重复调用昂贵的LLM API。语义缓存通过将问题向量化并在向量空间中进行相似度匹配,可识别30%-50%的重复提问,直接返回历史答案。文章详细解析了技术原理(Embedding+向量搜索)、架构设计,并提供了基于Python和ChromaDB的50行核心实现代码。同时指出了生产环境中的三大挑战:阈值设定、隐私保护和多轮对话处理,并给出相应解决方案。该技术能以极低成

BUG猿的博客 1056

使用JavaLangAccess和SharedSecrets来获取JVM中的实例

使用场景实例:最近一段时间在mybatis框架的源码,看到框架的日志模块的时候,发现其集成了JDK的原生日志java.util.logging,于是我就去看了一下java.util.logging实现源码,在其中的LogRecord.java文件中看到其中有一段代码:// Private method to infer the caller's class and method names

yums467的专栏 5969

Linux:安装Debian最新10.x操作系统(超详细)

安装Debian最新10.x操作系统安装Debian最新10.x操作系统1.下载Debian镜像2. 镜像安装引导启动页面,选择图形化安装:选择语言、时区,选中后点击continue:选择键盘模式:配置Hostname主机名,设置Root密码创建普通用户名和密码,进入磁盘分区步骤,选择“所有文件放在同一个分区”确认分区信息磁盘配置完,进入软件安装模块:选择源:进入软件包配置,等待配置结束根据需要选择软件包安装3. 安装完成重启后登录使用 安装Debian最新10.x操作系统 1.下载Debian镜像 下载D

HowieXue 薛永浩的博客 3万+

java——深度解析System系统类

天天说用System.out.println()来输出,那么我有个问题,out是一个变量还是一个内部类呢?大型的知识都有各种专题来详解,这些散碎的知识点我们也不能忽视,否则面试的时候被问到这么简单的问题,答不上来,就很尴尬了。

往事散云烟,十寸光阴换一钱 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【Java基础进阶】深度解析Java标准类库:字符串、包装类、System类与正则实战

读完本篇内容,大家能够清晰掌握核心知识点,熟练运用各类常用类完成业务编写。byte对应Byte,short对应Short,int对应Integer,long对应Long,float对应Float,double对应Double,char对应Character,boolean对应Boolean,一一对应适配所有基础类型。

Caiml_1006的博客 736

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java 中 System 类零度解析

System类是Java与系统交互的关键类,提供静态方法实现全局唯一功能。主要特性包括:标准I/O流控制(支持重定向)、高精度时间测量(currentTimeMillis与nanoTime区别)、高效数组复制(arraycopy的native实现)、系统属性与环境变量访问、虚拟机控制方法(需谨慎使用exit/gc)以及JDK9新增的轻量级日志接口。特别强调时间测量和数组复制的性能优化技巧,以及系统级操作的安全注意事项,是Java开发者必须掌握的核心工具类。

Java孩子的博客 1913

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Java System类全解析:从基础到实战的进阶指南

System类作为Java与底层系统交互的核心接口,其功能远比表面看起来更丰富。从JDK1.0到JDK8的演进历程,我们看到了Java团队对系统交互能力的持续优化。在JDK8中,凭借原生实现和JIT优化成为数组复制的性能标杆;虽线程安全但存在并发瓶颈,需通过缓存规避;和nanoTime()的差异化设计,提醒我们根据场景选择合适的时间API。理解这些细节,不仅能帮助我们写出更高效的代码,更能深入领会Java"平台无关性"背后的实现智慧。在实际开发中,既要善用System类的底层能力,也要学会结合。

m0_75126572的博客 1335

Java-System工具类深度解析

Java中的System工具类是一个不可或缺的存在,它提供了一系列与系统相关的操作方法,涵盖标准输入输出、系统属性获取、内存管理等多个重要功能,在开发过程中频繁被使用。无论是初学者搭建简单控制台程序,还是资深开发者进行复杂系统调试与性能优化,都离不开System类的支持

aa_hdkf_vg的博客 1301

类的分析 java_分析JAVA的Random类

Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数,在种子数的基础上进行一定的交换,从而产生需要的随机数字。在实际的项目开发过程中,经常需要产生一些随机数值,例如网站登录中的校验数字等,或者需要以一定的几率实现某种效果,例如游戏程序中的物品掉落等。在Java API中,在java.util包中专门提供了一个和随机处理有关的类,这个类就是Rando...

weixin_39831104的博客 65

Java System类完全指南:10大核心API详解与实战应用

摘要:本文深入解析Java开发中高频使用的System类核心API,包括时间测量(currentTimeMillis/nanoTime)、跨平台换行处理(lineSeparator)、系统属性获取(getProperty)、环境变量读取(getenv)、高性能数组复制(arraycopy)及对象身份识别(identityHashCode)等6类关键方法。通过典型代码示例和性能对比数据,展示了这些系统级工具在性能监控、跨平台兼容、环境配置管理等方面的实际应用价值,帮助开发者提升工程效率和代码质量。(146字)

m0_53626105的博客 1254

Java ArrayList类深度解析

针对以上面试题,小编已经把面试题+答案整理好了。

2401_83329402的博客 725

Java Scanner类深度解析:从控制台交互到文件解析的实战指南

在Java编程中,输入输出(I/O)处理是基础且关键的环节,它涉及数据从外部源到程序的流动与解析。其核心原理在于将底层的字节流或字符流进行封装和抽象,提供更便捷的读写接口。这项技术的价值在于简化了程序与用户、文件或网络的数据交互,是构建交互式应用、处理配置文件或日志分析等场景的基石。Scanner类正是Java标准库中实现这一思想的典型工具,它将输入源(如System.in、文件或字符串)封装成一个文本扫描器,通过定义分隔符将输入内容令牌化,从而允许开发者轻松读取整数、浮点数、字符串等多种数据类型。在控制台

weixin_30596165的博客 1338

(十八)Java核心类库深度解析:比较器、系统类与数学类的全面指南

本文全面探讨了Java中三大核心类库:比较器、系统类和数学类。比较器选择指南当对象有自然排序时实现Comparable需要多种排序方式时使用ComparatorJDK8的Lambda和方法引用极大简化了比较器代码系统类使用要点System类提供系统级访问入口Runtime管理JVM生命周期和资源ProcessBuilder提供更安全的进程控制数学运算最佳实践基本运算使用Math类精确计算必须使用BigDecimal随机数生成考虑线程安全和安全性需求。

MeyrlNotFound的博客 1075
上一篇: [java] Thread类详解
下一篇: [java] Integer类解析
topEngineerr
博客等级 码龄11年 627粉丝 157原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值