Java 中文官方教程 2022 版(二十八)(3)

简介: Java 中文官方教程 2022 版(二十八)

Java 中文官方教程 2022 版(二十八)(2)https://developer.aliyun.com/article/1486867

Duration

一个Duration在衡量机器时间的情况下最为适用,比如使用Instant对象的代码。Duration对象以秒或纳秒为单位进行衡量,不使用年、月和日等基于日期的构造,尽管该类提供了将时间转换为天、小时和分钟的方法。Duration可以具有负值,如果创建时结束点早于起始点。

以下代码计算两个瞬间之间的持续时间(以纳秒为单位):

Instant t1, t2;
...
long ns = Duration.between(t1, t2).toNanos();

以下代码将 10 秒添加到一个Instant中:

Instant start;
...
Duration gap = Duration.ofSeconds(10);
Instant later = start.plus(gap);

一个Duration与时间线无关,即它不跟踪时区或夏令时。将相当于 1 天的Duration添加到ZonedDateTime中,结果将确切地添加 24 小时,而不考虑夏令时或其他可能导致的时间差异。

ChronoUnit

讨论 Temporal Package 中的ChronoUnit枚举定义了用于衡量时间的单位。当您想要以单个时间单位(如天或秒)衡量一段时间时,ChronoUnit.between方法非常有用。between方法适用于所有基于时间的对象,但仅以单个单位返回时间量。以下代码计算两个时间戳之间的间隔,以毫秒为单位:

import java.time.Instant;
import java.time.temporal.Temporal;
import java.time.temporal.ChronoUnit;
Instant previous, current, gap;
...
current = Instant.now();
if (previous != null) {
    gap = ChronoUnit.MILLIS.between(previous,current);
}
...

Period

要使用基于日期的值(年、月、日)来定义一段时间,请使用Period类。Period类提供了各种get方法,比如getMonthsgetDaysgetYears,以便您可以从期间中提取时间量。

所有三个单位(月、日和年)一起表示的总时间段。要以单个时间单位(如天)表示测量的时间量,可以使用ChronoUnit.between方法。

以下代码报告了你的年龄,假设你出生于 1960 年 1 月 1 日。使用Period类来确定年、月和日的时间。使用ChronoUnit.between方法确定相同的时间段,以总天数显示在括号中:

LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1960, Month.JANUARY, 1);
Period p = Period.between(birthday, today);
long p2 = ChronoUnit.DAYS.between(birthday, today);
System.out.println("You are " + p.getYears() + " years, " + p.getMonths() +
                   " months, and " + p.getDays() +
                   " days old. (" + p2 + " days total)");

该代码生成类似以下的输出:

You are 53 years, 4 months, and 29 days old. (19508 days total)

要计算距离你下一个生日还有多长时间,可以使用来自Birthday示例的以下代码。使用Period类来确定月和日的值。ChronoUnit.between方法返回总天数的值,并显示在括号中。

LocalDate birthday = LocalDate.of(1960, Month.JANUARY, 1);
LocalDate nextBDay = birthday.withYear(today.getYear());
//If your birthday has occurred this year already, add 1 to the year.
if (nextBDay.isBefore(today) || nextBDay.isEqual(today)) {
    nextBDay = nextBDay.plusYears(1);
}
Period p = Period.between(today, nextBDay);
long p2 = ChronoUnit.DAYS.between(today, nextBDay);
System.out.println("There are " + p.getMonths() + " months, and " +
                   p.getDays() + " days until your next birthday. (" +
                   p2 + " total)");

该代码生成类似以下的输出:

There are 7 months, and 2 days until your next birthday. (216 total)

这些计算没有考虑时区差异。例如,如果你出生在澳大利亚,但目前居住在班加罗尔,这会稍微影响你确切年龄的计算。在这种情况下,可以结合使用PeriodZonedDateTime类。当你将Period添加到ZonedDateTime时,会考虑时差。

时钟

原文:docs.oracle.com/javase/tutorial/datetime/iso/clock.html

大多数基于时间的对象提供一个无参数的now()方法,使用系统时钟和默认时区提供当前日期和时间。这些基于时间的对象还提供一个带有一个参数的now(Clock)方法,允许您传入一个替代的Clock

当前日期和时间取决于时区,对于全球化应用程序,需要一个Clock来确保日期/时间是使用正确的时区创建的。因此,虽然使用Clock类是可选的,但这个特性允许您测试您的代码是否适用于其他时区,或者通过使用一个固定的时钟,时间不会改变。

