# 知识点汇总
# 在画面上显示字符
Java 编程语言拥有众多优点,支持面向对象编程。自从发布以来,随着其不断修订,使用者也越来越多。
Java 程序的开发需要免费的 Java 开发工具包,即 JDK 。
源程序是作为字符序列创建的。保存源程序的源文件的名称是类名加上 .java 扩展名。
源文件不能直接运行。使用 javac 命令编译后,会创建一个扩展名为 .class 的类文件。类文件的内容为字节码。
java 命令用于运行类文件中的类。
源程序的结构是类声明中包含 main 方法,main 方法中包含语句。
运行程序后,main 方法中的语句会被依次执行。
原则上语句的末尾是分号。
在画面上进行输出时程序会使用标准输出流。标准输出流的字符输出使用
System.out.print()
和System.out.println()
方法来执行。后一个方法在输出结束时会自动换行。表示字符序列的是字符串常量,其格式是用双引号将字符序列括起来。加号可以将字符串常量拼接起来。
转义字符
\n
表示换行符。源程序中应该简单明了地写上需要传达给包括编程者自身在内的程序阅读者的注释。注释的写法分为传统的注释、文档化注释、单行注释三种。
源程序中允许自由格式的技术。程序中应使用制表符或空格符进行适当的缩进,方便阅读。
# 使用变量
变量可以自由存取数值等数据。需要变量时,赋予其类型和名称,进行声明。
在从变量中取出值之前,必须进行初始化或赋值,将值赋给该变量。初始化是在创建变量时赋予初始值,赋值则是将值赋给创建好的变量。
变量时在需要时进行声明的。另外,最好在声明中赋上初始值,明确将变量初始化。
final变量通过初始化或赋值,只赋入一次值。在给常量赋予名称时可以使用该变量。
在诸多的类型中,Java 语言提供的标准类型是基本类型。
int 型是一种表示整数的整型。
像
13
这样的常量称为整数常量。double 型是一种表示实数(浮点数)的浮点型。
像
3.14
这样的常量称为浮点型常量。用于表示字符串(字符序列)的是 String 型。注意,该类型不是基本类型。
执行运算的符号是运算符,作为运算对象的表达式则是操作数。运算符根据操作数的个数分为 3 类:一元运算符、二元运算符、三元运算符。
用括号括起来的运算会优先执行。
在
字符串 + 数值
或数值 + 字符串
的运算中,数值要转换为字符串之后再进行拼接。读入通过键盘输入的值时使用标准输入流。Scanner类的
nextXxx()
方法用来读取标准输入流中的字符。通过生成随机数,可以创建随机的值。Random 类的
nextXxx()
方法用来生成随机数。通过
整数 / 整数
运算得到的商是舍去小数部分后的整数值。
# 程序流程之分支
所谓表达式,就是
变量
、常量
、通过运算符将变量和常量连接起来的式子
。表达式包含类型和值,它们在程序运行时通过求值获得。
给表达式加上分号的语句是表达式语句。只有分号的语句是空语句。
用大括号
{ }
将任意数量的语句括起来的语句是程序块,也叫复合语句。原则上,只在程序块中使用的变量在程序块中进行声明。如果仅当某个条件成立时才执行某条语句,可以使用 if 语句来实现。如果要根据条件的真假而执行不同的处理,可以使用 if-else 来实现。两者统称if 语句。
如果通过某个单一表达式的值将程序流程进行分支,最好使用switch 语句。分支跳转的位置是标签。如果没有与控制表达式的值相等的标签,则跳转到default 标签。
当 switch 语句中的 break 语句被执行时,switch 语句的执行将会终止。
各运算符的优先级和结合性是不同的。
优先级高的运算符比优先级低的运算符先执行。当优先级相同的运算符连续出现时,根据结核性,执行左运算或右运算 。
关系运算符、相等运算符、逻辑非运算符 可以生成 布尔型 的 true 或 false 。
使用逻辑与运算符和 逻辑或运算符的运算中会执行短路径求值。所谓段路径求值,就是当表达式的整体的值通过左操作数的值就可以确定时,将不再对右操作数进行求值。
当对赋值表达式进行求值时,可以得到赋值之后的左操作数的类型和值。
if 或 else 等词具有特殊的含义,称为关键字。
赋给变量和方法等的名称称为标识符。
所谓算法,就是“解决问题的方案,是一系列定义明确、有序并且数量有限的规则集合”。
# 程序流程之循环
循环分为在循环对象的处理执行之后判断循环是否继续的循环-判断,和处理执行之前判断循环是否继续的判断-循环。
循环-判断可以通过 do 语句来实现。
判断-循环可以通过 while 语句和for 语旬来实现。while 语句和 for 语句可以互相转换。
do 语句、while 语句和 for 语句统称为循环语句。作为循环对象的请句称为循环体。
循环-判断的 do 语句中,循环体一定会执行一次,
判断-循环的 while 语句和 for 语句中,循环体可能一次都不执行。
循环语句的循环体也可以是循环语句。这种结构的循环语句称为多重循环。
break 语句用于中断 switch 语句和循环语句的执行。
continue 语句和带标签的 continue 语句会跳过循环体中尚未执行的部分,前进到下一次循环。
当对使用了前置递增运算符/递减运算符的表达式进行求值时,可以得到操作数递增/递减(值只增加/减少1)后的值。
当对使用了后置递增运算符/递减运算符的表达式进行求值时,可以得到操作数递增/递减(值只增加/减少1)前的值。
在使用二元运算符的运算中,首先对左操作数进行求值,然后对右操作数进行求值、最后进行运算。
用单引号将一个字符括起来的
'X'
就是字符常量。复合赋值运算符会执行运算和赋值这两个操作。左操作数只求值一次。
使用
System out .println()
方法可以按指定格式显示数值或字符串。
# 基本类型和运算
Java 中可以使用的类型分为基本类型和引用类型。
基本类型分为数值类型和布尔型。数值类型又分为整型和浮点型。
整型是表示一定范围内连续的整数的类型。整型分为 char 型、byte 型、short 型、int 型、long 型。
char 型以外的整型是表示负值、0、正值的有符号整型。其内部通过补码表示的形式来表示
整数常量是 int 型,但如果加上整型后缀
L
或l
,就变成了 long 型。如果开头是0x
或0X
,则为十六进制整数常量,如果开头是0
并且是 2 位以上,则为八进制整数常量,否则便为十进制整数常量。浮点型由符号、指数、尾数构成,长度和精度存在一定限制。浮点型分为 float 型和 double 型。
浮点型常量是 double 型,但如果加上整型后缀
F
或f
,就变成了float型。表示真或假的是布尔型(boolean 型)表示真的布尔型常量为 true ,表示假的布尔型常量为 false 。
数值类型可以表示的数值范围
数值类型 | 变量类型 | 下限 | 上限 |
---|---|---|---|
整数 | char 型 | 0 | 65535 |
byte 型 | -128 | 127 | |
short 型 | -32768 | 32767 | |
int 型 | -2147483648 | 2147463647 | |
long 型 | -9223372036854775808 | 9223372036854775807 | |
浮点型 | float 型 | ±3.40282347E+38 | ±11.40239846E-45 |
double 型 | ±11.79769313486231507E+378 | ±4.94065645841246544E-324 |
当执行『字符串 + boolean值』 或者 『boolean值 + 字符串』的运算时,boolean 型的值会先转换为
"true"
或者"false"
字符串之后再进行拼接。二元算术运算中会对操作数进行双目数值提升。
使用 类型转换运算符
()
可以将操作数的值转换为任意类型的值。基本类型的缩小转换中,除了常量之外,原则上都必须进行显式类型转换。而基本类型的放大转换会自动执行,无需强制类型转换。
转义字符以开头为字符
\
的字符序列来表示单个字符。存在\n
、\t
等转义字符。
# 数组
数组是相同类型的变量的集合。各个变量是构成元素,变量的类型是构成元素类型,构成元素本身为数组的数组称为多维数组。
数组主体 是使用 new 运算符,在程序运行时动态创建的对象。数组变量引用该数组主体。
用于访问数组 a 中各个构成元素的表达式是对数组变量运用索引运算符的
a[i]
。方括号中的索引是从 0 开始连续编号的 int 型整数数值。数组中各个构成元素如果没有进行显式初始化,则会初始化为默认值 0(或等价形式)。
数组的初始化是将各个构成元素的初始值 xxx、yyy、zzz 用大括号括起来的
{xxx,yyy, zzz}
形式最后一个逗号可以省略。当为多维数组时,则使用嵌套结构。数组的构成元素个数可以使用
数组变量名.length
来获取。元素的遍历可以通过基本 for 语句 和 简洁 for 语句 来执行。使用赋值运算符
=
对数组变量进行赋值时,复制的是引用目标,而不是元素。对于 final 声明的数组,引用目标不可以被改写(元素的值可以修改)。
不引用任何对象的引用是空引用,表示空引用的空常量是 null 。
不再被任何变量引用的对象所占用的空间会通过垃级回收自动进行回收,可以再次被使用,
# 方法
统一的操作可以通过『方法』来实现。
方法的名称、返回类型、形参列表、方法体等的定义就是方法声明。
方法可以使用『方法调用运算符』(符号为
()
)进行调用。调用方法后,程序流程会从调用方跳转到被调用的方法。方法调用中的参数交换是通过值传递进行的。 调用方传递的实参值会初始化方法中接收的形参。即使被调用的方法内部改写了形参的值,调用方的实参值也不会发生改变。
方法使用 return 语句来返回值。执行 return 语句后,程序的流程会返回到调用方。返回的值为方法调用表达式的值。
不返回数值的方法的返回类型为 void 。
如果形参或返回类型为数组类型, 则可以接收数组,或返回数组。这种情况下交换的是数组的引用。
所谓方法的签名,就是方法名和形参的个数,类型的组合。签名中不包含返回类型。
可以对同一个类中签名不同的方法进行重载,赋给它们相同的名称,这样就可以防止方法名称过度增加。
在方法外部声明的变量,即字段。在该类的所有方法中都通用。而在方法内部声明的变量,即局部变量,只可以在该方法内部通用。
当相同名称的字段和局部变量同时存在时,字段会被隐藏。但被隐藏的字段可以使用
类名.字段名
进行访问。
# 类的基础知识
类是对字段、构造函数、方法等进行封装后的内容。
各个类应该实现为独立的源程序。
基于设计图的类创建的主体就是实例,使用 new 运算符可以执行实例化(创建实例)。
类类型变量是引用实例的变量。
未加 static 的字段是属于各个实例的,因此被称为实例变量,其值表示实例的状态。
字段的访问属性原则上必须设为私有(private)。由于对类的外部处隐爱的,因此可以实现数据隐藏。
构造函数与类名同名,没有返回类型。构造函数的作用是正确初始化实例。
未定义构造函数的类中,会自动定义一个不接收参数形式的默认构造函数。
未加 static 的方法是属于各个实例的,因此被称为实例方法,用来表示实例的动作。在调用实例方法时,会向实例发送消息。
类的成员(字段或方法等)可以通过使用成员访问运算符的表达式
类类型变量名.成员名
进行访问。在具有与类的字段同名的形参或局部变量的构造两数和实例方法的主体中,字段的名称会被隐藏。
构造两数和实例方法都持有 this 引用可以引用自身所属的实例。
在构造函数和实创方法中,对于类的字段
a
,不仅可以通过其名称a
进行访问,还可以通this.a
进行访问。
# 创建日期类
除了用完就舍弃的内容,类和方法的声明中都可以加上 public,这样就可以在任何地方使用。
在类中,可以根据需要定义访问器。用于获取字段 abc 的值的 getter 方法可以定义为
getAbe()
,用于设置值的 setter 方法可以定义为setAbe()
。当使用赋值或初始化复制类类型变量的值时,复制的并不是所有字段的值,而是引用目标。当通过方法的参数传递类类型的变量时,传递的是实例的引用。
当使用相等运算符比较类类型变量的值时,判断的是引用目标是否相等,而不是判断所有字段的值是否相等。
如果重载构造函数,该类的实例构建方法的选择范围就比较广了。在构造函数的开头,可以使用 this(...) 调用同一个类中的构造函数。
复制构造函数中会接收同一类类型的参数,并复制其全部字段的值,大家可以根据需要进行定义。
不应该将相同或者类似的代码分散在类中。如果要执行的处理在其他的方法或者构造函数中已经实现,就应该调用这个方法或者构造函数,委托其处理。
在类中,如果需要一个方法以字符串 表示来返回实例的“当前状态”,可以定义
public String toString() { ... }
。该方法在类型变量+字符中
和字符串+ 类类型变量
的运算中会被自动调用。创建类类型的数组时,类类型变量的全部元素都会被初始化为空引用 null。各个元素是类类型的变量,并不是实例,必须使用初始化成者眼值,将实例的引用赋给各个元素。
当类的字段是其他的类类型时,has-A关系成立。
# 10. 类变量和类方法
声明中加上 static 的字段和方法就是 类变量(静态字段)和 类方法(静态方法)。
类变量(静态字段)并不是属于各个实例的数据,而是该类的全部实例共享的数据。 与实例的个数无关(即使不存在实例),只有一个。使用
类名.字段名
进行动访问。提供给类的使用者的常量可以声明为 public 且 final 的类变量。
类方法(静态方法)不用于特定实例,而是用于与整个类相关的处理或者与类实例的状态无关的处理。使用
类名.方法名(...)
进行调用。重载是定义签名不同但名称相同的方法,可以对类方法和实例方法执行重载。
实例方法可以访问同一个类中的 实例变量(非静态字段)和 实例方法(非静态方法)。
类方法不可以访问同一个类中的实例变量(非静态宇段)和实例方法(非静态方法)。
不具有内部状态(实例变量),只提供类方法的类称为工具类。工具类适用于数值计算等某些特定领域的方法和常量的封装。
Math 工具类会提供数值计算所需的常量和众多方法。
类声明中的
static {/*..*/}
是 类初始化器(静态初始化器)。 类变量可以在类初始化器中进行初始化。当以某种方式首次使用类时,这个类的“类初始化器”就执行完毕了。
# 11. 包
包 是类和接口等类型的集合。包可以有层次结构,其配置与目录对应。
包名的首字母是小写字母。广泛公开的包可以使用与网址朋反的接列来取一个唯一的包名。
包 x.y.z 中 简名 为 Abc 的类型的 完全限定名 名为
x.y.z.Abc
。如果简名相同,但属于不同的包,则应该分开使用。同一个包中的类型名称可以用简名表示。
不同包中的类型名称使用完全限定名表示。不过,如果执行了 类型导入声明,则可以使用简名表示。类型导入声明分为 单类型导入声明 和 按需类型导入声明。不可以过多使用后一种声明。
java.lang
包是与 Java 语言紧密相关的类型的集合。对于该包中的类型名称,即使不导入,也可以通过简名进行使用。如果执行 静态导入声明,就可以使用简名来访问类变量和类方法。静态导人声明分为 单静态导入声明 和 按需静态导入声明 。
一个源程序中只可以有 0 个或 1 个包声明,无包声明的源程序中的类属于 无名包(默认包)。属于无名包的类的完全限定名和简名是一致的。
对于 public 类,包的内部和外部都可以对其进行访问。对于非 public 类,只可以在包的内部对其进行访问。一个源程序中最多只可以声明 1 个 public 类。
对于具有 公开(public)访问属性 的成员,包的内部和外部都可以对其进行访问。
对于具有 保护(protected)访问属性 的成员,包内部及该类派生的类可以对其进行访问。
对于具有 包(默认)访问属性 的成员,只可以在包中对其进行访问。
对于具有 私有(private)访问属性 的成员,只可以在该类内部对其进行访问。
# 12. 类的派生和多态
通过类的派生,可以简单创建 继承 已有类的资产的类。
派生源的类称为 超(基)类,通过派生创建的类称为 子(派生)类,派生赋予了类“血缘关系”。
未显示执行派生声明的类都是 Object 类 的子类。因此,Java 的所有类都是 Object 类的子(派生)类。
在类的派生中,构造函数不可以被继承。
在构造函数的开头,可以使用
super(...)
来调用超类的构造函数,如果未显式进行调用,编译器会自动插人一个超类的 “不接收参数的构造函数” 的调用在未定义构造函数的类中,编译器会自动定义一个只执行 super() 的 默认构造函数。如果超类中没有“不接收参数的构造函数”,则会发生编译错误。
超类中的非私有成员可以通过
super.成员名
进行访问。当类 B 为类 A 的派生类时,可以表示为“类 B 是 A 的 一种”,这种关系称为 is-A 关系。
如果超类类型的变量可以引用子类类型的实例,就可以实现 多态。在调用与多态相关的方法时,要调用的方法会在程序运行时确定,执行 动态联编。
子类类型的变量如果未执行转换,就不可以引用上位类类型的实例。
引用类型的放大转换(向上转型) 是将子类类型转换为超类类型,与之相反的转换是 引用类型的缩小转换(向下转型)。
对于要重写的方法,必须赋予与超类中的方法相同或更弱的访问控制修饰符。否则会发生编译错误。
注解 是传达给人类和编译器的注释。
当方法 重写 父类中的方法时,最好在声明中加上
@Override
注解。
# 13. 抽象类
声明中加上 abstract 的方法是 抽象方法 。抽象方法没有方法主体。
只要包含一个抽象方法,类就必须定义为 抽象类。抽象类的声明中需要加上 abstract。
无法创建抽象类的实例。
抽象类的类类型变量可以引用该类的子类实例,因此可以灵话应用多态。
重写超类中的抽象方法,定义方法主体的操作称为 实现方法。
超类中的非抽象方法可以在子类中被重写为抽象方法。
通过将 Object 类的非抽象方法
public String toString()
重写为抽象方法,可以强制该类的子类实现 toString() 方法。
# 14. 接口
接口 是引用类型的一种。
接口名称基本上都为名词。不过,表示“可...的”的接口名称建议使用
-able
。接口的成员为类、接口、常量、抽象方法。
接口的方法为
public
且abstract
。由于为抽象方法,因此不可以定义其主体。在实现接口的类的声明中,指定“implements 接口名”, 也能够同时实现多个接口。 在这种情况下,接口名使用逗号分隔。
当实现接口时,所有方法都应该赋上 public 修饰符来实现。未实现全部方法的类必须声明为抽象类。
接口的字段为 public 且 static 且 final,即为不可以改写数值的类变量。
实现接口的类内部可以使用字段的名称,即“字段名”来访问该接口的字段。其他的外部类则需要使用
接口名.字段名
进行访问。不可以创建接口类型的实例。
接口类型的变量可以引用实现该接口的类类型的实例。
类的派生和接口的实现可以同时执行。此时要先指定 extends,后指定 implements。
接口可以通过派生来创建扩展的新接口。
# 15. 字符和字符串
字符并不是通过拼写和发音,而是通过 字符编码 被识别的。 Java中采用的字符编码为 Unicode,字符是通过表示 0~65535 的无符号整数值的 char 型来表示的。
使用单引号将字符括起来的表达式 'x', 就是字符常量。 字符 '1' 和数值 1 是不一样的,不能混淆。
表示字符串的类型为
java.lang
包中的 String 类类型。字符串常量是用双引号将字符序列括起来的
"...."
形式,是 String 型实例的引用。拼写相同的字符串常量引用的是同一个实例。字符串的赋值并不是字符串的复制,而是引用的复制。
String 类中包含用于保存字符串的 char 型数组等字段,以及诸多的构造函数和方法。
当使用
String.format
方法时,可以执行格式化来创建字符串。格式化的指定与System.out.printf
方法相同。String 型为引用类型,因此,“字符串数组”中的各个元素并不是字符串本身,而是各个字符串的引用。
当使用基本类型的包装类的
parseXxx
方法时,可以将字符串转换为基本类型的数值。当程序启动时,通过命令行传人的字符串数组可以通过 main 方法的参数来接收。
# 16. 异常处理
所谓 异常,就是与程序预期的状态不一致的状态,或者在通常情况下未预料到(或无法预料)的状态。
通过异常处理,即对异常执行的处理,程序能够从可可能致命的状态中 恢复 过来。
throw 语句 用于抛出 异常。
try 语句 用于 捕获 抛出的异常并对异常进行处理。
对抛出的异常进行检在所需的代码要放在 try 语句块 中。对 try 语句块中检测出的异常进行捕获的是被称为 异常处理器 的 catch 子句。
无论是否发生异常,位于 try 语句末尾的 finally 子句 都会被执行。另外,finally 子句可以省略。
异常主体是 Throwable 类的子类的实例,包含 详细消息 和异常发生的 原因 等信息。
受检异常 是必须处理的异常,编译时会检查程序中是否对其进行了处理(捕获或者列举在 throws 子句中)。
当方法可能会抛出检查异常时,必须将这些异常列举在 throws 子句 中。
非检查异常 是并非一定要处理的异常。编译时不会检在是否对其进行了处理。
Throwable 类的子类有 Exception 类和 RuntimeException 类。
Exception 类及其子类为受检异常,但 RuntimeException 及其子类为非受检异常。
对于捕获的异常,在执行了某些处理后仍无法完全处理时,可以(直接或者改变形式)再次抛出 异常。