第一单元:java平台概述
JAVA语言:
跟任何编程语言一样,Java 语言拥有自己的结构、语法规则和编程范例。Java 语言的编程范例基于面向对象编程 (OOP) 的概念,该语言的特性支持这一概念。
Java 语言是 C 语言的一种衍生语言,所以它的语法规则与 C 语言的语法规则非常相似。例如,方法使代码模块化并使用花括号({ 和 })分隔,变量需要在使用之前声明。
在结构上,Java 语言以包 作为开头。包是 Java 语言的命名空间机制。包中包含类,而类中包含方法、变量、常量等。
JVM:
在 Java 平台编写程序时,您会在 .java 文件中编写源代码,然后编译它们。编译器针对语言的语法规则来检查代码,然后将字节码 写出到 .class 文件中。字节码是一组需要在 Java 虚拟机 (JVM) 上运行的指令。
在运行时,JVM 读取并解释 .class 文件,在编写的 JVM 的目标原生硬件平台上执行程序的指令。JVM 解释字节码就像 CPU 解释汇编语言指令一样。不同之处在于,JVM 是一个专为特定平台编写的软件。JVM 是 Java 语言的 “编写一次、随处运行” 原则的核心。您的代码可在任何拥有合适的 JVM 实现的芯片集上运行。
垃圾收集器
Java 平台不会强制您时刻关注内存分配(或使用第三方库来完成此工作),它提供了开箱即用的内存管理功能。当您的 Java 应用程序在运行时创建一个对象实例时,JVM 会自动从堆 中为该对象分配内存空间— 堆是一个专门留给您的程序使用的内存池。Java 垃圾收集器 在后台运行,跟踪记录应用程序不再需要哪些对象并从它们回收内存。这种内存处理方法称为隐式内存管理,因为它不需要您编写任何内存处理代码。垃圾收集是 Java 平台性能的基本特征之一。
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-java-platform-overview/index.html
第 2 单元:设置 Java 开发环境
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-setting-up-your-java-development-environment/index.html
第 3 单元:面向对象编程的概念和原理
什么是对象?
Java 语言(基本上)是面向对象的。
面向对象的语言遵循的编程模式不同于结构化编程语言,比如 C 和 COBOL。结构化编程范例是高度面向数据的:您拥有数据结构,然后程序指令处理该数据。面向对象的语言(比如 Java 语言)将数据和程序指令组合到对象 中。
对象是一个自成一体的实体,它仅包含属性和行为,不含任何其他内容。不需要拥有包含字段(属性)的数据结构并将该结构传递到处理它(行为)的所有程序逻辑,在面向对象的语言中,数据和程序逻辑组合在一起。
OOP的原则
封装
回想一下,一个对象是离散的或独立的。此特征是封装 的工作原理。对象在它的状态和行为与外部世界之间保持一条界线。在 Java 平台上,可以使用访问修饰符(后面将会介绍)来区分公共 与私有 对象关系的性质。公共访问是完全开放的,而私有访问意味着对象的属性仅可在对象自身内访问。
公共/私有边界采取面向对象的封装原则。在 Java 平台上,可以逐个对象地改变该边界的强度。封装是 Java 语言的一个强大特性。
继承
OOP 引入了继承 的概念,使得特殊化的类 — 无需额外的代码 — 可以 “复制” 它们要特殊化的来源类的属性和行为。如果其中一些属性或行为需要更改,您可覆盖它们。您更改的唯一的源代码是创建特殊化的类所需的代码。来源对象称为父对象,新的特殊化对象称为子对象
多态性
在本质上,多态性表示属于一个分层结构的同一个分支的对象,在发送相同的消息时(也即在被告知执行同一件事时),可通过不同方式表现出该行为。
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-object-oriented-programming-concepts-and-principles/index.html
第 4 单元:Java 语言入门
java类的结构
package packageName;
import ClassNameToImport;
accessSpecifier class ClassName {
accessSpecifier dataType variableName [= initialValue];
accessSpecifier ClassName([argumentList]) {
constructorStatement(s)
}
accessSpecifier returnType methodName ([argumentList]) {
methodStatement(s)
}
// This is a comment
/* This is a comment too */
/* This is a
multiline
comment */
}
#实例
package com.makotojava.intro;
public class Person {
private String name;
private int age;
private int height;
private int weight;
private String eyeColor;
private String gender;
public Person() {
// Nothing to do...
}
public Person(String name, int age, int height, int weight String eyeColor, String gender) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
this.eyeColor = eyeColor;
this.gender = gender;
}
public String getName() { return name; }
public void setName(String value) { name = value; }
// Other getter/setter combinations...
}
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-getting-started-with-the-java-language/index.html
第 5 单元:您的第一个 Java 类
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-your-first-java-class/index.html
第 6 单元:向一个 Java 类添加行为
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-adding-behavior-to-a-java-class/index.html
第 7 单元:字符串和运算符
字符串
以下是两种创建字符串的方法,我们以创建一个名为 greeting 且值为 hello 的 String 实例为例:
greeting = new String("hello");
String greeting = "hello";
#串联字符串
str1 + str2
str1.concat(str2).concat(str3)
运算符
java 语言使用两种类型的运算符:
- 一元:仅需要一个操作数。
- 二元:需要两个操作数。
运算符 | 用法 | 描述 |
---|---|---|
++ | a++ | 将 a 递增 1;计算递增之前 a 的值 |
++ | ++a | 将 a 递增 1;计算递增之后 a 的值 |
-- | a-- | 将 a 递减 1;计算递减之前 a 的值 |
-- | --a | 将 a 递减 1;计算递减之后 a 的值 |
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-strings-and-operators/index.html
第 8 单元:条件运算符和控制语句
三元运算符
Java 语言提供了一个方便的运算符来执行简单的 if / else 语句检查。这个运算符的语法是:
(conditional) ? statementIfTrue : statementIfFalse;
如果 conditional 计算为 true,则执行 statementIfTrue;否则执行 statementIfFalse。每条语句均不允许采用复合语句形式。
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-conditional-operators-and-control-statements/index.html
第 9 单元:循环
public boolean method3() {
boolean a = true;
boolean b = false;
boolean c;
if (a = b)
c = false;
else
c = a;
return c;
}
#答案是false
public int method1() {
int a = 10;
int b = 7;
int c = 0;
if (b >= a)
c++;
b = -47;
if (b > c)
c = b;
return c;
}
#答案是0
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-loops/index.html
第 10 单元:Java 集合
数组
#创建数组
int[] integers = new int[5];
int[] integers = new int[] { 1, 2, 3, 4, 5 };
int[] integers = { 1, 2, 3, 4, 5 };
int[] integers = new int[5];
for (int aa = 0; aa < integers.length; aa++) {
integers[aa] = aa+1;
}
装箱与拆箱
#装箱
int value = 238;
Integer boxedValue = Integer.valueOf(value);
#拆箱
Integer boxedValue = Integer.valueOf(238);
int intValue = boxedValue.intValue();
#自动装箱和自动拆箱
int intValue = 238;
Integer boxedValue = intValue;
intValue = boxedValue;
#解析和转换装箱的类型
String characterNumeric = "238";
Integer convertedValue = Integer.parseInt(characterNumeric);
Integer boxedValue = Integer.valueOf(238);
String characterNumeric = boxedValue.toString();
列表
List 是一种有序集合,也称为序列。因为 List 是有序的,所以您能够完全控制项目进入 List 中的何处。Java List 集合只能包含对象(不能包含像 int 这样的原语类型),而且它为其行为方式定义了严格的契约。
List 是一个接口,所以不能直接实例化它。这里将使用它的最常用实现 ArrayList。
#创建列表
List listOfStrings = new ArrayList();
List listOfStrings = new ArrayList<>();
List listOfIntegers = new ArrayList<>();
listOfIntegers.add(Integer.valueOf(238));
listOfIntegers.size()
listOfIntegers.get(0)
集(Set)
根据定义,Set 是一种包含唯一元素的集合结构 — 即没有重复元素。List 可包含同一个对象数百次,而 Set 仅可包含某个特定实例一次。Java Set 集合仅可包含对象,而且它为它的行为方式定义了严格的契约。
因为 Set 是一个接口,所以不能直接实例化它。我最喜欢的实现之一是 HashSet,它很容易使用且类似于 List。
Set setOfIntegers = new HashSet();
setOfIntegers.add(Integer.valueOf(10));
映射(Map)
Map 是一种方便的集合构造,可以使用它将一个对象(键)与另一个对象(值)相关联。您可能已想象到,Map 的键必须是唯一的,而且可在以后用于检索值。Java Map 集合仅可包含对象,而且它为其行为方式定义了严格的契约。
因为 Map 是一个接口,所以不能直接实例化它。我最喜欢的实现之一是 HashMap。
Map mapOfIntegers = new HashMap<>();
mapOfIntegers.put("1", Integer.valueOf(1));
Integer oneHundred68 = mapOfIntegers.get("168");
Set keys = mapOfIntegers.keySet();
public void question5() {
int[] intArray = new int[4];
intArray[0] = 1;
intArray[1] = 2;
intArray[2] = Integer.valueOf(3);
intArray[3] = Integer.MAX_VALUE;
}
#该代码没有错误。通过自动拆箱,可将 Integer 对象赋给 int 数组。
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-java-collections/index.html
第 11 单元:存档 Java 代码
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-archiving-java-code/index.html
第 12 单元:编写良好的 Java 代码
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-writing-good-java-code/index.html
第 13 单元:对象的后续处理
重载方法
创建两个具有相同名称和不同参数列表(即不同的参数数量或类型)的方法时,您就拥有了一个重载 方法。在运行时,JRE 基于传递给它的参数来决定调用您的重载方法的哪个变体。
在使用重载方法时,请记住两条重要规则:
- 不能仅通过更改一个方法的返回类型来重载它。
- 不能拥有两个具有相同名称和相同参数列表的方法。
如果违背这些规则,编译器就会抛出错误。
重写方法
如果一个子类提供其父类中定义的方法的自有实现,这被称为方法重写。
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-next-steps-with-objects/index.html
第 14 单元:异常
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-exceptions/index.html
第 15 单元:构建 Java 应用程序
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-building-java-applications/index.html
第 16 单元:继承
Java 语言仅支持单一继承,这意味着您只能对一个类使用 extends 关键字。所以任何 Java 类的类分层结构始终包含一直连接到 java.lang.Object 的一条直线。Java 语言支持在单个类中实现多个接口,为您提供单一继承问题的解决办法。
构造方法不是完整的面向对象成员,所以它们不是继承的;必须在子类中显式实现它们。
抽象化:两条规则
作为一条经验规则,不要在初始设计中抽象化。在设计过程的早期使用抽象类会迫使您进入一条可能限制您的应用程序的设计路线。您可以始终在继承图中的更高层级上重构常见行为(这是拥有抽象类的唯一理由) — 而且在发现您需要重构后再重构似乎总是更好一些。Eclipse 对重构提供了极好的支持。
第二,尽管抽象类很强大,仍要拒绝使用它们。除非您的超类包含大量相同的行为,而且这些超类本身没有意义,否则保持它们非抽象化。较深的继承图可能使代码维护变得很困难。请考虑太大的类与可维护的代码之间的利弊。
更多详情请见https://www.ibm.com/developerworks/cn/java/j-perry-inheritance/index.html
第 17 单元:接口
当您在应用程序中看到一组可分组到一起的常见行为,但它们存在两个或多个实现时,可以考虑使用接口 定义该行为,这正是 Java 语言提供此特性的原因。但是,这个高级特性很容易被滥用、混淆和变成最讨厌的形式,所以使用接口时需要小心谨慎。
以这种方式考虑接口可能有所帮助:它们像仅包含抽象方法的抽象类;它们仅定义契约,而不定义实现。
定义接口的语法
public interface InterfaceName {
returnType methodName(argumentList);
}
第 18 单元:嵌套类
嵌套类(或内部类) 是在一个类中定义的另一个类。
#公共嵌套类
public class Manager extends Employee {
public Manager() {
}
. . .
public class DirectReports {
. . .
}
}
// Meanwhile, in another method somewhere...
public static void main(String[] args) {
Manager manager = new Manager();
Manager.DirectReports dr = manager.new DirectReports();
}
#静态内部类
public class Manager extends Employee {
public Manager() {
}
. . .
public static class DirectReports {
. . .
}
}
// Meanwhile, in another method somewhere...
public static void main(String[] args) {
Manager.DirectReports dr = new Manager.DirectReports();
}
第 19 单元:正则表达式
Regular Expressions API 有 3 个您几乎总是在使用的核心类:
- Pattern 描述了一种字符串模式。
- Matcher 测试一个字符串,查看它是否与该模式匹配。
- PatternSyntaxException 告诉您,您尝试定义的模式的某个方面无法被接受。
Pattern pattern = Pattern.compile("[Aa].*string");
Matcher matcher = pattern.matcher("A string");
boolean didMatch = matcher.matches();
int patternStartIndex = matcher.start();
int patternEndIndex = matcher.end();
while (matcher.find()) {
matcher.group();
}
String result = matcher.replaceAll("replacement");
第 20 单元:泛型
泛型是一种编译器机制,您可通过该机制获取通用的代码并参数化(或模板化)剩余部分,从而以一种一般化方式创建(和使用)一些类型的实体(比如类或接口和方法)。这种编程方法被称为泛型编程。
参数化的类:
List
参数化的方法:
enum 类型:
enum 表示一组与某个特定概念相关的常量对象,每个对象都表示该集合中的一个不同的常量值。事实上,enum 非常像类,所以它们可拥有构造方法、属性和方法。类与 enum 的一个区别是,enum 的构造方法必须声明为 private,而且它无法扩展(或继承)其他 enum。但是,一个 enum可以 实现一个接口。
public enum Gender {
MALE,
FEMALE,
OTHER
}
第 21 单元:I/O
import java.io.File;
File f = new File("temp.txt");
if (f.exists()) {
// File exists. Process it...
} else {
// File doesn't exist. Create it...
f.createNewFile();
}
字节流读(InputStream 和子类)和写(OutputStream 和子类)8 位字节。
字符流读(Reader 和它的子类)和写(Writer 和它的子类)16 位字符。
第 22 单元:Java 序列化
在序列化 的过程中,对象和它的元数据(比如对象的类名和它的属性名称)存储为一种特殊的二进制格式。将对象存储为这种格式(序列化 它)会保留所有必要的信息,使您在需要时能够重建(或去序列化)对象。
对象序列化的两个主要使用场景包括:
- 对象持久化:将对象的状态存储在一种永久的持久性机制中,比如数据库
- 对象远程存储:将对象发送到另一台计算机或另一个系统
实现序列化的第一步是使对象能够使用该机制。您希望能够序列化的每个对象必须实现一个名为 java.io.Serializable 的接口:
import java.io.Serializable;
public class Person implements Serializable {
// etc...
}
如果 Java 运行时尝试序列化您的对象,无法序列化的对象的每个属性会导致它抛出一个 NotSerializableException。可以使用 transient 关键字管理此行为,告诉运行时不要尝试序列化一些属性。在这种情况下,您应该负责确保恢复这些属性(在必要时),以便您的对象能正常运行。