Clock类是抽象的,因此您不能创建它的实例。以下工厂方法对于测试很有用。

非 ISO 日期转换

原文:docs.oracle.com/javase/tutorial/datetime/iso/nonIso.html

本教程不会详细讨论java.time.chrono包。但是,了解到该包提供了几个不基于 ISO 的预定义年表,如日本、伊斯兰、民国和泰国佛教。您还可以使用此包创建自己的年表。

本节将向您展示如何在 ISO 日期和其他预定义年表日期之间进行转换。

转换为非 ISO 日期

您可以使用from(TemporalAccessor)方法将 ISO 日期转换为其他年表的日期,例如JapaneseDate.from(TemporalAccessor)。如果无法将日期转换为有效实例,则此方法会抛出DateTimeException。以下代码将LocalDateTime实例转换为几个预定义的非 ISO 日历日期:

LocalDateTime date = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
JapaneseDate jdate     = JapaneseDate.from(date);
HijrahDate hdate       = HijrahDate.from(date);
MinguoDate mdate       = MinguoDate.from(date);
ThaiBuddhistDate tdate = ThaiBuddhistDate.from(date);

StringConverter示例将从LocalDate转换为ChronoLocalDate再转换为String,然后再转回去。toString方法接受LocalDate实例和Chronology,并通过提供的Chronology返回转换后的字符串。DateTimeFormatterBuilder用于构建可用于打印日期的字符串:

/**
 * Converts a LocalDate (ISO) value to a ChronoLocalDate date
 * using the provided Chronology, and then formats the
 * ChronoLocalDate to a String using a DateTimeFormatter with a
 * SHORT pattern based on the Chronology and the current Locale.
 *
 * @param localDate - the ISO date to convert and format.
 * @param chrono - an optional Chronology. If null, then IsoChronology is used.
 */
public static String toString(LocalDate localDate, Chronology chrono) {
    if (localDate != null) {
        Locale locale = Locale.getDefault(Locale.Category.FORMAT);
        ChronoLocalDate cDate;
        if (chrono == null) {
            chrono = IsoChronology.INSTANCE;
        }
        try {
            cDate = chrono.date(localDate);
        } catch (DateTimeException ex) {
            System.err.println(ex);
            chrono = IsoChronology.INSTANCE;
            cDate = localDate;
        }
        DateTimeFormatter dateFormatter =
            DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
                             .withLocale(locale)
                             .withChronology(chrono)
                             .withDecimalStyle(DecimalStyle.of(locale));
        String pattern = "M/d/yyyy GGGGG";
        return dateFormatter.format(cDate);
    } else {
        return "";
    }
}

当使用以下日期调用预定义年表的方法时:

LocalDate date = LocalDate.of(1996, Month.OCTOBER, 29);
System.out.printf("%s%n",
     StringConverter.toString(date, JapaneseChronology.INSTANCE));
System.out.printf("%s%n",
     StringConverter.toString(date, MinguoChronology.INSTANCE));
System.out.printf("%s%n",
     StringConverter.toString(date, ThaiBuddhistChronology.INSTANCE));
System.out.printf("%s%n",
     StringConverter.toString(date, HijrahChronology.INSTANCE));

输出如下:

10/29/0008 H
10/29/0085 1
10/29/2539 B.E.
6/16/1417 1

转换为基于 ISO 的日期

您可以使用静态LocalDate.from方法将非 ISO 日期转换为LocalDate实例,如下例所示:

LocalDate date = LocalDate.from(JapaneseDate.now());

其他基于时间的类也提供此方法,如果日期无法转换,则会抛出DateTimeException

来自StringConverter示例的fromString方法解析包含非 ISO 日期的String并返回LocalDate实例。

/**
 * Parses a String to a ChronoLocalDate using a DateTimeFormatter
 * with a short pattern based on the current Locale and the
 * provided Chronology, then converts this to a LocalDate (ISO)
 * value.
 *
 * @param text   - the input date text in the SHORT format expected
 *                 for the Chronology and the current Locale.
 *
 * @param chrono - an optional Chronology. If null, then IsoChronology
 *                 is used.
 */
public static LocalDate fromString(String text, Chronology chrono) {
    if (text != null && !text.isEmpty()) {
        Locale locale = Locale.getDefault(Locale.Category.FORMAT);
        if (chrono == null) {
           chrono = IsoChronology.INSTANCE;
        }
        String pattern = "M/d/yyyy GGGGG";
        DateTimeFormatter df = new DateTimeFormatterBuilder().parseLenient()
                              .appendPattern(pattern)
                              .toFormatter()
                              .withChronology(chrono)
                              .withDecimalStyle(DecimalStyle.of(locale));
        TemporalAccessor temporal = df.parse(text);
        ChronoLocalDate cDate = chrono.date(temporal);
        return LocalDate.from(cDate);
    }
return null;
}

