第一章
编译和解释
- 解释器
The interpreter examines each line of a computer program and executes that line, then proceeds to the next line.
解释器检查计算机程序的每一行并且运行,然后继续下一行。
The biggest advantage of interpreted languages is that they are faster to test.
解释型语言测试速度快。
The primary disadvantage is that interpreted languages run slower than other programs. Each line has to be translated into instructions the computer can run, one line at a time.
解释型语言的主要缺点是比其他程序运行速度慢。每一行需要翻译成计算机可以执行的指令,一次一行。
- 编译器
The compiler takes a program and translates it into a form that the computer can understand. It also makes the program run as efficiently as possible.
编译器将程序转换成计算机可以理解的形式。同时使程序尽可能高效运行。
Compiled programs run more quickly than interpreted programs but take more time to test.
编译的程序比解释的程序运行速度更快,但是需要更多时间测试。
- JAVA虚拟机
Java is unusual because it requires both a compiler and an interpreter. The compiler converts the statements that make up the program into bytecode. Once this bytecode has been created successfully, it can be run by an interpreter called the Java Virtual Machine.
Java不同寻常,因为它同时需要编译器和解释器。编译器将程序语句转化为字节码(bytecode)。一旦成功创建了字节码,它可以被称作Java虚拟机的解释器所运行。
The Java Virtual Machine, also called a JVM, is the thing that makes it possible for the same Java program to run without modification on different operating systems and different kinds of computing devices. The virtual machine turns bytecode into instructions that a particular device's operating system can execute.
Java虚拟机,又叫JVM,使得相同的Java程序可以在不同的操作系统和不同的计算设备上运行,而不需要修改。虚拟机将字节码转换成特定设备的操作系统可以运行的指令。
第二章
The main
statement is the entry point to most Java programs. The exceptions are applets
, programs that are run on a web page by a web browser; servlets
, programs run by a web server; and apps
, programs run by a mobile device.
main语句是大多数Java程序的入口。例外有:applet,web浏览器在网页上运行的程序;servlet,web服务器运行的程序;app,移动设备运行的程序。
编译:源代码(.java) -> 类文件(.class)
第三章
Q. Why are Java applets no longer popular?
A. When the Java language was introduced in the mid-1990s, most people were learning the language to write applets. Java was the only way to create interactive programs that ran in a web browser. Over the years, alternatives emerged. Macromedia Flash, Microsoft Silverlight, and the new web publishing HTML5 standard all offer ways to put programs on web pages. Applets were hampered by poor loading times, slow support for new versions of Java by browser developers, and security holes exploited by hackers. Though applets are disappearing from the web, Java has outgrown its origins as a web browser enhancement and is now a sophisticated general-purpose programming language.
Q. 为何Java Applet不再流行?
A. 当Java语言在1990年代中期被引入时,大多数人学习这个语言是为了写applet。Java曾经是创建可以在web浏览器中运行的交互式程序的唯一方式。这么多年过去了,替代方案出现了。Macromedia Flash, Microsoft Silverlight,以及新的网页发布HTML5标准都提供了在网页中放置程序的办法。由于加载速度慢,浏览器开发者对Java新版本的支持慢,以及会被黑客利用的安全漏洞等缺陷都阻碍了applet的发展。虽然applet逐渐从web中消失,Java已经从初始用于web浏览器功能增强,发展为了如今的复杂的通用编程语言。
第四章
随机数
import java.util.Random;
Random generator = new Random();
int value = generator.nextInt();
JShell
bin文件夹中。
命令 /exit
退出
Read-Eval-Print Loop = REPL
第五章
常量
命名约定将值不变的变量名中所有字母大写
final int PAT = 1;
对象首字母大写,变量首字母小写。
递增和递减变量: ++, --
后缀postfix vs 前缀prefix
When a postfixed operator is used on a variable inside an expression, the variable's value doesn't change until after the expression has been completely evaluated.
当表达式中使用后缀运算符时,表达式的被计算完成之后,变量的值才会改变。
int x = 3;
int ans = x++ * 10;;
ans的值为30
int x = 3;
int ans = ++x * 10;;
ans的值为40
如何指定整数为二进制:在前面加 0b
int z = 0b0000_1101;
z为13
第六章
字符串处理
boolean A.equals(B)
int A.length()
String A.toUpperCase()
String A.toLowerCase()
int A.indexOf(B) //找不到返回-1
boolean A.contains(B) //找不到返回false
When you call a String object's toUpperCase() method, it doesn't actually change the String object it is called on. Instead, it creates a new string that is set in all uppercase letters.
Strings do not change in value in Java after they are created.
当调用字符串对象的toUpperCase()方法时,它不会更改被调用的字符串对象,而是创建了一个字母都大写的新的字符串。
在Java中,字符串被创建后值不会改变。
String a = "Apple";
String b = "Apple";
a.equals(b); //true
a == b; //true
String c = new String("Apple");
a.equals(c); //true
a == c; //false
第七章
三元运算符 ternary operator
测试的条件?条件为真时使用的值:条件为假时使用的值
第八章
命名循环:为外循环命名,同时跳出多个循环
int points = 0;
int target = 100;
targetLoop:
while (target <= 100) {
for (int i = 0; i < target; i++) {
if (points > 50) {
break targetLoop;
}
points = points + i;
}
}
第九章
类型后加方括号[],区分数组和变量;
也可以放在变量名后面
String[] naughtchild;
String niceChild[];
使用new关键字时,必须指定数组中存储了多少不同的项。
int[] selfSeniority = new int[250];
数组中每个元素都有一个初始值:
- 数值数组:初始值0
- 字符型数组:'\0'
- 布尔型数组:false
- 字符串型数组和所有其他对象:null
创建的同时设定初始值,用花括号{}
String[] reindeerNames = { "Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Donner", "Blitzen" };
使用数组
A.length //数组长度
//String转化为char数组
char[] myCharArr = myString.toCharArray()
//数组排序,升序
import java.util.*;
Arrays.sort(myArr);
第十章
Converting information to a new form is called casting
. Casting produces a new value that is a different type of variable or object than its source. You don't actually change the value when casting. Instead, a new variable or object is created in the format you need.
将信息转化为新的形式,称为类型转换。类型转换创建了与源不同类型的变量或者对象的一个新的值。类型转换时并没有改变值,而是按需创建了新的变量或者对象。
Java中有针对每种简单变量的类
- Boolean
- Byte
- Character
- Double
- Float
- Integer
- Long
- Short
Java's capability to use the basic data type and object forms of a value interchangeably is made possible through autoboxing and unboxing.
Autoboxing
casts a simple variable value to the corresponding class.
Unboxing
casts an object to the corresponding simple value.
通过自动装箱和拆箱,Java可以交换使用基本数据类型跟对象形式。
自动装箱:将简单变量转化为对应的类
拆箱:将对象转化为对应的简单值
Q. Can classes inherit from more than one class?
A. It's possible with classes in some programming languages (such as C++), but not Java. Multiple inheritance is a powerful feature, but it also makes OOP harder to learn and use. Java's developers decided to limit inheritance to one superclass for any class, although a class can have numerous subclasses. One way to compensate for this limitation is to inherit methods from a special type of class called an interface.
Q. 类可以继承多个类吗?
A. 在某些编程语言(比如C++)中是可以的,但是Java不行。多重继承是一个强大的特征,但同时也让OOP变得更加难学和难用。因此Java的开发者决定限制每个类只能继承一个超类,虽然一个类可以有无数个子类。弥补这种限制的一个方法是从一种特殊的类(称为接口)中继承方法。
第十一章
You can use a protected variable only in the same class as the variable, any subclasses of that class, or by classes in the same package. A package is a group of related classes that serve a common purpose.
protected变量只能在变量的同一个类中、任何该类的子类中、或同一个包中的类中被使用。一个包是指服务于一个共同目标的一组相关的类。
A private variable is restricted even further than a protected variable—you can use it only in the same class.
private变量的使用更加受限——只能在同一个类中使用。
There also is another type of access control: the lack of any public, private, or protected statement when the variable is created.
When no access control is set, the variable is available only to classes in the same package. This is called default or package access.
还有另一种访问控制的方法:在变量创建时无任何public, private, 或者protected语句。
如果没有访问控制设定,变量只能被同一个包中的类使用。这叫做默认访问或者包访问。
There are times when an attribute should describe an entire class of objects instead of a specific object itself. These are called class variables.
Class variables also are called static variables.
Although class variables are useful, you must take care not to overuse them. These variables exist for as long as the class is running. If a large array of objects is stored in class variables, it will take up a sizeable chunk of memory and never release it.
有时候需要属性描述整个类的对象,而不是某个特定的对象。这些属性叫做类变量。
类变量又叫做静态变量。
虽然类变量很有用,但必须小心不要过度使用。当类在运行时,这些变量就会存在。如果大量对象储存在类变量里,会占据很大的内存,并且从不释放。
static int gremlinCount = 0;
Gremlin.gremlinCount++;
accessor methods 访问器方法
encapsulation封装
Different methods in a class can have different names, but methods also can have the same name if they have different arguments.
Two methods can have the same name if they have a different number of arguments or the arguments are of different variable types.
The arguments to a method are called the method's signature. A class can have different methods with the same name as long as each method has a different signature.
类中的不同方法可以有不同的名称;如果他们的参数不同,名称可以相同。
两个方法可以同名,如果他们有不同数量的参数,或者参数的变量类型不同。
方法的参数称作方法的签名。只要类的方法的签名各自不同,他们的名字可以相同。
If you don't include any constructors in a class, it inherits a single constructor with no arguments from its superclass.
If your subclass defines a constructor with one or more arguments, the class will no longer inherit a constructor with no arguments from its superclass. For this reason, you must always define a no-argument constructor when your class has other constructors.
如果类中不包含任何构造函数,它会从超类中继承一个没有参数的构造函数。
如果子类定义了有一个或多个参数的构造函数,该类将不再会继承它的超类中无参数的构造函数。因此,当类中包含其他构造函数时,必须定义一个无参数的构造函数。
Like class variables, class methods are a way to provide functionality associated with an entire class instead of a specific object.
跟类变量一样,类方法提供跟整个类相关的功能,而非某个特定的对象。
static void showGremlinCount() {
System.out.println("There are " + gremlinCount + " gremlins");
}
If more than one class is defined in the same source file, only one of the classes can be public.
The other classes should not have public in their class statements. The name of the source code file must match the public class that it defines.
如果一个源文件中定义了多于一个类,只能有一个是public的。
其他类的类语句中不应该含有public。源文件的名称必须跟它定义的public类的名称相同。
辅助类 vs 内部类
第十二章
ArrayList
import java.util.ArrayList;
ArrayList myArrayList = new ArrayList();
ArrayList myArrayList = new ArrayList(100);
myArrayList.add("First");
myArrayList.add(1, "Second");
myArrayList.add(0, "Test"))
myArrayList.contains("First");
myArrayList.get(0);
myArrayList.remove(0);
myArrayList.remove("First");
//大小
int n = myArrayList.size();
//index
int i = myArrayList.indexOf("Second");
//遍历ArrayList
for (String name : myArrayList) {
System.out.println(name);
}
//排序
Collections.sort(myArrayList);
第十三章
HashMap 散列映射
Two things can be specified in a new hash map that control how efficient it is: the initial capacity and the load factor. 在散列映射中,两件事可以用来控制效率:初始容量和负载系数。
The capacity is the number of buckets in which hash map values can be stored. The load factor is the number of buckets that can be used before the capacity automatically is increased. The value is a floating-point number ranging from 0 (empty) to 1.0 (full), so a 0.7 means that when the buckets are 70 percent full, the capacity increases. The defaults are a capacity of 16 and load factor of .75, which often are sufficient.
容量是指存储散列映射值的桶数。负载系数是指容量自动增加前可以使用的桶数。该值是一个浮点数,范围从0(空)到1.0(满)。因此0.7表示当桶70%满时,增加容量。默认值时容量16以及负载系数0.75,通常都足够了。
HashMap phonebook = new HashMap(30, 0.7F);
HashMap phonebook = new HashMap<>();
phonebook.put("Butterball Turkey Line", 8002888372L);
long number = phonebook.get("Butterball Turkey Line"); //没有匹配到,则返回null
//会出现问题,null不是一个long值
//解决办法1
long number = phonebook.getOrDefault("Butterball Turkey Line", -1L);
//解决办法2
Long number = phonebook.get("Butterball Turkey Line");
phonebook.containsKey("Butterball Turkey Line");
phonebook.containsValue(8002888372L);
//大小
int n = phonebook.size();
//遍历
for(Map.Entry entry : phonebook.entrySet()) {
String key = entry.getKey();
Long value = entry.getValue();
System.out.println(key + "=" + value);
}
Array lists and hash maps are two of the more useful data structures in the java.util package. The array list class expands on the functionality of arrays, making it possible to overcome the fixed-size limitation of that data type. Hash maps enable any kind of object to be used as the key to retrieve a value.
There also are bit sets (the BitSet class), which hold the bit values of 0 and 1; stacks (Stack), which are a last-in, first-out collection of data similar to array lists; the sorted structures TreeMap and TreeSet; and properties (Properties), a specialized hash map that holds configuration properties for a program in a file or another permanent storage place.
数组列表和散列映射,是java.util包中2个更有用的数据结构。
数组列表类扩张了数组的功能,克服了这种数据类型固定大小的限制。散列映射使得任何对象都可以用作检索一个值的键。
还有位集(BitSet类),保存0和1的位值;栈(Stack类),是类似数组列表的后进先出的数据集合;排序的结构,TreeMap和TreeSet;以及属性(Properties类),一种特定的散列映射,将程序的配置属性保存在一个文件里,或其他永久存储空间内。
第十四章
Two terms are used to describe this process: throw
and catch
. Objects throw exceptions to alert other objects that they have occurred. These exceptions are caught by other objects or the Java Virtual Machine.
两个术语用来描述这个过程:抛出 和 捕获。
对象抛出异常,警告其他对象发生了异常。
这些异常被其他对象或者JVM捕获。
五个关键词:try, catch, finally, throw, and throws(忽略异常)
Whenever you see an error stating that an exception "must be caught or declared to be thrown," it indicates the method you are trying to use throws that exception. Any class that calls these methods must do one of the following things:
当看到一个错误说明异常是“必须捕获或者声明为抛出”时,它表示正在你尝试使用的方法抛出了这个异常。任何一个调用这些方法的类,必须做以下几件事之一:
- Handle the exception with a try-catch block 通过try-catch块处理异常
- Throw the exception 抛出异常
- Handle the exception with a try-catch block and then throw it 通过try-catch块处理异常,并抛出
float principal;
try {
principal = Float.parseFloat(loanText) * 1.1F;
} catch (Exception e) {
System.out.println("Error " + e.getMessage());
throw e;
}
final
关键字:
When you use throw in a catch block that catches a parent class, such as Exception, throwing the exception throws that class. This loses some detail of what kind of error occurred, because a subclass such as NumberFormatException tells you a lot more about the problem than simply the Exception class.
Java offers a way to keep this detail: the final
keyword in a catch
statement.
当你在catch块中捕获了父类(比如Exception)并抛出,会损失了具体发生哪类错误的细节,例如抛出NumberFormatException子类比单纯的Exception类更能提示问题所在。
Java提供了保留这种细节的方法:在catch语句中使用final关键字。
try {
principal = Float.parseFloat(loanText) * 1.1F;
} catch (final Exception e) {
System.out.println("Error " + e.getMessage());
throw e;
}
That final
keyword in catch
causes throw to behave differently. The specific class that was caught is thrown.
catch语句中的final关键字导致抛出的表现不同,会抛出捕获的明确的类。
You can create your own exceptions easily by making them a subclass of an existing exception, such as Exception, the superclass of all exceptions. In a subclass of Exception, there are only two constructors you might want to override: Exception() with no arguments and Exception() with a String as an argument. In the latter, the string should be a message describing the error that has occurred.
作为现有异常(比如Exception,所有异常的超类)的子类,可以创建自己的异常。在Exception的子类中,只需要重写(override)两个构造函数:没有参数的Exception(),以及以一个String为参数的Exception。后者中,String是一个用来描述所发生错误的消息。
第十五章
线程(threads)对象
Threads are represented by the Thread class and the Runnable interface, which are both part of the java.lang package of classes.
Thread类
Runnable接口
Two ways to place a task in its own thread include 两种将任务放入线程的方法
- Putting the task in a class that implements the Runnable interface 将任务放入实现Runnable接口的类中 implements Runnable
- Putting the task in a class that is a subclass of Thread 将任务放入Thread类的子类中 extends Thread
public class LoadStocks implements Runnable {
// body of the class
}
实现Runnable接口的方法必须包含run()方法
public void run() {
// body of the method
}
When a threaded application is run, the statements in its run() method are not executed automatically. Threads can be started and stopped in Java, and a thread doesn't begin running until you do two things
线程应用运行时,run()方法内的语句不会自动执行。在Java中可以启动和停止线程。只有做了以下两件事后,线程才开始运行:
- Create an object of the threaded class by calling the Thread constructor 调用Thread构造函数,来创建线程类的对象
- Start the thread by calling its start() method 通过调用start()方法来启动线程。
第十六章
There are three reasons that Java includes inner classes: Java包含内部类的三个原因
- When a helper class is only used by one other class, it makes sense to define it within that class. 如果一个辅助类只被一个类所用,那在该类中定义它是合理的。
- They enable a helper class to access private methods and variables it could not access as a separate class. 使得辅助类可以访问private方法和变量;如果作为独立的类则不行。
- They put a helper class as close as possible to where it is being used in another class. 将内部类尽可能近地放置在它在另一个类中被使用的地方。
public class Outer {
class Inner {
Inner() {
System.out.println("I am an inner class!");
}
}
public Outer() {
// empty constructor
}
public static void main(String[] arguments) {
Outer out = new Outer(); // 实例化外部类
Outer.Inner in = out.new Inner(); //实例化内部类
//Inner in = new Outer().new Inner();
}
}
类名称 = 外部类名称.内部类名称
anonymous inner class 匿名内部类
An anonymous inner class is one that has no name and is declared and created at the same time.
匿名内部类,没有名字,同时声明和创建。
不使用匿名内部类
WorkerClass worker = new WorkerClass();
Thread main = new Thread(worker);
main.start();
worker对象应该实现了Runnable接口,并且可以作为线程运行。
如果WorkerClass内的代码很简略,且类只使用一次,就值得放在匿名内部类里。
Thread main = new Thread(new Runnable() {
public void run() {
// thread's work to perform goes here
}
});
main.start();
closure [闭包] / lambda expression [lambda表达式]
Runnable runner = () -> { System.out.println("Run!"); };
ActionListener al = (ActionEvent act) -> {
System.out.println(act.getSource());
}
In a lambda expression, the statement to the right of the arrow operator -> becomes the method that implements the interface.
lambda表达式,->右边的语句成为实现接口的方法。
This can be done only when the interface has a single method to implement, such as Runnable, which just contains run(). An interface in Java that has one method is now called a functional interface.
当且仅当接口中仅有一个方法要实现时,才可以这么做。比如Runnable,仅包含run()。
只有一个方法的接口在Java中称为函数式接口。
Target typing[目标类型]
In a lambda expression, it's possible to infer the class of the argument or arguments sent to the method.
Consider the last example. Because the ActionListener functional interface has a method that takes an ActionEvent object as its only argument, the name of that class can be omitted.
lambda表达式可以推断发送给方法的参数的类,类名可以省略。
ActionListener al = (act) -> {
System.out.println(act.getSource());
}