Java 中文官方教程 2022 版(五)(1)https://developer.aliyun.com/article/1486294
当抽象类实现接口时
在接口
部分中指出,实现接口的类必须实现所有接口的方法。然而,可以定义一个不实现所有接口方法的类,只要该类声明为abstract
。例如,
abstract class X implements Y { // implements all but one method of Y } class XX extends X { // implements the remaining method in Y }
在这种情况下,类X
必须是abstract
,因为它没有完全实现Y
,但事实上,类XX
实现了Y
。
类成员
一个抽象类可能有static
字段和static
方法。您可以像使用其他类一样使用这些静态成员,通过类引用(例如,AbstractClass.staticMethod()
)。
继承摘要
原文:
docs.oracle.com/javase/tutorial/java/IandI/summaryinherit.html
除了Object
类外,一个类只有一个直接的父类。一个类从所有直接或间接的父类那里继承字段和方法。子类可以重写继承的方法,或者隐藏继承的字段或方法。(请注意,隐藏字段通常是不良的编程实践。)
在覆盖和隐藏方法部分的表格显示了声明具有与超类中方法相同签名的方法的效果。
Object
类是类层次结构的顶部。所有类都是从这个类继承的后代,并从中继承方法。从Object
继承的有用方法包括toString()
,equals()
,clone()
和getClass()
。
通过在类的声明中使用final
关键字,可以防止类被子类化。同样,通过将方法声明为最终方法,可以防止子类覆盖它。
抽象类只能被子类化;它不能被实例化。抽象类可以包含抽象方法—声明但未实现的方法。然后子类为抽象方法提供实现。
问题和练习:继承
原文:
docs.oracle.com/javase/tutorial/java/IandI/QandE/inherit-questions.html
问题
1. 考虑以下两个类:
public class ClassA { public void methodOne(int i) { } public void methodTwo(int i) { } public static void methodThree(int i) { } public static void methodFour(int i) { } } public class ClassB extends ClassA { public static void methodOne(int i) { } public void methodTwo(int i) { } public void methodThree(int i) { } public static void methodFour(int i) { } }
a. 哪个方法覆盖了超类中的方法?
b. 哪个方法隐藏了超类中的方法?
c. 其他方法做什么?
2. 考虑你在问题和练习:类中编写的Card
、Deck
和DisplayDeck
类。每个类应该覆盖哪些Object
方法?
练习
1. 编写你在问题 2 中回答的方法的实现。
检查你的答案。
课程:数字和字符串
数字
这一部分从讨论Number
类(位于java.lang
包中)及其子类开始。特别是,本节讨论了在何种情况下您会使用这些类的实例化而不是原始数据类型。此外,本节还讨论了您可能需要与数字一起工作的其他类,例如格式化或使用数学函数来补充语言内置的运算符。最后,还讨论了自动装箱和拆箱,这是一种简化代码的编译器功能。
字符串
字符串在 Java 编程中被广泛使用,它们是字符序列。在 Java 编程语言中,字符串是对象。本节描述了使用String
类来创建和操作字符串。它还比较了String
和StringBuilder
类。
数字
本节开始讨论java.lang
包中的Number
类,它的子类,以及在何种情况下您会使用这些类的实例化而不是原始数字类型。
本节还介绍了PrintStream
和DecimalFormat
类,它们提供了用于编写格式化数字输出的方法。
最后,讨论了java.lang
中的Math
类。它包含了用于补充语言内置运算符的数学函数。该类具有三角函数、指数函数等方法。
数字类
原文:
docs.oracle.com/javase/tutorial/java/data/numberclasses.html
在处理数字时,大多数情况下您会在代码中使用原始类型。例如:
int i = 500; float gpa = 3.65f; byte mask = 0x7f;
然而,有理由使用对象代替原始类型,并且 Java 平台为每种原始数据类型提供了包装类。这些类将原始类型“包装”在对象中。通常,编译器会执行包装操作—如果您在期望对象的地方使用原始类型,编译器会为您将原始类型装箱到其包装类中。同样,如果您在期望原始类型的地方使用数字对象,编译器会为您拆箱对象。有关更多信息,请参阅自动装箱和拆箱
所有数字包装类都是抽象类Number
的子类:
注意: 还有四个Number
的子类没有在此处讨论。BigDecimal
和BigInteger
用于高精度计算。AtomicInteger
和AtomicLong
用于多线程应用程序。
有三个原因可能会使用Number
对象而不是原始类型:
- 作为期望对象的方法的参数(在操作数字集合时经常使用)。
- 要使用类定义的常量,如
MIN_VALUE
和MAX_VALUE
,提供数据类型的上限和下限。 - 要使用类方法将值转换为其他原始类型,将值转换为字符串,以及在不同数字系统之间进行转换(十进制、八进制、十六进制、二进制)。
以下表格列出了所有Number
类的子类实现的实例方法。
所有Number
子类实现的方法
方法 | 描述 |
| `byte byteValue() short shortValue()
int intValue()
long longValue()
float floatValue()
double doubleValue() | 将此
Number`对象的值转换为返回的原始数据类型。 |
| `int compareTo(Byte anotherByte) int compareTo(Double anotherDouble)
int compareTo(Float anotherFloat)
int compareTo(Integer anotherInteger)
int compareTo(Long anotherLong)
int compareTo(Short anotherShort) | 将此
Number`对象与参数进行比较。 |
| boolean equals(Object obj)
| 确定此数字对象是否等于参数。如果参数不为null
且为相同类型且具有相同数值的对象,则方法返回true
。
对于Double
和Float
对象,还有一些额外的要求,这些要求在 Java API 文档中有描述。 |
每个Number
类包含其他方法,用于将数字转换为字符串,以及在不同数字系统之间进行转换。以下表格列出了Integer
类中的这些方法。其他Number
子类的方法类似:
转换方法,Integer
类
方法 | 描述 |
static Integer decode(String s) |
将字符串解码为整数。可以接受十进制、八进制或十六进制数字的字符串表示作为输入。 |
static int parseInt(String s) |
返回一个整数(仅限十进制)。 |
static int parseInt(String s, int radix) |
返回一个整数,给定十进制、二进制、八进制或十六进制(radix 分别等于 10、2、8 或 16)数字的字符串表示作为输入。 |
String toString() |
返回表示此Integer 值的String 对象。 |
static String toString(int i) |
返回表示指定整数的String 对象。 |
static Integer valueOf(int i) |
返回一个包含指定原始值的Integer 对象。 |
static Integer valueOf(String s) |
返回一个Integer 对象,其中包含指定字符串表示形式的值。 |
static Integer valueOf(String s, int radix) |
返回一个Integer 对象,其中包含指定字符串表示形式的整数值,使用基数进行解析。例如,如果s = "333" 且radix = 8 ,则该方法返回八进制数 333 的十进制整数等价值。 |
格式化数字打印输出
原文:
docs.oracle.com/javase/tutorial/java/data/numberformat.html
之前你看到了使用print
和println
方法将字符串打印到标准输出(System.out
)的示例。由于所有数字都可以转换为字符串(稍后将会看到),你可以使用这些方法打印任意混合的字符串和数字。然而,Java 编程语言还有其他方法,允许你在包含数字时更好地控制打印输出。
printf
和format
方法
java.io
包中包含一个PrintStream
类,其中有两个格式化方法可用于替换print
和println
。这些方法,format
和printf
,是等效的。你一直在使用的熟悉的System.out
恰好是一个PrintStream
对象,因此你可以在System.out
上调用PrintStream
方法。因此,在你以前使用print
或println
的代码中,你可以使用format
或printf
。例如,
System.out.format(.....);
这两个java.io.PrintStream
方法的语法是相同的:
public PrintStream format(String format, Object... args)
其中format
是一个指定要使用的格式化的字符串,args
是要使用该格式化打印的变量列表。一个简单的示例可能是
System.out.format("The value of " + "the float variable is " + "%f, while the value of the " + "integer variable is %d, " + "and the string is %s", floatVar, intVar, stringVar);
第一个参数,format
,是一个格式字符串,指定了第二个参数args
中的对象如何被格式化。格式字符串包含普通文本以及格式说明符,这些是特殊字符,用于格式化Object... args
的参数。(Object... args
的表示法称为可变参数,意味着参数的数量可能变化。)
格式说明符以百分号(%)开始,并以转换器结束。转换器是指示要格式化的参数类型的字符。在百分号(%)和转换器之间,你可以有可选的标志和说明符。有许多转换器、标志和说明符,这些都在java.util.Formatter
中有文档记录。
这里是一个基本示例:
int i = 461012; System.out.format("The value of i is: %d%n", i);
%d
指定单个变量为十进制整数。%n
是一个与平台无关的换行符。输出为:
The value of i is: 461012
printf
和format
方法是重载的。每个都有以下语法版本:
public PrintStream format(Locale l, String format, Object... args)
例如,要在法国系统中打印数字(在英文浮点数表示中使用逗号代替小数点),你可以使用:
System.out.format(Locale.FRANCE, "The value of the float " + "variable is %f, while the " + "value of the integer variable " + "is %d, and the string is %s%n", floatVar, intVar, stringVar);
一个示例
下表列出了在接下来的示例程序TestFormat.java
中使用的一些转换器和标志。
在TestFormat.java
中使用的转换器和标志
转换器 | 标志 | 说明 |
d | 十进制整数。 | |
f | 一个浮点数。 | |
n | 适用于运行应用程序的平台的换行符。应始终使用%n ,而不是\n 。 |
|
tB | 日期和时间转换—月份的区域设置全名。 | |
td, te | 日期和时间转换—月份中的 2 位数字。td 根据需要带有前导零,te 则不带。 | |
ty, tY | 日期和时间转换—ty = 2 位年份,tY = 4 位年份。 | |
tl | 日期和时间转换—12 小时制钟表中的小时。 | |
tM | 日期和时间转换—以 2 位数字表示的分钟,必要时带有前导零。 | |
tp | 日期和时间转换—区域设置特定的上午/下午(小写)。 | |
tm | 日期和时间转换—月份以 2 位数字表示,必要时带有前导零。 | |
tD | 日期和时间转换—日期为 %tm%td%ty | |
08 | 宽度为 8 个字符,必要时带有前导零。 | |
+ | 包括符号,无论是正数还是负数。 | |
, | 包括特定于区域设置的分组字符。 | |
- | 左对齐。 | |
.3 | 小数点后三位。 | |
10.3 | 宽度为 10 个字符,右对齐,小数点后三位。 |
以下程序展示了您可以使用format
进行的一些格式化。输出在嵌入式注释中用双引号显示:
import java.util.Calendar; import java.util.Locale; public class TestFormat { public static void main(String[] args) { long n = 461012; System.out.format("%d%n", n); // --> "461012" System.out.format("%08d%n", n); // --> "00461012" System.out.format("%+8d%n", n); // --> " +461012" System.out.format("%,8d%n", n); // --> " 461,012" System.out.format("%+,8d%n%n", n); // --> "+461,012" double pi = Math.PI; System.out.format("%f%n", pi); // --> "3.141593" System.out.format("%.3f%n", pi); // --> "3.142" System.out.format("%10.3f%n", pi); // --> " 3.142" System.out.format("%-10.3f%n", pi); // --> "3.142" System.out.format(Locale.FRANCE, "%-10.4f%n%n", pi); // --> "3,1416" Calendar c = Calendar.getInstance(); System.out.format("%tB %te, %tY%n", c, c, c); // --> "May 29, 2006" System.out.format("%tl:%tM %tp%n", c, c, c); // --> "2:34 am" System.out.format("%tD%n", c); // --> "05/29/06" } }
注意: 本节讨论仅涵盖了format
和printf
方法的基础知识。更详细的信息可以在基础教程的基本 I/O
部分的“格式化”页面中找到。
使用String.format
创建字符串的方法在字符串中有介绍。
DecimalFormat 类
您可以使用java.text.DecimalFormat
类来控制前导和尾随零、前缀和后缀、分组(千位)分隔符以及小数点分隔符的显示。DecimalFormat
在数字格式化方面提供了很大的灵活性,但可能会使您的代码变得更加复杂。
接下来的示例创建了一个DecimalFormat
对象myFormatter
,通过将模式字符串传递给DecimalFormat
构造函数来创建。然后通过myFormatter
调用从NumberFormat
继承的format()
方法—它接受一个double
值作为参数,并以字符串形式返回格式化的数字:
这是一个演示DecimalFormat
使用的示例程序:
import java.text.*; public class DecimalFormatDemo { static public void customFormat(String pattern, double value ) { DecimalFormat myFormatter = new DecimalFormat(pattern); String output = myFormatter.format(value); System.out.println(value + " " + pattern + " " + output); } static public void main(String[] args) { customFormat("###,###.###", 123456.789); customFormat("###.##", 123456.789); customFormat("000000.000", 123.78); customFormat("$###,###.###", 12345.67); } }
输出为:
123456.789 ###,###.### 123,456.789 123456.789 ###.## 123456.79 123.78 000000.000 000123.780 12345.67 $###,###.### $12,345.67
以下表格解释了每行输出。
DecimalFormat.java
输出
值 | 模式 | 输出 | 解释 |
123456.789 | ###,###.### | 123,456.789 | 井号(#)表示数字,逗号是分组分隔符的占位符,句点是小数分隔符的占位符。 |
123456.789 | ###.## | 123456.79 | value 小数点右侧有三位数字,但pattern 只有两位。format 方法通过四舍五入处理这个问题。 |
123.78 | 000000.000 | 000123.780 | pattern 指定了前导和尾随零,因为使用的是 0 字符而不是井号(#)。 |
12345.67 | $###,###.### | $12,345.67 | pattern 中的第一个字符是美元符号($)。请注意,它紧跟在格式化output 中最左边的数字之前。 |
超出基本算术
原文:
docs.oracle.com/javase/tutorial/java/data/beyondmath.html
Java 编程语言支持基本算术运算,使用算术运算符:+,-,*,/和%。java.lang
包中的Math
类提供了更高级数学计算的方法和常量。
Math
类中的方法都是静态的,因此您可以直接从类中调用它们,如下所示:
Math.cos(angle);
注意: 使用static import
语言特性,您不必在每个数学函数前面写Math
:
import static java.lang.Math.*;
这使您可以通过简单名称调用Math
类的方法。例如:
cos(angle);
常量和基本方法
Math
类包括两个常量:
Math.E
,即自然对数的底数,以及Math.PI
,即圆周与直径的比值。
Math
类还包括 40 多个静态方法。以下表格列出了一些基本方法。
基本数学方法
方法 | 描述 |
| `double abs(double d) float abs(float f)
int abs(int i)
long abs(long lng)
| 返回参数的绝对值。 |
double ceil(double d) |
返回大于或等于参数的最小整数。返回为 double 类型。 |
double floor(double d) |
返回小于或等于参数的最大整数。返回为 double 类型。 |
double rint(double d) |
返回与参数最接近的整数值。返回为 double 类型。 |
long round(double d) int round(float f) |
返回最接近参数的 long 或 int,如方法的返回类型所示。 |
| `double min(double arg1, double arg2) float min(float arg1, float arg2)
int min(int arg1, int arg2)
long min(long arg1, long arg2)
| 返回两个参数中较小的值。 |
| `double max(double arg1, double arg2) float max(float arg1, float arg2)
int max(int arg1, int arg2)
long max(long arg1, long arg2)
| 返回两个参数中较大的值。 |
以下程序,BasicMathDemo
,演示了如何使用其中一些方法:
public class BasicMathDemo { public static void main(String[] args) { double a = -191.635; double b = 43.74; int c = 16, d = 45; System.out.printf("The absolute value " + "of %.3f is %.3f%n", a, Math.abs(a)); System.out.printf("The ceiling of " + "%.2f is %.0f%n", b, Math.ceil(b)); System.out.printf("The floor of " + "%.2f is %.0f%n", b, Math.floor(b)); System.out.printf("The rint of %.2f " + "is %.0f%n", b, Math.rint(b)); System.out.printf("The max of %d and " + "%d is %d%n", c, d, Math.max(c, d)); System.out.printf("The min of of %d " + "and %d is %d%n", c, d, Math.min(c, d)); } }
这个程序的输出如下:
The absolute value of -191.635 is 191.635 The ceiling of 43.74 is 44 The floor of 43.74 is 43 The rint of 43.74 is 44 The max of 16 and 45 is 45 The min of 16 and 45 is 16
Java 中文官方教程 2022 版(五)(3)https://developer.aliyun.com/article/1486296