当使用以下字符串调用方法时:

System.out.printf("%s%n", StringConverter.fromString("10/29/0008 H",
    JapaneseChronology.INSTANCE));
System.out.printf("%s%n", StringConverter.fromString("10/29/0085 1",
    MinguoChronology.INSTANCE));
System.out.printf("%s%n", StringConverter.fromString("10/29/2539 B.E.",
    ThaiBuddhistChronology.INSTANCE));
System.out.printf("%s%n", StringConverter.fromString("6/16/1417 1",
    HijrahChronology.INSTANCE));

打印的字符串应该都能转换回 1996 年 10 月 29 日:

1996-10-29
1996-10-29
1996-10-29
1996-10-29

传统日期时间代码

原文:docs.oracle.com/javase/tutorial/datetime/iso/legacy.html

在 Java SE 8 发布之前,Java 日期和时间机制由 java.util.Datejava.util.Calendarjava.util.TimeZone 类以及它们的子类,如 java.util.GregorianCalendar 提供。这些类有几个缺点,包括:

  • Calendar 类不是类型安全的。
  • 由于这些类是可变的,它们不能在多线程应用程序中使用。
  • 应用程序代码中常见的错误是由于月份编号不寻常和缺乏类型安全性。

与传统代码的互操作性

也许您有使用 java.util 日期和时间类的传统代码,并且希望在最小更改代码的情况下利用 java.time 功能。

JDK 8 发布中添加了几种允许在 java.utiljava.time 对象之间进行转换的方法:

以下示例将 Calendar 实例转换为 ZonedDateTime 实例。请注意,必须提供一个时区来从 Instant 转换为 ZonedDateTime

Calendar now = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault()));

以下示例展示了 DateInstant 之间的转换:

Instant inst = date.toInstant();
Date newDate = Date.from(inst);

以下示例将从 GregorianCalendar 转换为 ZonedDateTime,然后从 ZonedDateTime 转换为 GregorianCalendar。其他基于时间的类是使用 ZonedDateTime 实例创建的:

GregorianCalendar cal = ...;
TimeZone tz = cal.getTimeZone();
int tzoffset = cal.get(Calendar.ZONE_OFFSET);
ZonedDateTime zdt = cal.toZonedDateTime();
GregorianCalendar newCal = GregorianCalendar.from(zdt);
LocalDateTime ldt = zdt.toLocalDateTime();
LocalDate date = zdt.toLocalDate();
LocalTime time = zdt.toLocalTime();

将 java.util 日期和时间功能映射到 java.time

由于在 Java SE 8 发布中完全重新设计了日期和时间的 Java 实现,您不能将一个方法替换为另一个方法。如果您想使用 java.time 包提供的丰富功能,最简单的解决方案是使用前一节中列出的 toInstanttoZonedDateTime 方法。但是,如果您不想使用该方法或该方法不满足您的需求,则必须重写您的日期时间代码。

在 概述 页面介绍的表格是评估哪些 java.time 类满足您需求的好地方。

两个 API 之间没有一对一的映射对应关系,但以下表格给出了 java.util 日期和时间类中的哪些功能映射到 java.time API 的一般想法。

java.util 功能 java.time 功能 注释

| java.util.Date | java.time.Instant | InstantDate 类相似。每个类:- 表示时间线上的瞬时时间点(UTC)

  • 持有独立于时区的时间
  • 表示为自 1970-01-01T00:00:00Z 以来的纪元秒数加上纳秒

Date.from(Instant)Date.toInstant() 方法允许在这些类之间进行转换。 |

| java.util.GregorianCalendar | java.time.ZonedDateTime | ZonedDateTime 类是 GregorianCalendar 的替代品。它提供以下类似功能。人类时间表示如下:

LocalDate:年,月,日

LocalTime:小时,分钟,秒,纳秒

ZoneId:时区

ZoneOffset:与 GMT 的当前偏移量

GregorianCalendar.from(ZonedDateTime)GregorianCalendar.to(ZonedDateTime) 方法促进这些类之间的转换。

