學(xué)習(xí)Java語(yǔ)言
面向?qū)ο缶幊谈拍?/h3>
核心概念:對(duì)象,消息,類(lèi)和繼承
這一節(jié)會(huì)介紹 對(duì)象,類(lèi)闲礼,繼承,接口和包
What Is an Object?
An object is a software bundle of related state and behavior.
對(duì)象是相關(guān)屬性和行為的軟件集合铐维。
將不同的實(shí)物對(duì)象成不同的對(duì)象位仁,有以下好處
- 模塊化
- 信息隱藏
- 代碼復(fù)用
- 擴(kuò)展性和易調(diào)試
What Is a Class?
A class is a blueprint or prototype from which objects are created.
類(lèi)是創(chuàng)建的對(duì)象的藍(lán)圖或原型。
What Is Inheritance?
Inheritance provides a powerful and natural mechanism for organizing and structuring your software.
繼承提供了一種強(qiáng)大且自然的機(jī)制來(lái)組織/構(gòu)建程序方椎。
面向?qū)ο缶幊淘试S從其他類(lèi)繼承公共有用的屬性和行為聂抢。
使用 extends
關(guān)鍵字
class MountainBike extends Bicycle {
// new fields and methods defining
// a mountain bike would go here
}
What Is an Interface?
An interface is a contract between a class and the outside world.
接口是類(lèi)和外部世界的約定。當(dāng)一個(gè)類(lèi)實(shí)現(xiàn)接口棠众,他承諾提供接口發(fā)布的行為琳疏。
定義接口:
interface Bicycle {
// wheel revolutions per minute
void changeCadence(int newValue);
void changeGear(int newValue);
void speedUp(int increment);
void applyBrakes(int decrement);
}
實(shí)現(xiàn)接口,使用關(guān)鍵字implements
class ACMEBicycle implements Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
// The compiler will now require that methods
// changeCadence, changeGear, speedUp, and applyBrakes
// all be implemented. Compilation will fail if those
// methods are missing from this class.
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:" +
cadence + " speed:" +
speed + " gear:" + gear);
}
}
What Is a Package?
A package is a namespace for organizing classes and interfaces in a logical manner.
包是以合理的方式來(lái)組織類(lèi)和接口的一個(gè)命名空間闸拿。
把程序放到包里可以使得大項(xiàng)目易于管理空盼。
語(yǔ)言基礎(chǔ)
Java語(yǔ)言的基礎(chǔ)特征:變量,數(shù)組新荤,數(shù)據(jù)類(lèi)型揽趾,操作符和控制流
Variables
Java 對(duì)象把屬性保存在域中:
int cadence = 0;
int speed = 0;
int gear = 1;
"field" and "variable" 這兩個(gè)概念是一樣的。
Java 語(yǔ)言中有下列幾種變量:
- 實(shí)例變量(Non-Staic Fields)
- 類(lèi)變量(Static Fields)
- 本地變量: 臨時(shí)變量
- 參數(shù)變量
命名規(guī)則:
- 變量名是大小寫(xiě)敏感的case-sensitive苛骨,字母篱瞎,數(shù)字苟呐,美元符號(hào)""和下劃線"_",長(zhǎng)度沒(méi)有限制,開(kāi)頭不能是數(shù)字。正常開(kāi)頭都是字母俐筋,而不用''和'_'. 并且正常都不使用牵素,只有自動(dòng)生成的名字中有。
- 使用全詞來(lái)命名澄者,而不是選擇縮寫(xiě)笆呆。
- 不能使用關(guān)鍵字來(lái)命名
- 駝峰命名法
- 常量命名為大寫(xiě),
static final int NUM_GEARS = 6;
為了方便粱挡,其他地方一般不使用下劃線來(lái)命名赠幕。
Operators
Operators | Precedence |
---|---|
postfix | expr++ expr-- |
unary | ++expr --expr +expr -expr ~ ! |
multiplicative | * / % |
additive | + - |
shift | << >> >>> |
relational | < > <= >= instanceof |
equality | == != |
bitwise AND | & |
bitwise exclusive OR | ^ |
bitwise inclusive OR | | |
logical AND | && |
logical OR | || |
ternary | ? : |
assignment | = += -= *= /= %= &= ^= |= <<= >>= >>>= |
Expressions, Statements, and Blocks
- 表達(dá)式
表達(dá)式是由變量,操作符和方法調(diào)用評(píng)估得到一個(gè)值询筏。
表達(dá)式返回值的數(shù)據(jù)類(lèi)型取決于表達(dá)式中的元素:
int cadence = 0榕堰;
表達(dá)式 cadence = 0
返回的類(lèi)型就是int.
表達(dá)式支持混合運(yùn)算:
1 * 2 * 3 / 4
為了避免產(chǎn)生歧義和錯(cuò)誤,建議用小括號(hào)
x + y / 100 //有歧義
(x + y) / 100
x + (y / 100)
- 語(yǔ)句
Java 語(yǔ)句大致跟自然語(yǔ)言的句子相同屈留。
語(yǔ)句形成表達(dá)式完整的單元。
下列幾種表達(dá)式可以組成語(yǔ)句测蘑,并且用分號(hào)';'結(jié)束:- 賦值表達(dá)式
- 自增/自減操作
- 方法調(diào)用
- 對(duì)象創(chuàng)建表達(dá)式
// assignment statement
aValue = 8933.234;
// increment statement
aValue++;
// method invocation statement
System.out.println("Hello World!");
// object creation statement
Bicycle myBike = new Bicycle();
還有另外兩種語(yǔ)句
5. 聲明語(yǔ)句
6. 控制流
//declaration statement
double aValue = 8933.234;
//the decision-making statements
if-then, if-then-else, switch,
//the looping statements
for, while, do-while
//the branching statements
break, continue, return
- 塊
塊是0條或多條語(yǔ)句的組合灌危,用大括號(hào)圈起來(lái)。
class BlockDemo {
public static void main(String[] args) {
boolean condition = true;
if (condition) { // begin block 1
System.out.println("Condition is true.");
} // end block one
else { // begin block 2
System.out.println("Condition is false.");
} // end block 2
}
}
Control Flow Statements
- 選擇語(yǔ)句
if-then, if-then-else, switch
- 循環(huán)語(yǔ)句
for, while, do-while
- 分支語(yǔ)句
break, continue, return
類(lèi)和對(duì)象
創(chuàng)建對(duì)象碳胳,使用對(duì)象
類(lèi)
剖析類(lèi)勇蝙,以及怎樣聲明屬性,方法和構(gòu)成器
public class Bicycle {
// the Bicycle class has
// three fields
public int cadence;
public int gear;
public int speed;
// the Bicycle class has
// one constructor
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
// the Bicycle class has
// four methods
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
幾種變量:
- Member variables in a class—these are called fields.
- Variables in a method or block of code—these are called local variables.
- Variables in method declarations—these are called parameters.
變量聲明:
- 0個(gè)或多個(gè)修飾符挨约,例如public或private
- 類(lèi)型
- 變量名
public int cadence;
權(quán)限修飾符:
public > protect > default > private
定義方法:
Here is an example of a typical method declaration:
public double calculateAnswer(double wingSpan, int numberOfEngines,
double length, double grossTons) {
//do the calculation here
}
返回類(lèi)型 方法名 括號(hào)( 參數(shù) ) { 方法體 }
方法命名:駝峰命名法
run
runFast
getBackground
getFinalData
compareTo
setX
isEmpty
重載方法:
通過(guò)不同的參數(shù)(類(lèi)型味混,個(gè)數(shù))來(lái)區(qū)別:
public class DataArtist {
...
public void draw(String s) {
...
}
public void draw(int i) {
...
}
public void draw(double f) {
...
}
public void draw(int i, double f) {
...
}
}
構(gòu)造器:
A class contains constructors that are invoked to create objects from the class blueprint.
類(lèi)調(diào)用構(gòu)造器來(lái)創(chuàng)建對(duì)象。
構(gòu)造器的聲明和方法聲明類(lèi)似诫惭,有兩點(diǎn)不同:
- 使用類(lèi)名作方法名
- 沒(méi)有返回類(lèi)型
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
調(diào)用構(gòu)造器來(lái)創(chuàng)建對(duì)象翁锡,用new
操作符
Bicycle myBike = new Bicycle(30, 0, 8);
一個(gè)類(lèi)可以有多個(gè)構(gòu)造器,他們之間的參數(shù)不同夕土。
代碼沒(méi)有顯示聲明構(gòu)造器的話馆衔,會(huì)有一個(gè)默認(rèn)的無(wú)參構(gòu)造器。
傳遞參數(shù):
可以向方法或構(gòu)造器傳遞參數(shù)怨绣。
參數(shù)的數(shù)量沒(méi)有限制
Java中的參數(shù)傳遞都是值傳遞角溃,基本類(lèi)型和引用類(lèi)型有點(diǎn)區(qū)別:
public class PassPrimitiveByValue {
public static void main(String[] args) {
int x = 3;
// invoke passMethod() with
// x as argument
passMethod(x);
// print x to see if its
// value has changed
System.out.println("After invoking passMethod, x = " + x); //這里x沒(méi)有被修改
}
// change parameter in passMethod()
public static void passMethod(int p) {
p = 10;
}
}
執(zhí)行結(jié)果是:
After invoking passMethod, x = 3
基本變量傳遞參數(shù)時(shí),方法內(nèi)對(duì)參數(shù)的修改只在本地生效篮撑,不會(huì)影響外層的值减细。
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/02
*/
public class Circle {
int x;
int y;
public Circle(int xx, int yy) {
x = xx;
y = yy;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "Circle [x=" + x + ", y=" + y + "]";
}
public void moveCircle(Circle circle, int deltaX, int deltaY) {
// code to move origin of circle to x+deltaX, y+deltaY
// circle指向的對(duì)象唄修改,外層的對(duì)象也跟著被修改赢笨,變成(27未蝌,62)
circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
System.out.println(circle);
// code to assign a new reference to circle
// 這里重新將circle變量指向新的對(duì)象(0驮吱,0),外層的circle依然是指向原來(lái)的對(duì)象(27树埠,62)
// 外層的circle指向的對(duì)象不會(huì)被修改糠馆,不會(huì)指向其他對(duì)象,但是對(duì)象的屬性值可以被修改怎憋。
circle = new Circle(0, 0);
System.out.println(circle);
}
public static void main(String[] args) {
Circle myCircle = new Circle(4, 6);
System.out.println(myCircle);
moveCircle(myCircle, 23, 56);
System.out.println(myCircle); //這里myCircle對(duì)象以及被修改了
}
}/**Output
Circle [x=4, y=6]
Circle [x=27, y=62]
Circle [x=0, y=0]
Circle [x=27, y=62]
*///~
這里的值傳遞又碌,指的是引用的值,外層的circle指向的對(duì)象不會(huì)被修改绊袋,不會(huì)指向其他對(duì)象毕匀,但是對(duì)象的屬性值可以被修改。
對(duì)象
As you know, a class provides the blueprint for objects; you create an object from a class.
Point originOne = new Point(23, 94);
Rectangle rectOne = new Rectangle(originOne, 100, 200);
Rectangle rectTwo = new Rectangle(50, 100);
創(chuàng)建對(duì)象的語(yǔ)句有三個(gè)部分:
- 聲明:類(lèi)型+對(duì)象名
Point originOne
- 實(shí)例化:
new
關(guān)鍵字是用來(lái)創(chuàng)建對(duì)象的Java操作符 - 初始化:new調(diào)用構(gòu)造器來(lái)初始化對(duì)象
Point(23, 94)
使用對(duì)象:
objectReference.fieldName
objectReference.methodName(argumentList)
objectReference.methodName();
垃圾收集器:
The Java runtime environment deletes objects when it determines that they are no longer being used. This process is called garbage collection.
當(dāng)對(duì)象不再被使用時(shí)癌别,Java 運(yùn)行環(huán)境會(huì)刪除它皂岔。這個(gè)過(guò)程叫做垃圾回收。
An object is eligible for garbage collection when there are no more references to that object.References that are held in a variable are usually dropped when the variable goes out of scope. Or, you can explicitly drop an object reference by setting the variable to the special value null.
當(dāng)沒(méi)有應(yīng)用指向?qū)ο蟮臅r(shí)候展姐,它就是滿(mǎn)足垃圾回收要求的躁垛。當(dāng)變量離開(kāi)作用域時(shí),它的引用就會(huì)被刪除圾笨〗坦荩或者可以通過(guò)將變量賦值為null來(lái)刪除引用。
更多關(guān)于類(lèi)
這一節(jié)是關(guān)于類(lèi)依賴(lài)于使用對(duì)象引用和.
操作符:
返回值
方法返回的三種情況:
1. 所有語(yǔ)句正常執(zhí)行結(jié)束
2. return 語(yǔ)句
3. 拋出異常this 關(guān)鍵字
this關(guān)鍵字指向當(dāng)前對(duì)象
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(0, 0, 1, 1);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
...
}
- 訪問(wèn)控制
public > protect > default > private
Modifier | Class | Package | Subclass | World |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
no modifier | Y | Y | N | N |
private | Y | N | N | N |
- static 類(lèi)變量和類(lèi)方法
- 類(lèi)變量
When a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables.
當(dāng)創(chuàng)建類(lèi)的多個(gè)對(duì)象時(shí)擂达,每個(gè)對(duì)象實(shí)例都有各自的實(shí)例變量土铺。如果在變量前面加上static
關(guān)鍵字,這個(gè)變量就是類(lèi)變量板鬓,是跟類(lèi)關(guān)聯(lián)在一起悲敷,而不是對(duì)象實(shí)例。
public class Bicycle {
private int cadence;
private int gear;
private int speed;
// add an instance variable for the object ID
private int id;
// add a class variable for the
// number of Bicycle objects instantiated
private static int numberOfBicycles = 0;
...
}
上面的numberOfBicycles
就是類(lèi)變量 class variables or static fields.
2. 類(lèi)方法
Static methods, which have the static modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class, as in
ClassName.methodName(args)
類(lèi)方法可以直接用類(lèi)名來(lái)調(diào)用俭令,不需要先創(chuàng)建對(duì)象實(shí)例后德。也可以跟普通方法調(diào)用一樣,使用 instanceName.methodName(args)
. 不過(guò)不推薦抄腔,因?yàn)檫@樣就不能將類(lèi)方法和普通方法區(qū)分開(kāi)了探遵。
類(lèi)方法的常見(jiàn)用法就是用來(lái)訪問(wèn)類(lèi)變量(靜態(tài)域).
訪問(wèn)注意:
- 實(shí)例方法可以直接訪問(wèn)實(shí)例變量和實(shí)例方法;
- 實(shí)例方法可以直接訪問(wèn)類(lèi)變量和類(lèi)方法妓柜;
- 類(lèi)方法可以直接訪問(wèn)類(lèi)變量和類(lèi)方法箱季;
- 類(lèi)方法不可以訪問(wèn)實(shí)例變量和實(shí)例方法-它們必須用一個(gè)對(duì)象引用才能訪問(wèn);
- 類(lèi)方法不能用this關(guān)鍵字棍掐,因?yàn)樗恢赶蛉魏螌?shí)例對(duì)象藏雏。
- 常量
static
和final
關(guān)鍵字的組合可以用來(lái)定義常量。
final 標(biāo)識(shí)符表明這個(gè)域的值不能被修改。
static final double PI = 3.141592653589793;
如果想要改變PI的值掘殴,編譯報(bào)錯(cuò)赚瘦。
Note: If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.
如果一個(gè)基本類(lèi)型或字符串類(lèi)型被定義為常量,且編譯階段就知道常量的值奏寨,編譯器就會(huì)在用到這個(gè)常量的所有地方把它替換為具體的值起意。這個(gè)叫做編譯時(shí)常量。所以如果上面PI的值變成了3.975病瞳,那么就要重新編譯來(lái)獲取最新的值揽咕。
- 初始化域
public class BedAndBreakfast {
// initialize to 10
public static int capacity = 10;
// initialize to false
private boolean full = false;
}
Note: It is not necessary to declare fields at the beginning of the class definition, although this is the most common practice. It is only necessary that they be declared and initialized before they are used.
沒(méi)有要求一定要在類(lèi)定義的開(kāi)頭聲明域,盡管這是最常見(jiàn)的用法套菜。只需要滿(mǎn)足在使用域之前被初始化就可以亲善。
Static Initialization Blocks 靜態(tài)初始化塊
static {
// whatever code is needed for initialization goes here
}
- 總結(jié):創(chuàng)建,使用類(lèi)和對(duì)象
A class declaration names the class and encloses the class body between braces.
類(lèi)定義:命名類(lèi),并且用括號(hào)來(lái)圈起來(lái)類(lèi)主體逗柴。
類(lèi)主體包含域蛹头,方法和構(gòu)造器。
- 域: 屬性xinxi
- 方法:實(shí)現(xiàn)行為
- 構(gòu)造器:初始化對(duì)象
類(lèi)變量和類(lèi)方法: static 關(guān)鍵字
實(shí)例變量和實(shí)例方法: 沒(méi)有用static關(guān)鍵字
嵌套類(lèi)
Java允許在一個(gè)類(lèi)里面再定義一個(gè)類(lèi)戏溺,這個(gè)類(lèi)就叫做嵌套類(lèi)渣蜗。
class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
嵌套類(lèi)是外部類(lèi)的一個(gè)成員。
嵌套類(lèi)分為兩個(gè)兩類(lèi):
- static 嵌套類(lèi)不可以訪問(wèn)外部類(lèi)的其他成員旷祸。
- non-static 嵌套類(lèi)(inner classes) 可以訪問(wèn)外部類(lèi)的其他成員
為什么使用嵌套類(lèi):
- It is a way of logically grouping classes that are only used in one place:如果一個(gè)類(lèi)僅僅被其他一個(gè)類(lèi)訪問(wèn)耕拷,那么可以將他們合理地嵌套在一起。
- It increases encapsulation: 提高封裝特性肋僧“呤ぃ可以將內(nèi)部類(lèi)隱藏在外部類(lèi)下
- It can lead to more readable and maintainable code:提高代碼的易讀性和可維護(hù)性控淡。
靜態(tài)內(nèi)部類(lèi):
Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
靜態(tài)內(nèi)部類(lèi)和它的外部類(lèi)(或其他類(lèi))的實(shí)例成員的交互就像任何其他的頂層的類(lèi)一樣嫌吠。
//可以使用外部類(lèi)的名字來(lái)訪問(wèn)靜態(tài)內(nèi)部類(lèi)
OuterClass.StaticNestedClass
//例如,可以使用下面的語(yǔ)法來(lái)創(chuàng)建靜態(tài)內(nèi)部類(lèi)的對(duì)象
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
普通內(nèi)部類(lèi)
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.
類(lèi)似實(shí)例方法和實(shí)例變量掺炭,內(nèi)部類(lèi)和外部類(lèi)的一個(gè)實(shí)例對(duì)象相關(guān)聯(lián)辫诅,可以直接訪問(wèn)這個(gè)實(shí)例對(duì)象的方法和域。而且涧狮,內(nèi)部類(lèi)是和實(shí)例對(duì)象相關(guān)聯(lián)炕矮,所以里面不能定義任何靜態(tài)成員。
一個(gè)內(nèi)部類(lèi)的實(shí)例只能存在域外部類(lèi)的實(shí)例內(nèi)者冤。
要實(shí)例化內(nèi)部類(lèi)肤视,必須先實(shí)例化外部類(lèi),然后用下面的語(yǔ)法來(lái)創(chuàng)建內(nèi)部類(lèi):
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
普通內(nèi)部類(lèi) Inner classes 分為兩種:
- Local 本地內(nèi)部類(lèi)
- Anonymous 匿名內(nèi)部類(lèi)
內(nèi)部類(lèi)同樣可以使用private清寇,public和protected.
Shadowing 隱藏
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/02
*/
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}/**Output:
x = 23
this.x = 1
ShadowTest.this.x = 0
*///~
序列化:
內(nèi)部類(lèi)的序列化是強(qiáng)烈勸阻的朵逝,包括本地內(nèi)部類(lèi)和匿名內(nèi)部類(lèi)盈魁。
Lambda表達(dá)式: 用來(lái)優(yōu)美地實(shí)例化只有一個(gè)方法的類(lèi)钦幔。
Lambda 表達(dá)式看上去更像是一個(gè)方法的聲明困后,可以把Lambda表達(dá)式當(dāng)成匿名方法乐纸,一個(gè)沒(méi)有名字的方法。
Lambda表達(dá)式語(yǔ)法:
- 包含在花括號(hào)內(nèi)逗號(hào)分隔的正常參數(shù)摇予。
- 箭頭符號(hào) ->
- 主體汽绢,包含簡(jiǎn)單的表達(dá)式或者語(yǔ)句塊
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/03
*/
public class Calculator {
interface IntegerMath {
int operation(int a, int b);
}
public int operateBinary(int a, int b, IntegerMath op) {
return op.operation(a, b);
}
public static void main(String... args) {
Calculator myApp = new Calculator();
IntegerMath addition = (a, b) -> a + b;
IntegerMath subtraction = (a, b) -> a - b;
System.out.println("40 + 2 = " +
myApp.operateBinary(40, 2, addition));
System.out.println("20 - 10 = " +
myApp.operateBinary(20, 10, subtraction));
}
}/**Output:
40 + 2 = 42
20 - 10 = 10
*///~
方法operateBinary 對(duì)兩個(gè)整型操作數(shù)進(jìn)行算術(shù)運(yùn)算。運(yùn)算方式是用接口IntegerMath聲明的侧戴。這個(gè)例子用Lambda表達(dá)式定義了兩種操作宁昭,addition 和 subtraction。
如果一個(gè)Lambda表達(dá)式的目標(biāo)類(lèi)型和攜帶參數(shù)都是可序列化的救鲤,你可以序列化這個(gè)Lambda表達(dá)式久窟。然而,就像匿名類(lèi)本缠,強(qiáng)烈建議別瞎搗騰去序列化Lambda表達(dá)式斥扛。
枚舉類(lèi)型
枚舉類(lèi)型:是一個(gè)允許定義和使用常數(shù)集合的特殊類(lèi)。
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
枚舉類(lèi)型有個(gè)方法 values() 可以返回包含所有值的數(shù)組丹锹,并且按照聲明的順序稀颁。
for(Day d : Day.values()) {
//...
}
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/03
*/
public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6),
JUPITER (1.9e+27, 7.1492e7),
SATURN (5.688e+26, 6.0268e7),
URANUS (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7);
private final double mass; // in kilograms
private final double radius; // in meters
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
private double mass() { return mass; }
private double radius() { return radius; }
// universal gravitational constant (m3 kg-1 s-2)
public static final double G = 6.67300E-11;
double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java Planet <earth_weight>");
System.exit(-1);
}
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight/EARTH.surfaceGravity();
for (Planet p : Planet.values())
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
}/** Output:傳入的參數(shù)是111時(shí)
Your weight on MERCURY is 41.931095
Your weight on VENUS is 100.454900
Your weight on EARTH is 111.000000
Your weight on MARS is 42.039827
Your weight on JUPITER is 280.891885
Your weight on SATURN is 118.327725
Your weight on URANUS is 100.469119
Your weight on NEPTUNE is 126.354416
*/// ~
注解
參考譯文
注解是一種元數(shù)據(jù)的形式,為編譯器提供信息楣黍。
注解不是程序本身匾灶,僅提供程序相關(guān)的信息,注解對(duì)它們所注釋的代碼沒(méi)有直接的影響租漂。
這里介紹在哪里以及怎樣高效的在程序中使用注解阶女。
注解的用途:
- Information for the compiler:為編譯器提供信息來(lái)檢測(cè)錯(cuò)誤或者抑制警告。
- Compile-time and deployment-time processing: 編譯時(shí)和發(fā)布時(shí)處理哩治,軟件工具可以處理注解信息來(lái)生成代碼秃踩,XML文件等等。
- Runtime processing业筏,運(yùn)行時(shí)處理憔杨,一些注解可以在運(yùn)行時(shí)進(jìn)行檢查。
注解基礎(chǔ)
注解的格式:
符號(hào)@
告訴編譯器這接下來(lái)的是一個(gè)注解蒜胖。
@Entity
@Override
void mySuperMethod() { ... }
@Author(
name = "Benjamin Franklin",
date = "3/27/2003"
)
class MyClass() { ... }
or
@SuppressWarnings(value = "unchecked")
void myMethod() { ... }
//如果只有一個(gè)元素叫做value消别,那這個(gè)名字可以被省略
@SuppressWarnings("unchecked")
void myMethod() { ... }
@Author(name = "Jane Doe")
@Author(name = "John Smith")
class MyClass { ... }
可以使用注解的地方:
注解可以用在聲明:聲明類(lèi),域台谢,方法和其他程序元素寻狂。當(dāng)注解用在聲明時(shí),一般是單獨(dú)一行朋沮。
Java SE8 發(fā)布后蛇券,注解可以用在類(lèi)型:
//Class instance creation expression: 創(chuàng)建類(lèi)的實(shí)例
new @Interned MyObject();
//Type cast:類(lèi)型強(qiáng)制轉(zhuǎn)換
myString = (@NonNull String) str;
//implements clause:實(shí)現(xiàn)子句
class UnmodifiableList<T> implements
@Readonly List<@Readonly T> { ... }
//Thrown exception declaration:拋異常聲明
void monitorTemperature() throws
@Critical TemperatureException { ... }
聲明一個(gè)注解類(lèi)型
許多注解用來(lái)替換代碼中的注釋。
一般類(lèi)中的注釋信息:
public class Generation3List extends Generation2List {
// Author: John Doe
// Date: 3/17/2002
// Current revision: 6
// Last modified: 4/12/2004
// By: Jane Doe
// Reviewers: Alice, Bill, Cindy
// class code goes here
}
要用注解來(lái)加上同樣的元數(shù)據(jù),我們首先需要定義一個(gè)注解類(lèi)型:
@interface ClassPreamble {
String author();
String date();
int currentRevision() default 1;
String lastModified() default "N/A";
String lastModifiedBy() default "N/A";
// Note use of array
String[] reviewers();
}
定義注解的方式有點(diǎn)類(lèi)似定義接口怀读,使用了關(guān)鍵字interface
和前綴@
符號(hào)诉位,注解是屬于接口的一種。
定義好注解后菜枷,就可以使用注解了:
@ClassPreamble (
author = "John Doe",
date = "3/17/2002",
currentRevision = 6,
lastModified = "4/12/2004",
lastModifiedBy = "Jane Doe",
// Note array notation
reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {
// class code goes here
}
Note: To make the information in
@ClassPreamble
appear in Javadoc-generated documentation, you must annotate the@ClassPreamble
definition with the@Documented
annotation:
為了@ClassPreamble
的信息可以出現(xiàn)在javadoc文檔生成中苍糠,需要在定義中加上@Documented
注解
// import this to use @Documented
import java.lang.annotation.*;
@Documented
@interface ClassPreamble {
// Annotation element definitions
}
預(yù)定義注解類(lèi)型
一系列的注解類(lèi)型在Java SE API中預(yù)定義了。一些注解類(lèi)型被用在Java編譯器啤誊,一些被用在其他注解上岳瞭。
Java語(yǔ)言中用到的注解
java.lang
中預(yù)定義的注解類(lèi)型是:
- @Deprecated:棄用
表示已經(jīng)被棄用,當(dāng)程序使用了@Deprecated注解標(biāo)注的方法/類(lèi)/域時(shí)蚊锹,編譯器會(huì)發(fā)出警告瞳筏。
@Override: 覆蓋
告訴編譯器這個(gè)元素是覆蓋父類(lèi)的一個(gè)元素聲明@SuppressWarnings:抑制警告
告訴編譯器抑制原本會(huì)產(chǎn)生的特定的警告。
// use a deprecated method and tell
// compiler not to generate a warning
@SuppressWarnings("deprecation")
void useDeprecatedMethod() {
// deprecation warning
// - suppressed
objectOne.deprecatedMethod();
}
上面例子中牡昆,調(diào)用了一個(gè)被棄用的方法姚炕,正常編譯器會(huì)提示警告,但是加了@SuppressWarning
后丢烘,這個(gè)警告就被抑制了柱宦。
抑制多種警告信息:
@SuppressWarnings({"unchecked", "deprecation"})
@SafeVarargs 安全參數(shù)
運(yùn)用在方法或構(gòu)造器上,表明代碼不會(huì)對(duì)參數(shù)進(jìn)行潛在的不安全的操作播瞳。@FunctionalInterface 函數(shù)式接口
表示聲明的類(lèi)型是Java SE 8中的函數(shù)式接口
被其他注解應(yīng)用的注解
被其他注解應(yīng)用的注解成為元注解掸刊。
這里有一些元注解定義在java.lang.annotation
-
@Retention 保留注解
表明標(biāo)記的注解是怎么保存的:- RetentionPolicy.SOURCE 只保留在源碼中,編譯器會(huì)忽略它
- RetentionPolicy.CLASS 編譯時(shí)被編譯器保留赢乓,但是被JVM忽略
- RetentionPolicy.RUNTIME 被JVM保留所以能在運(yùn)行時(shí)環(huán)境使用
@Documented Java 文檔
表明被標(biāo)記的注解要被javadoc工具記錄忧侧。 Javadoc tools page.
-
@Target 目標(biāo)
限制被標(biāo)記的注解能被哪種Java 元素應(yīng)用。- ElementType.ANNOTATION_TYPE can be applied to an annotation type.
- ElementType.CONSTRUCTOR can be applied to a constructor.
- ElementType.FIELD can be applied to a field or property.
- ElementType.LOCAL_VARIABLE can be applied to a local variable.
- ElementType.METHOD can be applied to a method-level annotation.
- ElementType.PACKAGE can be applied to a package declaration.
- ElementType.PARAMETER can be applied to the parameters of a method.
- ElementType.TYPE can be applied to any element of a class.
@Inherited 繼承
表示被標(biāo)記的注解類(lèi)型可以從父類(lèi)中繼承牌芋。這個(gè)注解只用在類(lèi)的聲明蚓炬。@Repeatable 可重復(fù)的
Java SE8 中@Repeatable
注解表明被標(biāo)記的注解可以被應(yīng)用多次在同一個(gè)聲明或類(lèi)型使用上。
Type注解和插件
在Java 8之前姜贡,注解僅僅只能在聲明(declarations)時(shí)使用试吁。在Java 8棺棵,注解可以在任何 type use楼咳。這就是說(shuō),注解可以應(yīng)用在任何你使用type的地方烛恤。例如母怜,class實(shí)例的創(chuàng)建表達(dá)式(new),類(lèi)型轉(zhuǎn)換(casts)缚柏,implements子句苹熏,throws子句。這種注解被稱(chēng)為type annotation。更多例子轨域,可以參考上面的基礎(chǔ)知識(shí)(Annotations Basics)袱耽。
Type annotation是為了提高Java程序的強(qiáng)類(lèi)型檢查功能而誕生的。Java 8并沒(méi)有提供一個(gè)類(lèi)型檢查框架(type checking framework)干发,但卻允許你自己寫(xiě)(或者down)一個(gè)類(lèi)型檢查框架作為Java編譯器的插件使用朱巨。
舉個(gè)例子,你想確保你程序里的某些變量永遠(yuǎn)不會(huì)被賦值為null枉长;你想避免產(chǎn)生NullPointerException冀续。你可以自己寫(xiě)個(gè)插件來(lái)檢查。你只需要修改你的代碼必峰,把特定變量加上標(biāo)識(shí)不能用null賦值的注解洪唐。這個(gè)變量的聲明可能看起來(lái)像這樣:
@NonNull String str;
重復(fù)注解
Java SE 8 開(kāi)始,可以使用重復(fù)注解
@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }
接口和繼承
接口是什么吼蚁,為什么使用接口凭需,怎樣使用接口
從基類(lèi)繼承,生成一個(gè)導(dǎo)出類(lèi)肝匆。子類(lèi)和父類(lèi)的關(guān)系
所有的類(lèi)都是繼承自Obeject
類(lèi)
Numbers和Strings
Number 和 String 類(lèi)的使用功炮,以及格式化輸出
泛型
泛型是Java語(yǔ)言中一個(gè)強(qiáng)大的特性,提升了代碼的類(lèi)型安全术唬,使得代碼bug能在編譯階段檢測(cè)得到
包
包能夠幫助你組織構(gòu)造生成的類(lèi)以及其他類(lèi)之間的關(guān)系薪伏。