轉(zhuǎn)載自Github用戶CyC2018的博客
關(guān)鍵字
1. final
數(shù)據(jù)
聲明數(shù)據(jù)為常量同规,可以是編譯時(shí)常量盏浇,也可以是在運(yùn)行時(shí)被初始化后不能被改變的常量嬉愧。
- 對(duì)于基本類型曼氛,final 使數(shù)值不變衙解;
- 對(duì)于引用類型阳柔,final 使引用不變,也就不能引用其它對(duì)象蚓峦,但是被引用的對(duì)象本身是可以修改的舌剂。
方法
聲明方法不能被子類覆蓋。
private 方法隱式地被指定為 final暑椰,如果在子類中定義的方法和基類中的一個(gè) private 方法簽名相同霍转,此時(shí)子類的方法不是覆蓋基類方法,而是重載了一汽。
類
聲明類不允許被繼承避消。
2. static
靜態(tài)變量
靜態(tài)變量在內(nèi)存中只存在一份,只在類第一次實(shí)例化時(shí)初始化一次召夹。
- 靜態(tài)變量: 類所有的實(shí)例都共享靜態(tài)變量岩喷,可以直接通過(guò)類名來(lái)訪問(wèn)它;
- 實(shí)例變量:每創(chuàng)建一個(gè)實(shí)例就會(huì)產(chǎn)生一個(gè)實(shí)例變量监憎,它與該實(shí)例同生共死纱意。
靜態(tài)方法
靜態(tài)方法在類加載的時(shí)候就存在了,它不依賴于任何實(shí)例枫虏,所以 static 方法必須實(shí)現(xiàn)妇穴,也就是說(shuō)它不能是抽象方法(abstract)爬虱。
靜態(tài)語(yǔ)句塊
靜態(tài)語(yǔ)句塊和靜態(tài)變量一樣在類第一次實(shí)例化時(shí)運(yùn)行一次。
初始化順序
靜態(tài)數(shù)據(jù)優(yōu)先于其它數(shù)據(jù)的初始化腾它,靜態(tài)變量和靜態(tài)語(yǔ)句塊哪個(gè)先運(yùn)行取決于它們?cè)诖a中的順序跑筝。
public static String staticField = "靜態(tài)變量";
static {
System.out.println("靜態(tài)語(yǔ)句塊");
}
實(shí)例變量和普通語(yǔ)句塊的初始化在靜態(tài)變量和靜態(tài)語(yǔ)句塊初始化結(jié)束之后。
public String field = "實(shí)例變量";
{
System.out.println("普通語(yǔ)句塊");
}
最后才是構(gòu)造函數(shù)中的數(shù)據(jù)進(jìn)行初始化
public InitialOrderTest() {
System.out.println("構(gòu)造函數(shù)");
}
存在繼承的情況下瞒滴,初始化順序?yàn)椋?/p>
- 父類(靜態(tài)變量曲梗、靜態(tài)語(yǔ)句塊塊)
- 子類(靜態(tài)變量、靜態(tài)語(yǔ)句塊)
- 父類(實(shí)例變量妓忍、普通語(yǔ)句塊)
- 父類(構(gòu)造函數(shù))
- 子類(實(shí)例變量虏两、普通語(yǔ)句塊)
- 子類(構(gòu)造函數(shù))
Object 通用方法
1. 概覽
public final native Class<?> getClass()
public native int hashCode()
public boolean equals(Object obj)
protected native Object clone() throws CloneNotSupportedException
public String toString()
public final native void notify()
public final native void notifyAll()
public final native void wait(long timeout) throws InterruptedException
public final void wait(long timeout, int nanos) throws InterruptedException
public final void wait() throws InterruptedException
protected void finalize() throws Throwable {}
2. clone()
淺拷貝
引用類型引用同一個(gè)對(duì)象。clone() 方法默認(rèn)就是淺拷貝實(shí)現(xiàn)世剖。
<div align="center"> <img src="../pics//d990c0e7-64d1-4ba3-8356-111bc91e53c5.png"/> </div>
深拷貝
可以使用序列化實(shí)現(xiàn)定罢。
<div align="center"> <img src="../pics//2e5620c4-b558-46fe-8f12-00c9dd597a61.png"/> </div>
3. equals()
== 與 equals() 區(qū)別
對(duì)于基本類型,== 就是判斷兩個(gè)值是否相等旁瘫;
對(duì)于引用類型祖凫,== 是判斷兩個(gè)引用是否引用同一個(gè)對(duì)象,而 equals() 是判斷引用的對(duì)象是否等價(jià)酬凳。
等價(jià)性
繼承
1. 訪問(wèn)權(quán)限
Java 中有三個(gè)訪問(wèn)權(quán)限修飾符:private惠况、protected 以及 public,如果不加訪問(wèn)修飾符宁仔,表示包級(jí)可見(jiàn)稠屠。
可以對(duì)類或類中的成員(字段以及方法)加上訪問(wèn)修飾符。成員可見(jiàn)表示其它類可以用成員所在類的對(duì)象訪問(wèn)到該成員翎苫;類可見(jiàn)表示其它類可以用這個(gè)類創(chuàng)建對(duì)象权埠。在理解類的可見(jiàn)性時(shí),可以把類當(dāng)做包中的一個(gè)成員拉队,然后包表示一個(gè)類弊知,那么就可以類比成員的可見(jiàn)性阻逮。
protected 用于修飾成員粱快,表示在繼承體系中成員對(duì)于子類可見(jiàn)。但是這個(gè)訪問(wèn)修飾符對(duì)于類沒(méi)有意義叔扼,因?yàn)榘鼪](méi)有繼承體系事哭。
更詳細(xì)的內(nèi)容:淺析 Java 中的訪問(wèn)權(quán)限控制
2. 抽象類與接口
抽象類和抽象方法都使用 abstract 進(jìn)行聲明。抽象類一般會(huì)包含抽象方法瓜富,但是少數(shù)情況下可以不包含鳍咱,例如 HttpServlet 類,但是抽象方法一定位于抽象類中与柑。抽象類和普通類最大的區(qū)別是谤辜,抽象類不能被實(shí)例化蓄坏,需要繼承抽象類才能實(shí)例化其子類。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
// abstract method
abstract void service(ServletRequest req, ServletResponse res);
void init() {
// Its implementation
}
// other method related to Servlet
}
接口定義了一組方法丑念,但是接口都沒(méi)有方法的實(shí)現(xiàn)涡戳,可以理解為這些方法都是抽象方法。
public interface Externalizable extends Serializable {
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
參數(shù) | 抽象類 | 接口 |
---|---|---|
默認(rèn)的方法實(shí)現(xiàn) | 它可以有默認(rèn)的方法實(shí)現(xiàn) | 接口完全是抽象的脯倚。它根本不存在方法的實(shí)現(xiàn) |
實(shí)現(xiàn) | 子類使用 extends 關(guān)鍵字來(lái)繼承抽象類渔彰。如果子類不是抽象類的話,它需要提供抽象類中所有聲明的方法的實(shí)現(xiàn)推正。 | 子類使用關(guān)鍵字 implements 來(lái)實(shí)現(xiàn)接口恍涂。它需要提供接口中所有聲明的方法的實(shí)現(xiàn) |
構(gòu)造器 | 抽象類可以有構(gòu)造器 | 接口不能有構(gòu)造器 |
與正常 Java 類的區(qū)別 | 除了你不能實(shí)例化抽象類之外,它和普通 Java 類沒(méi)有任何區(qū)別 | 接口是完全不同的類型 |
訪問(wèn)修飾符 | 抽象方法可以有 public植榕、protected 和 default 這些修飾符 | 接口方法默認(rèn)修飾符是 public 再沧。你不可以使用其它修飾符。 |
main 方法 | 抽象方法可以有 main 方法并且我們可以運(yùn)行它 | 接口沒(méi)有 main 方法尊残,因此我們不能運(yùn)行它产园。 |
多繼承 | 抽象方法可以繼承一個(gè)類和實(shí)現(xiàn)多個(gè)接口 | 接口只可以繼承一個(gè)或多個(gè)其它接口 |
速度 | 它比接口速度要快 | 接口是稍微有點(diǎn)慢的,因?yàn)樗枰獣r(shí)間去尋找在類中實(shí)現(xiàn)的方法夜郁。 |
添加新方法 | 如果你往抽象類中添加新的方法什燕,你可以給它提供默認(rèn)的實(shí)現(xiàn)。因此你不需要改變你現(xiàn)在的代碼竞端。 | 如果你往接口中添加方法屎即,那么你必須改變實(shí)現(xiàn)該接口的類。 |
3. super
訪問(wèn)父類的成員
如果子類覆蓋了父類的中某個(gè)方法的實(shí)現(xiàn)事富,那么就可以通過(guò)使用 super 關(guān)鍵字來(lái)引用父類的方法實(shí)現(xiàn)技俐。
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
public class Subclass extends Superclass {
// Overrides printMethod in Superclass
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
訪問(wèn)父類的構(gòu)造函數(shù)
可以使用 super() 函數(shù)訪問(wèn)父類的構(gòu)造函數(shù),從而完成一些初始化的工作统台。
public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) {
super(startCadence, startSpeed, startGear);
seatHeight = startHeight;
}
4. 重載與重寫(xiě)
重寫(xiě)存在于繼承體系中雕擂,指子類實(shí)現(xiàn)了一個(gè)與父類在方法聲明上完全相同的一個(gè)方法;
重載即存在于繼承體系中贱勃,也存在于同一個(gè)類中井赌,指一個(gè)方法與已經(jīng)存在的方法或者父類的方法名稱上相同,但是參數(shù)類型贵扰、個(gè)數(shù)仇穗、順序至少有一個(gè)不同。應(yīng)該注意的是戚绕,返回值不同纹坐,其它都相同不算是重載。
String
1. String, StringBuffer and StringBuilder
是否可變
String 不可變舞丛,StringBuffer 和 StringBuilder 可變耘子。
是否線程安全
String 不可變果漾,因此是線程安全的。
StringBuilder 不是線程安全的谷誓;StringBuffer 是線程安全的跨晴,使用 synchronized 來(lái)同步。
2. String 不可變的原因
可以緩存 hash 值
因?yàn)?String 的 hash 值經(jīng)常被使用片林,例如 String 用做 HashMap 等端盆。不可變的特性可以使得 hash 值也不可變,因此就只需要進(jìn)行一次計(jì)算费封。
String Pool 的需要
如果 String 已經(jīng)被創(chuàng)建過(guò)了焕妙,那么就會(huì)從 String Pool 中取得引用。只有 String 是不可變的弓摘,才可能使用 String Pool焚鹊。
<div align="center"> <img src="../pics//f76067a5-7d5f-4135-9549-8199c77d8f1c.jpg"/> </div>
安全性
String 經(jīng)常作為參數(shù),String 不可變性可以保證參數(shù)不可變韧献。例如在作為網(wǎng)絡(luò)連接參數(shù)的情況下如果 String 是可變的末患,那么在網(wǎng)絡(luò)連接過(guò)程中,String 被改變锤窑,改變 String 對(duì)象的那一方以為現(xiàn)在連接的是其它主機(jī)璧针,而實(shí)際情況卻不一定是。
線程安全
String 不可變性天生具備線程安全渊啰,可以在多個(gè)線程中使用探橱。
3. String.intern()
使用 String.intern() 可以保證所有相同內(nèi)容的字符串變量引用相同的內(nèi)存對(duì)象。
更詳細(xì)的內(nèi)容:揭開(kāi) String.intern() 那神秘的面紗
基本類型與運(yùn)算
1. 包裝類型
八個(gè)基本類型:boolean 1 byte 8 char 16 short 16 int 32 float 32 long 64 double 64
基本類型都有對(duì)應(yīng)的包裝類型绘证,它們之間的賦值使用自動(dòng)裝箱與拆箱完成隧膏。
Integer x = 2; // 裝箱
int y = x; // 拆箱
new Integer(123) 與 Integer.valueOf(123) 的區(qū)別在于,Integer.valueOf(123) 可能會(huì)使用緩存對(duì)象嚷那,因此多次使用 Integer.valueOf(123) 會(huì)取得同一個(gè)對(duì)象的引用胞枕。
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println("a==b? " + (a==b));
Integer c = Integer.valueOf(1);
Integer d = Integer.valueOf(1);
System.out.println("c==d? " + (c==d));
}
a==b? false
c==d? true
valueOf() 方法的實(shí)現(xiàn)比較簡(jiǎn)單,就是先判斷值是否在緩存池中魏宽,如果在的話就直接使用緩存池的內(nèi)容腐泻。
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
The following is the list of primitives stored as immutable objects:
- boolean values true and false
- all byte values
- short values between -128 and 127
- int values between -128 and 127
- char in the range \u0000 to \u007F
自動(dòng)裝箱過(guò)程編譯器會(huì)調(diào)用 valueOf() 方法,因此多個(gè) Integer 對(duì)象使用裝箱來(lái)創(chuàng)建并且值相同湖员,那么就會(huì)引用相同的對(duì)象贫悄,這樣做很顯然是為了節(jié)省內(nèi)存開(kāi)銷瑞驱。
Integer x = 1;
Integer y = 1;
System.out.println(c==d); // true
Differences between new Integer(123), Integer.valueOf(123) and just 123
2. switch
A switch works with the byte, short, char, and int primitive data types. It also works with enumerated types and a few special classes that "wrap" certain primitive types: Character, Byte, Short, and Integer.
In the JDK 7 release, you can use a String object in the expression of a switch statement.
switch 不支持 long娘摔,是因?yàn)?swicth 的設(shè)計(jì)初衷是為那些只需要對(duì)少數(shù)幾個(gè)值進(jìn)行等值判斷,如果值過(guò)于復(fù)雜唤反,那么還是用 if 比較合適凳寺。
switch 使用查找表的方式來(lái)實(shí)現(xiàn)鸭津,JVM 中使用的指令是 lookupswitch。
public static void main(String... args) {
switch (1) {
case 1:
break;
case 2:
break;
}
}
public static void main(java.lang.String[]);
Code:
Stack=1, Locals=1, Args_size=1
0: iconst_1
1: lookupswitch{ //2
1: 28;
2: 31;
default: 31 }
28: goto 31
31: return
反射
每個(gè)類都有一個(gè) Class 對(duì)象肠缨,包含了與類有關(guān)的信息逆趋。當(dāng)編譯一個(gè)新類時(shí),會(huì)產(chǎn)生一個(gè)同名的 .class 文件晒奕,該文件內(nèi)容保存著 Class 對(duì)象闻书。
類加載相當(dāng)于 Class 對(duì)象的加載。類在第一次使用時(shí)才動(dòng)態(tài)加載到 JVM 中脑慧,可以使用 Class.forName('com.mysql.jdbc.Driver.class') 這種方式來(lái)控制類的加載魄眉,該方法會(huì)返回一個(gè) Class 對(duì)象。
反射可以提供運(yùn)行時(shí)的類信息闷袒,并且這個(gè)類可以在運(yùn)行時(shí)才加載進(jìn)來(lái)坑律,甚至在編譯時(shí)期該類的 .class 不存在也可以加載進(jìn)來(lái)。
Class 和 java.lang.reflect 一起對(duì)反射提供了支持囊骤,java.lang.reflect 類庫(kù)包含了 Field 晃择、Method 以及 Constructor 類∫参铮可以使用 get() 和 set() 方法讀取和修改 Field 對(duì)象關(guān)聯(lián)的字段宫屠,可以使用 invoke() 方法調(diào)用與 Method 對(duì)象關(guān)聯(lián)的方法,可以用 Constructor 創(chuàng)建新的對(duì)象滑蚯。
IDE 使用反射機(jī)制獲取類的信息激况,在使用一個(gè)類的對(duì)象時(shí),能夠把類的字段膘魄、方法和構(gòu)造函數(shù)等信息列出來(lái)供用戶選擇乌逐。
更詳細(xì)的內(nèi)容:深入解析 Java 反射(1)- 基礎(chǔ)
Advantages of Using Reflection:
- Extensibility Features : An application may make use of external, user-defined classes by creating instances of extensibility objects using their fully-qualified names.
- Class Browsers and Visual Development Environments : A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code.
- Debuggers and Test Tools : Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a discoverable set APIs defined on a class, to insure a high level of code coverage in a test suite.
Drawbacks of Reflection
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.
- Performance Overhead : Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
- Security Restrictions : Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.
- Exposure of Internals :Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
異常
Throwable 可以用來(lái)表示任何可以作為異常拋出的類,分為兩種: Error 和 Exception创葡,其中 Error 用來(lái)表示編譯時(shí)系統(tǒng)錯(cuò)誤浙踢。
Exception 分為兩種: 受檢異常 和 非受檢異常。受檢異常需要用 try...catch... 語(yǔ)句捕獲并進(jìn)行處理灿渴,并且可以從異常中恢復(fù)洛波;非受檢異常是程序運(yùn)行時(shí)錯(cuò)誤,例如除 0 會(huì)引發(fā) Arithmetic Exception骚露,此時(shí)程序奔潰并且無(wú)法恢復(fù)蹬挤。
<div align="center"> <img src="../pics//48f8f98e-8dfd-450d-8b5b-df4688f0d377.jpg"/> </div>
更詳細(xì)的內(nèi)容:
泛型
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
更詳細(xì)的內(nèi)容:
注解
Java注解是附加在代碼中的一些元信息,用于一些工具在編譯棘幸、運(yùn)行時(shí)進(jìn)行解析和使用焰扳,起到說(shuō)明、配置的功能。注解不會(huì)也不能影響代碼的實(shí)際邏輯吨悍,僅僅起到輔助性的作用扫茅。
更多詳細(xì)內(nèi)容:注解Annotation實(shí)現(xiàn)原理與自定義注解例子
特性
1. 三大特性
2. Java 各版本的新特性
New highlights in Java SE 8
- Lambda Expressions
- Pipelines and Streams
- Date and Time API
- Default Methods
- Type Annotations
- Nashhorn JavaScript Engine
- Concurrent Accumulators
- Parallel operations
- PermGen Error Removed
New highlights in Java SE 7
- Strings in Switch Statement
- Type Inference for Generic Instance Creation
- Multiple Exception Handling
- Support for Dynamic Languages
- Try with Resources
- Java nio Package
- Binary Literals, Underscore in literals
- Diamond Syntax
更詳細(xì)的內(nèi)容:Java 8 特性
3. Java 與 C++ 的區(qū)別
Java 是純粹的面向?qū)ο笳Z(yǔ)言,所有的對(duì)象都繼承自 java.lang.Object驱证,C++ 為了兼容 C 即支持面向?qū)ο笠仓С置嫦蜻^(guò)程躏仇。
比較詳細(xì)的內(nèi)容:
Java | C++ |
---|---|
Java does not support pointers, templates, unions, operator overloading, structures etc. The Java language promoters initially said "No pointers!", but when many programmers questioned how you can work without pointers, the promoters began saying "Restricted pointers." Java supports what it calls "references". References act a lot like pointers in C++ languages but you cannot perform arithmetic on pointers in Java. References have types, and they're type-safe. These references cannot be interpreted as raw address and unsafe conversion is not allowed. | C++ supports structures, unions, templates, operator overloading, pointers and pointer arithmetic. |
Java support automatic garbage collection. It does not support destructors as C++ does. | C++ support destructors, which is automatically invoked when the object is destroyed. |
Java does not support conditional compilation and inclusion. | Conditional inclusion (#ifdef #ifndef type) is one of the main features of C++. |
Java has built in support for threads. In Java, there is a Thread class that you inherit to create a new thread and override the run() method. |
C++ has no built in support for threads. C++ relies on non-standard third-party libraries for thread support. |
Java does not support default arguments. There is no scope resolution operator (::) in Java. The method definitions must always occur within a class, so there is no need for scope resolution there either. | C++ supports default arguments. C++ has scope resolution operator (::) which is used to to define a method outside a class and to access a global variable within from the scope where a local variable also exists with the same name. |
There is no goto statement in Java. The keywords const and goto are reserved, even though they are not used. |
C++ has goto statement. However, it is not considered good practice to use of goto statement. |
Java doesn't provide multiple inheritance, at least not in the same sense that C++ does. | C++ does support multiple inheritance. The keyword virtual is used to resolve ambiguities during multiple inheritance if there is any. |
Exception handling in Java is different because there are no destructors. Also, in Java, try/catch must be defined if the function declares that it may throw an exception. | While in C++, you may not include the try/catch even if the function throws an exception. |
Java has method overloading, but no operator overloading. The String class does use the + and += operators to concatenate strings and String expressions use automatic type conversion, but that's a special built-in case. |
C++ supports both method overloading and operator overloading. |
Java has built-in support for documentation comments (/** ... */ ); therefore, Java source files can contain their own documentation, which is read by a separate tool usually javadoc and reformatted into HTML. This helps keeping documentation maintained in easy way. |
C++ does not support documentation comments. |
Java is interpreted for the most part and hence platform independent. | C++ generates object code and the same code may not run on different platforms. |
4. JRE or JDK
- JRE is the JVM program, Java application need to run on JRE.
- JDK is a superset of JRE, JRE + tools for developing java programs. e.g, it provides the compiler "javac"