java.util.TimeZone java.time.ZoneIdjava.time.ZoneOffset ZoneId 类指定时区标识符,并访问每个时区使用的规则。ZoneOffset 类仅指定与格林威治/UTC 的偏移量。更多信息,请参阅时区和偏移类。
将日期设置为 1970-01-01GregorianCalendar java.time.LocalTime 将日期设置为 1970-01-01GregorianCalendar 实例中的代码以使用时间组件可以替换为 LocalTime 实例。
GregorianCalendar 时间设置为 00:00. java.time.LocalDate 将时间设置为 GregorianCalendar 实例中的 00:00 以使用日期组件的代码可以替换为 LocalDate 实例。(这种 GregorianCalendar 方法存在缺陷,因为由于转换到夏令时,有些国家一年中不会发生午夜。)

日期和时间格式化

尽管java.time.format.DateTimeFormatter提供了一个强大的机制来格式化日期和时间值,但你也可以直接使用java.time基于时间的类与java.util.FormatterString.format一起使用,使用与java.util日期和时间类相同的基于模式的格式化。

摘要

原文:docs.oracle.com/javase/tutorial/datetime/iso/summary.html

java.time 包含许多类,您的程序可以使用这些类来表示时间和日期。这是一个非常丰富的 API。基于 ISO 的日期的关键入口点如下:

  • Instant 类提供了时间线的机器视图。
  • LocalDateLocalTimeLocalDateTime 类提供了日期和时间的人类视图,没有任何关于时区的参考。
  • ZoneIdZoneRulesZoneOffset 类描述时区、时区偏移和时区规则。
  • ZonedDateTime 类表示带有时区的日期和时间。OffsetDateTimeOffsetTime 类分别表示日期和时间,或仅时间。这些类考虑了时区偏移。
  • Duration 类以秒和纳秒来衡量时间量。
  • Period 类使用年、月和日来衡量时间量。

其他非 ISO 日历系统可以使用 java.time.chrono 包来表示。尽管本教程不涵盖此包,但 非 ISO 日期转换 页面提供了关于将基于 ISO 的日期转换为其他日历系统的信息。

日期时间 API 是作为 Java 社区流程的一部分开发的,其编号为 JSR 310。更多信息,请参阅 JSR 310: 日期和时间 API

问题和练习:日期时间 API

原文:docs.oracle.com/javase/tutorial/datetime/iso/QandE/questions.html

问题

1. 你会使用哪个类来存储你的生日,包括年、月、日、秒和纳秒?

2. 给定一个随机日期,如何找到前一个星期四的日期?

3. ZoneIdZoneOffset之间有什么区别?

4. 如何将Instant转换为ZonedDateTime?如何将ZonedDateTime转换为Instant

练习

1. 为给定年份编写一个示例,报告该年份内每个月的长度。

2. 为当前年份的给定月份编写一个示例,列出该月份内所有的星期一。

3. 编写一个示例,测试给定日期是否是一个星期五的 13 日。

检查你的答案。

Trail: 国际化

原文:docs.oracle.com/javase/tutorial/i18n/index.html

本教程中的课程将教您如何国际化 Java 应用程序。国际化的应用程序易于根据全球用户的习俗和语言进行定制。


注意: 本教程涵盖了核心国际化功能,这是桌面、企业和移动应用程序提供的附加功能所需的基础。有关更多信息,请参阅Java 国际化主页


定义了国际化这一术语,提供了一个快速的示例程序,并提供了一个检查表,您可以用来国际化现有程序。

解释了如何创建和使用Locale对象。

展示了如何动态访问随Locale变化的对象。

解释了如何根据Locale格式化数字、日期和文本消息,以及如何使用模式创建自定义格式。

提供了在与区域设置无关的方式下操作文本的技术。

解释了如何为 IDN 提供国际化支持。

解释了如何启用依赖于区域设置的数据和服务的插件。

教训:介绍

原文:docs.oracle.com/javase/tutorial/i18n/intro/index.html

国际化 是设计应用程序的过程,使其能够在不进行工程更改的情况下适应各种语言和地区。有时国际化一词被缩写为 i18n,因为在第一个 “i” 和最后一个 “n” 之间有 18 个字母。

一个国际化的程序具有以下特点:

  • 通过添加本地化数据,同一个可执行文件可以在全球范围内运行。
  • 文本元素,比如状态消息和 GUI 组件标签,不是硬编码在程序中的。而是存储在源代码之外,并动态检索。
  • 支持新语言不需要重新编译。
  • 依赖文化的数据,比如日期和货币,以符合最终用户的地区和语言的格式出现。
  • 它可以快速本地化。

本地化 是通过添加特定区域或语言的区域特定组件和翻译文本来使软件适应特定区域或语言的过程。本地化一词通常缩写为 l10n,因为在 “l” 和 “n” 之间有 10 个字母。

本地化的主要任务是翻译用户界面元素和文档。本地化不仅涉及改变语言交互,还涉及其他相关变化,比如数字、日期、货币的显示等。如果音频和图像等其他类型的数据在文化上敏感,可能需要本地化。应用程序国际化得越好,为特定语言和字符编码方案本地化就越容易。

一开始国际化可能看起来有点令人生畏。阅读以下章节将有助于您逐渐了解这个主题。

一个快速示例

本节向您展示如何逐步国际化一个简单的程序。

清单

所以你继承了一个需要国际化的程序,或者你正在计划确定新开发软件的需求。你可能不知道从哪里开始?查看这个清单。它总结了必要的国际化任务,并提供了本章相关课程的链接。

一个快速示例

原文:docs.oracle.com/javase/tutorial/i18n/intro/quick.html

如果你是国际化软件的新手,这节课适合你。这节课使用一个简单的示例来演示如何国际化程序,以便以适当的语言显示文本消息。你将学习如何LocaleResourceBundle对象一起工作,以及如何使用属性文件。

国际化前

源代码的第一个版本包含了硬编码的英文消息版本,这不是编写国际化软件的正确方式。

国际化后

这是我们的源代码在国际化后的 sneak preview。

运行示例程序

要运行示例程序,你需要在命令行上指定语言和国家。本节将向你展示一些示例。

国际化示例程序

国际化程序只需要几个步骤。你会惊讶于它是多么容易。

Java 中文官方教程 2022 版(二十八)(4)https://developer.aliyun.com/article/1486877

相关文章
|
7月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
363 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
3月前
|
Oracle Java 关系型数据库
java 编程基础入门级超级完整版教程详解
这份文档是针对Java编程入门学习者的超级完整版教程,涵盖了从环境搭建到实际项目应用的全方位内容。首先介绍了Java的基本概念与开发环境配置方法,随后深入讲解了基础语法、控制流程、面向对象编程的核心思想,并配以具体代码示例。接着探讨了常用类库与API的应用,如字符串操作、集合框架及文件处理等。最后通过一个学生成绩管理系统的实例,帮助读者将理论知识应用于实践。此外,还提供了进阶学习建议,引导学员逐步掌握更复杂的Java技术。适合初学者系统性学习Java编程。资源地址:[点击访问](https://pan.quark.cn/s/14fcf913bae6)。
306 2
|
8月前
|
消息中间件 Java 数据库
自研Java框架 Sunrays-Framework使用教程「博客之星」
### Sunrays-Framework:助力高效开发的Java微服务框架 **Sunrays-Framework** 是一款基于 Spring Boot 构建的高效微服务开发框架,深度融合了 Spring Cloud 生态中的核心技术组件。它旨在简化数据访问、缓存管理、消息队列、文件存储等常见开发任务,帮助开发者快速构建高质量的企业级应用。 #### 核心功能 - **MyBatis-Plus**:简化数据访问层开发,提供强大的 CRUD 操作和分页功能。 - **Redis**:实现高性能缓存和分布式锁,提升系统响应速度。 - **RabbitMQ**:可靠的消息队列支持,适用于异步
自研Java框架 Sunrays-Framework使用教程「博客之星」
|
9月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
8416 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
8月前
|
Java 数据库连接 数据处理
探究Java异常处理【保姆级教程】
Java 异常处理是确保程序稳健运行的关键机制。它通过捕获和处理运行时错误,避免程序崩溃。Java 的异常体系以 `Throwable` 为基础,分为 `Error` 和 `Exception`。前者表示严重错误,后者可细分为受检和非受检异常。常见的异常处理方式包括 `try-catch-finally`、`throws` 和 `throw` 关键字。此外,还可以自定义异常类以满足特定需求。最佳实践包括捕获具体异常、合理使用 `finally` 块和谨慎抛出异常。掌握这些技巧能显著提升程序的健壮性和可靠性。
133 4
|
8月前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
145 1
|
9月前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
556 26
|
8月前
|
前端开发 Java 开发工具
Git使用教程-将idea本地Java等文件配置到gitte上【保姆级教程】
本内容详细介绍了使用Git进行版本控制的全过程,涵盖从本地仓库创建到远程仓库配置,以及最终推送代码至远程仓库的步骤。
415 0
|
9月前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
9月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)

热门文章

最新文章